string-replace-middleware
Advanced tools
Comparing version 1.0.2 to 1.1.0
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
48949
470
9