-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Brotli transparent support #443
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,9 @@ | |
"mocha": true, | ||
}, | ||
"globals": {}, | ||
"parserOptions": { "ecmaVersion": 8 }, | ||
"parserOptions": { | ||
"ecmaVersion": 8 | ||
}, | ||
"rules": { | ||
"camelcase": [ | ||
2, | ||
|
@@ -21,8 +23,13 @@ | |
2, | ||
{ | ||
"ArrayExpression": 1, | ||
"CallExpression": {"arguments": 1}, | ||
"FunctionDeclaration": {"body": 1, "parameters": 2}, | ||
"CallExpression": { | ||
"arguments": 1 | ||
}, | ||
"FunctionDeclaration": { | ||
"body": 1, | ||
"parameters": 2 | ||
}, | ||
"MemberExpression": 1, | ||
"ObjectExpression": 1, | ||
"SwitchCase": 1 | ||
|
@@ -61,10 +68,13 @@ | |
"no-undef": 2, | ||
"no-unused-vars": 2, | ||
"no-eq-null": 2, | ||
"space-before-function-paren": ["error", { | ||
"space-before-function-paren": [ | ||
"error", | ||
{ | ||
"anonymous": "always", | ||
"named": "never" | ||
}], | ||
} | ||
], | ||
"no-empty": [ | ||
2, | ||
{ | ||
|
@@ -150,7 +160,10 @@ | |
], | ||
"lines-around-comment": [ | ||
2, | ||
{ "afterLineComment": true, "allowBlockEnd": true } | ||
{ | ||
"afterLineComment": false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've changed this because the existing code wasn't following this rule (and also I think it's fairly common to have no empty line between a single line comment and the next line it explains) |
||
"allowBlockEnd": true | ||
} | ||
], | ||
"semi": [ | ||
2, | ||
|
@@ -165,4 +178,4 @@ | |
"unix" | ||
] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,31 +3,54 @@ | |
var as = require('../../lib/as.js'); | ||
var debug = require('debug')('express-http-proxy'); | ||
var zlib = require('zlib'); | ||
var brotli = require('iltorb'); | ||
|
||
function isResGzipped(res) { | ||
return res.headers['content-encoding'] === 'gzip'; | ||
var ENCODING = { | ||
gzip: 'gzip', | ||
brotli: 'br' | ||
}; | ||
|
||
function isResEncoded(res, encoding) { | ||
return res.headers['content-encoding'] === encoding; | ||
} | ||
|
||
function zipOrUnzip(method) { | ||
return function(rspData, res) { | ||
const id = data => Promise.resolve(data); | ||
|
||
function createGzipHandler(method) { | ||
return function (data) { | ||
return new Promise(function (resolve, reject) { | ||
if (isResGzipped(res) && rspData.length) { | ||
zlib[method](rspData, function(err, buffer) { | ||
if(err) { | ||
reject(err); | ||
} else { | ||
resolve(buffer); | ||
} | ||
}); | ||
} else { | ||
resolve(rspData); | ||
if (!data || !data.length) { | ||
return resolve(data); | ||
} | ||
zlib[method](data, function (err, buffer) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(buffer); | ||
} | ||
}); | ||
|
||
}); | ||
}; | ||
} | ||
|
||
var maybeUnzipPromise = zipOrUnzip('gunzip'); | ||
var maybeZipPromise = zipOrUnzip('gzip'); | ||
function createEncodingHandler(res) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Obviously, this is the central part |
||
if (isResEncoded(res, ENCODING.gzip)) { | ||
return { | ||
decode: createGzipHandler('gunzip'), | ||
encode: createGzipHandler('gzip') | ||
}; | ||
} else if (isResEncoded(res, ENCODING.brotli)) { | ||
return { | ||
decode: brotli.decompress, | ||
encode: brotli.compress | ||
}; | ||
} | ||
return { | ||
decode: id, | ||
encode: id | ||
}; | ||
} | ||
|
||
function verifyBuffer(rspd, reject) { | ||
if (!Buffer.isBuffer(rspd)) { | ||
|
@@ -37,11 +60,11 @@ function verifyBuffer(rspd, reject) { | |
|
||
function updateHeaders(res, rspdBefore, rspdAfter, reject) { | ||
if (!res.headersSent) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Automatically formatted, it looks like 4 spaces were used |
||
res.set('content-length', rspdAfter.length); | ||
res.set('content-length', rspdAfter.length); | ||
} else if (rspdAfter.length !== rspdBefore.length) { | ||
var error = '"Content-Length" is already sent,' + | ||
'the length of response data can not be changed'; | ||
return reject(new Error(error)); | ||
var error = '"Content-Length" is already sent, ' + | ||
'the length of response data can not be changed'; | ||
return reject(new Error(error)); | ||
} | ||
} | ||
|
||
|
@@ -52,31 +75,32 @@ function decorateProxyResBody(container) { | |
return Promise.resolve(container); | ||
} | ||
|
||
var proxyResDataPromise = maybeUnzipPromise(container.proxy.resData, container.proxy.res); | ||
var proxyRes = container.proxy.res; | ||
var req = container.user.req; | ||
var res = container.user.res; | ||
var originalResData; | ||
var originalResData; | ||
|
||
if (res.statusCode === 304) { | ||
debug('Skipping userResDecorator on response 304'); | ||
return Promise.resolve(container); | ||
} | ||
|
||
return proxyResDataPromise | ||
.then(function(proxyResData){ | ||
const encodingHandler = createEncodingHandler(container.proxy.res); | ||
|
||
return encodingHandler.decode(container.proxy.resData) | ||
.then(function (proxyResData) { | ||
originalResData = proxyResData; | ||
return resolverFn(proxyRes, proxyResData, req, res); | ||
}) | ||
.then(function(modifiedResData) { | ||
return new Promise(function(resolve, reject) { | ||
.then(function (modifiedResData) { | ||
return new Promise(function (resolve, reject) { | ||
var rspd = as.buffer(modifiedResData, container.options); | ||
verifyBuffer(rspd, reject); | ||
updateHeaders(res, originalResData, rspd, reject); | ||
maybeZipPromise(rspd, container.proxy.res).then(function(buffer) { | ||
encodingHandler.encode(rspd).then(function (buffer) { | ||
container.proxy.resData = buffer; | ||
resolve(container); | ||
}).catch(function(error){ | ||
}).catch(function (error) { | ||
reject(error); | ||
}); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,9 @@ function asBuffer(body, options) { | |
if (Buffer.isBuffer(body)) { | ||
ret = body; | ||
} else if (typeof body === 'object') { | ||
ret = new Buffer(JSON.stringify(body), options.reqBodyEncoding); | ||
ret = Buffer.from(JSON.stringify(body), options.reqBodyEncoding); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Buffer constructor is deprecated and the |
||
} else if (typeof body === 'string') { | ||
ret = new Buffer(body, options.reqBodyEncoding); | ||
ret = Buffer.from(body, options.reqBodyEncoding); | ||
} | ||
return ret; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All formatting changes here are automated by the ESlint plugin in my editor