whistle
Version:
HTTP, HTTP2, HTTPS, Websocket debugging proxy
95 lines (88 loc) • 2.64 kB
JavaScript
var Transform = require('pipestream').Transform;
var util = require('util');
var LENGTH = 5120;
var slice = [].slice;
var SUB_MATCH_RE = /(^|\\{0,2})?(\$\$?(b)?[&\d])/g;
var ALL_RE = /^\/\.[*+]\/g?i?g?$/;
var MAX_SUB_MATCH_LEN = 512;
function ReplacePatternTransform(pattern, value, isSSE) {
Transform.call(this);
this._pattern = pattern;
this._replaceAll = ALL_RE.test(pattern);
this._value = value == null ? '' : value + '';
this._isSSE = isSSE;
this._rest = '';
}
util.inherits(ReplacePatternTransform, Transform);
var proto = ReplacePatternTransform.prototype;
proto._transform = function (chunk, _, callback) {
var value = this._value;
if (this._replaceAll) {
this._value = '';
chunk = value;
} else if (chunk != null) {
chunk = this._rest + chunk;
var index = 0;
var len = chunk.length - MAX_SUB_MATCH_LEN;
var result = chunk.replace(this._pattern, function () {
var matcher = arguments[0];
var matcherLen = matcher.length;
var i = arguments[arguments.length - 2] + matcherLen;
var subLen = i - len;
if (subLen >= 0 && matcherLen <= LENGTH - subLen) {
return matcher;
}
index = i;
return replacePattern(value, arguments);
});
index = Math.max(index, chunk.length - LENGTH);
if (this._isSSE) {
var endIndex = chunk.lastIndexOf('\n\n');
if (endIndex !== -1) {
index = Math.max(endIndex + 2, index);
}
}
this._rest = chunk.substring(index);
chunk = result.substring(0, result.length - this._rest.length);
} else if (this._rest) {
chunk = this._rest.replace(this._pattern, function () {
return replacePattern(value, arguments);
});
}
callback(null, chunk);
};
function getSubMatchers(args) {
args = slice.call(args);
return args.slice(0, -2);
}
function replacePattern(replacement, args, vals) {
var arr = args && args.length ? getSubMatchers(args) : args;
return replacement
? replacement.replace(SUB_MATCH_RE, function (_, $1, $2, $3) {
var list = $3 ? vals : arr;
if (!list) {
return $1 + $2;
}
if ($1 === '\\') {
return $2;
}
if ($1 === '\\\\') {
$1 = '\\';
}
var encode = $2[1] === '$';
$2 = $2.substring((encode ? 2 : 1) + ($3 ? 1 : 0));
if ($2 === '&') {
$2 = 0;
}
$2 = list[$2] || '';
if (encode && $2) {
try {
$2 = encodeURIComponent($2);
} catch (e) {}
}
return ($1 || '') + $2;
})
: '';
}
ReplacePatternTransform.replacePattern = replacePattern;
module.exports = ReplacePatternTransform;