Socket
Socket
Sign inDemoInstall

string-replace-middleware

Package Overview
Dependencies
2
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.2 to 1.1.0

3

dist/index.d.ts
import { NextFunction, Request, Response } from 'express';
export declare type Options = Record<'contentTypeFilterRegexp', RegExp>;
export declare const stringReplace: (replacements: Record<string, string>, options?: Partial<Options>) => (_req: Request, res: Response, next: NextFunction) => void;
export declare type ReplaceFunction = (req: Request, res: Response) => string;
export declare const stringReplace: (replacements: Record<string, string | ReplaceFunction>, options?: Partial<Options>) => (req: Request, originalResponse: Response, next: NextFunction) => void;

@@ -12,6 +12,5 @@ 'use strict';

function _extends() {
_extends = Object.assign || function (target) {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {

@@ -23,6 +22,4 @@ if (Object.prototype.hasOwnProperty.call(source, key)) {

}
return target;
};
return _extends.apply(this, arguments);

@@ -35,3 +32,2 @@ }

};
function buildReplacers(replacements, opts) {

@@ -47,3 +43,2 @@ return Object.keys(replacements).sort(function (a, b) {

}
function getMaxSearchLength(replacements) {

@@ -54,3 +49,2 @@ return Object.keys(replacements).reduce(function (acc, search) {

}
function StringReplaceStream(replacements, options) {

@@ -60,9 +54,6 @@ if (options === void 0) {

}
var opts = _extends({}, defaultOptions, options);
var replacers = buildReplacers(replacements, opts);
var maxSearchLength = getMaxSearchLength(replacements);
var tail = '';
var replaceSlidingWindow = function replaceSlidingWindow(haystack, replacers, replaceBefore) {

@@ -84,3 +75,2 @@ /**

};
var transform = function transform(buf, _enc, cb) {

@@ -90,3 +80,2 @@ var replaceBefore = maxSearchLength * 2;

var body = '';
if (haystack.length < maxSearchLength * 3 - 2) {

@@ -97,5 +86,3 @@ tail = haystack;

}
var _replaceSlidingWindow = replaceSlidingWindow(haystack, replacers, replaceBefore);
body = _replaceSlidingWindow[0];

@@ -105,3 +92,2 @@ tail = _replaceSlidingWindow[1];

};
var flush = function flush(cb) {

@@ -112,3 +98,2 @@ if (!tail) {

}
var body = replacers.reduce(function (acc, replacer) {

@@ -119,3 +104,2 @@ return acc.replace(replacer.matcher, replacer.replace);

};
return new stream.Transform({

@@ -134,18 +118,36 @@ transform: transform,

}
var opts = _extends({}, defaultOptions$1, options);
return function (_req, res, next) {
hijackResponse(res, function (err, res) {
var contentType = res.get('content-type');
// Split string and function replacements so we don't have to process them on every request
var stringReplacements = {};
var functionReplacements = {};
Object.keys(replacements).forEach(function (key, _index) {
var replacement = replacements[key];
if (typeof replacement === 'function') {
functionReplacements[key] = replacement;
} else {
stringReplacements[key] = replacement;
}
});
var hasFunctionReplacements = Object.keys(functionReplacements).length > 0;
return function (req, originalResponse, next) {
hijackResponse(originalResponse, function (err, res) {
var contentType = res.get('content-type') || '';
if (opts.contentTypeFilterRegexp.test(contentType)) {
if (err) {
res.unhijack(); // Make the original res object work again
return next(err);
}
res.removeHeader('content-length');
res.pipe(StringReplaceStream(replacements)).pipe(res);
var scopedReplacements;
if (hasFunctionReplacements) {
// If we have dynamic replacements, calculate for this request
scopedReplacements = _extends({}, stringReplacements);
Object.keys(functionReplacements).forEach(function (key, _index) {
scopedReplacements[key] = functionReplacements[key](req, res);
});
} else {
// No dynamic replacements, safe to share the global
scopedReplacements = stringReplacements;
}
res.pipe(StringReplaceStream(scopedReplacements)).pipe(res);
} else {

@@ -152,0 +154,0 @@ return res.unhijack();

@@ -1,2 +0,2 @@

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var n=e(require("hijackresponse")),t=require("stream"),r=e(require("escape-string-regexp"));function i(){return(i=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e}).apply(this,arguments)}var c={encoding:"utf8",ignoreCase:!0},o={contentTypeFilterRegexp:/^text\/|^application\/json$|^application\/xml$/},u=function(e,u){void 0===u&&(u={});var a=i({},o,u);return function(o,u,l){n(u,(function(n,o){var u=o.get("content-type");return a.contentTypeFilterRegexp.test(u)?n?(o.unhijack(),l(n)):(o.removeHeader("content-length"),void o.pipe(function(e,n){void 0===n&&(n={});var o=i({},c,n),u=function(e,n){return Object.keys(e).sort((function(e,n){return n.length-e.length})).map((function(t){return{matcher:new RegExp(r(t),n.ignoreCase?"gmi":"gm"),replace:e[t]}}))}(e,o),a=function(e){return Object.keys(e).reduce((function(e,n){return Math.max(e,n.length)}),0)}(e),l="";return new t.Transform({transform:function(e,n,t){var r=2*a,i=l+e.toString(o.encoding);if(i.length<3*a-2)return l=i,void t(null,"");var c=function(e,n,t){var r=e;return n.forEach((function(e){r=r.slice(0,t).replace(e.matcher,e.replace)+r.slice(t)})),[r.slice(0,t),r.slice(t)]}(i,u,r);l=c[1],t(null,c[0])},flush:function(e){l?e(null,u.reduce((function(e,n){return e.replace(n.matcher,n.replace)}),l)):e()}})}(e)).pipe(o)):o.unhijack()})),l()}};module.exports=u,module.exports.stringReplace=u,exports.stringReplace=u;
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var n=e(require("hijackresponse")),t=require("stream"),r=e(require("escape-string-regexp"));function c(){return(c=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e}).apply(this,arguments)}var i={encoding:"utf8",ignoreCase:!0},o={contentTypeFilterRegexp:/^text\/|^application\/json$|^application\/xml$/},u=function(e,u){void 0===u&&(u={});var a=c({},o,u),l={},p={};Object.keys(e).forEach((function(n,t){var r=e[n];"function"==typeof r?p[n]=r:l[n]=r}));var s=Object.keys(p).length>0;return function(e,o,u){n(o,(function(n,o){var f,g=o.get("content-type")||"";return a.contentTypeFilterRegexp.test(g)?n?(o.unhijack(),u(n)):(o.removeHeader("content-length"),s?(f=c({},l),Object.keys(p).forEach((function(n,t){f[n]=p[n](e,o)}))):f=l,void o.pipe(function(e,n){void 0===n&&(n={});var o=c({},i,n),u=function(e,n){return Object.keys(e).sort((function(e,n){return n.length-e.length})).map((function(t){return{matcher:new RegExp(r(t),n.ignoreCase?"gmi":"gm"),replace:e[t]}}))}(e,o),a=function(e){return Object.keys(e).reduce((function(e,n){return Math.max(e,n.length)}),0)}(e),l="";return new t.Transform({transform:function(e,n,t){var r=2*a,c=l+e.toString(o.encoding);if(c.length<3*a-2)return l=c,void t(null,"");var i=function(e,n,t){var r=e;return n.forEach((function(e){r=r.slice(0,t).replace(e.matcher,e.replace)+r.slice(t)})),[r.slice(0,t),r.slice(t)]}(c,u,r);l=i[1],t(null,i[0])},flush:function(e){l?e(null,u.reduce((function(e,n){return e.replace(n.matcher,n.replace)}),l)):e()}})}(f)).pipe(o)):o.unhijack()})),u()}};module.exports=u,module.exports.stringReplace=u,exports.stringReplace=u;
//# sourceMappingURL=string-replace-middleware.cjs.production.min.js.map

@@ -6,6 +6,5 @@ import hijackResponse from 'hijackresponse';

function _extends() {
_extends = Object.assign || function (target) {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {

@@ -17,6 +16,4 @@ if (Object.prototype.hasOwnProperty.call(source, key)) {

}
return target;
};
return _extends.apply(this, arguments);

@@ -29,3 +26,2 @@ }

};
function buildReplacers(replacements, opts) {

@@ -41,3 +37,2 @@ return Object.keys(replacements).sort(function (a, b) {

}
function getMaxSearchLength(replacements) {

@@ -48,3 +43,2 @@ return Object.keys(replacements).reduce(function (acc, search) {

}
function StringReplaceStream(replacements, options) {

@@ -54,9 +48,6 @@ if (options === void 0) {

}
var opts = _extends({}, defaultOptions, options);
var replacers = buildReplacers(replacements, opts);
var maxSearchLength = getMaxSearchLength(replacements);
var tail = '';
var replaceSlidingWindow = function replaceSlidingWindow(haystack, replacers, replaceBefore) {

@@ -78,3 +69,2 @@ /**

};
var transform = function transform(buf, _enc, cb) {

@@ -84,3 +74,2 @@ var replaceBefore = maxSearchLength * 2;

var body = '';
if (haystack.length < maxSearchLength * 3 - 2) {

@@ -91,5 +80,3 @@ tail = haystack;

}
var _replaceSlidingWindow = replaceSlidingWindow(haystack, replacers, replaceBefore);
body = _replaceSlidingWindow[0];

@@ -99,3 +86,2 @@ tail = _replaceSlidingWindow[1];

};
var flush = function flush(cb) {

@@ -106,3 +92,2 @@ if (!tail) {

}
var body = replacers.reduce(function (acc, replacer) {

@@ -113,3 +98,2 @@ return acc.replace(replacer.matcher, replacer.replace);

};
return new Transform({

@@ -128,18 +112,36 @@ transform: transform,

}
var opts = _extends({}, defaultOptions$1, options);
return function (_req, res, next) {
hijackResponse(res, function (err, res) {
var contentType = res.get('content-type');
// Split string and function replacements so we don't have to process them on every request
var stringReplacements = {};
var functionReplacements = {};
Object.keys(replacements).forEach(function (key, _index) {
var replacement = replacements[key];
if (typeof replacement === 'function') {
functionReplacements[key] = replacement;
} else {
stringReplacements[key] = replacement;
}
});
var hasFunctionReplacements = Object.keys(functionReplacements).length > 0;
return function (req, originalResponse, next) {
hijackResponse(originalResponse, function (err, res) {
var contentType = res.get('content-type') || '';
if (opts.contentTypeFilterRegexp.test(contentType)) {
if (err) {
res.unhijack(); // Make the original res object work again
return next(err);
}
res.removeHeader('content-length');
res.pipe(StringReplaceStream(replacements)).pipe(res);
var scopedReplacements;
if (hasFunctionReplacements) {
// If we have dynamic replacements, calculate for this request
scopedReplacements = _extends({}, stringReplacements);
Object.keys(functionReplacements).forEach(function (key, _index) {
scopedReplacements[key] = functionReplacements[key](req, res);
});
} else {
// No dynamic replacements, safe to share the global
scopedReplacements = stringReplacements;
}
res.pipe(StringReplaceStream(scopedReplacements)).pipe(res);
} else {

@@ -146,0 +148,0 @@ return res.unhijack();

{
"name": "string-replace-middleware",
"version": "1.0.2",
"version": "1.1.0",
"description": "Express middleware to replace strings in response stream on the fly",

@@ -30,3 +30,4 @@ "license": "MIT",

"devDependencies": {
"@types/express": "^4.17.7",
"@types/express": "4.17.13",
"@types/express-serve-static-core": "4.17.28",
"@types/supertest": "^2.0.10",

@@ -40,2 +41,5 @@ "express": "^4.17.1",

},
"resolutions": {
"@types/express-serve-static-core": "4.17.28"
},
"husky": {

@@ -42,0 +46,0 @@ "hooks": {

@@ -7,2 +7,4 @@ import { NextFunction, Request, Response } from 'express';

export type ReplaceFunction = (req: Request, res: Response) => string;
const defaultOptions: Options = {

@@ -13,9 +15,23 @@ contentTypeFilterRegexp: /^text\/|^application\/json$|^application\/xml$/,

export const stringReplace = (
replacements: Record<string, string>,
replacements: Record<string, string | ReplaceFunction>,
options: Partial<Options> = {}
) => {
const opts = { ...defaultOptions, ...options };
return (_req: Request, res: Response, next: NextFunction) => {
hijackResponse(res, function(err, res) {
const contentType = res.get('content-type');
// Split string and function replacements so we don't have to process them on every request
const stringReplacements: Record<string, string> = {};
const functionReplacements: Record<string, ReplaceFunction> = {};
Object.keys(replacements).forEach(function(key, _index) {
const replacement = replacements[key];
if (typeof replacement === 'function') {
functionReplacements[key] = replacement;
} else {
stringReplacements[key] = replacement;
}
});
const hasFunctionReplacements = Object.keys(functionReplacements).length > 0;
return (req: Request, originalResponse: Response, next: NextFunction) => {
hijackResponse(originalResponse, function(err, res) {
const contentType = res.get('content-type') || '';
if (opts.contentTypeFilterRegexp.test(contentType)) {

@@ -27,3 +43,16 @@ if (err) {

res.removeHeader('content-length');
res.pipe(stringReplaceStream(replacements)).pipe(res);
let scopedReplacements: Record<string, string>;
if (hasFunctionReplacements) {
// If we have dynamic replacements, calculate for this request
scopedReplacements = { ...stringReplacements };
Object.keys(functionReplacements).forEach(function(key, _index) {
scopedReplacements[key] = functionReplacements[key](req, res);
});
} else {
// No dynamic replacements, safe to share the global
scopedReplacements = stringReplacements;
}
res.pipe(stringReplaceStream(scopedReplacements)).pipe(res);
} else {

@@ -38,2 +67,2 @@ return res.unhijack();

module.exports = stringReplace;
module.exports.stringReplace = stringReplace;
module.exports.stringReplace = stringReplace;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc