koa-even-better-http-proxy
Version:
http proxy middleware for Koa
63 lines (53 loc) • 2.02 kB
JavaScript
import zlib from 'zlib';
import { asBuffer } from '../../lib/as';
const isResGzipped = (rspData, res) =>
rspData?.byteLength > 0 && res.headers['content-encoding'] === 'gzip';
const zipOrUnzip = (method) => (rspData, res) =>
isResGzipped(rspData, res) ? zlib[method](rspData) : rspData;
const maybeUnzipResponse = zipOrUnzip('gunzipSync');
const maybeZipResponse = zipOrUnzip('gzipSync');
const verifyBuffer = (rspd, reject) => {
if (Buffer.isBuffer(rspd)) return null;
return reject(
new Error('userResDecorator should return string or buffer as data')
);
};
const updateHeaders = (ctx, rspdBefore, rspdAfter, reject) => {
if (!ctx.headerSent) {
ctx.set('content-length', rspdAfter.length);
} else if (rspdAfter.length !== rspdBefore.length) {
const error =
'"Content-Length" is already sent,' +
'the length of response data can not be changed';
reject(new Error(error));
}
};
export default (container) => {
if (container.user.ctx.status === 504) {
return Promise.resolve(container);
}
const resolverFn = container.options.userResDecorator;
if (!resolverFn) {
return Promise.resolve(container);
}
const proxyResData = maybeUnzipResponse(
container.proxy.resData,
container.proxy.res
);
const proxyRes = container.proxy.res;
const { ctx } = container.user;
return Promise.resolve(resolverFn(proxyRes, proxyResData, ctx)).then(
(modifiedResData) =>
new Promise((resolve, reject) => {
const rspd = asBuffer(modifiedResData, container.options);
verifyBuffer(rspd, reject);
updateHeaders(ctx, proxyResData, rspd, reject);
// eslint-disable-next-line no-param-reassign
container.proxy.resData = maybeZipResponse(
rspd,
container.proxy.res
);
resolve(container);
})
);
};