villadora / express-http-proxy

Proxy middleware for express/connect
Other
1.22k stars 235 forks source link

Support for brotli #360

Open aczekajski opened 6 years ago

aczekajski commented 6 years ago

Currently, if remote server returns response encoded with brotli algorithm (and sends header content-encoding set to br), the library does nothing to the response which is passed to userResDecorator. In effect, user must manually decompress it and compress it back before returning it from the callback function.

How about adding suport for brotli into express-http-proxy?

Compressing and decompressing with https://www.npmjs.com/package/iltorb package is as simple as doing:

var brotli = require('iltorb');
/* ... */
var decompressedBuffer = brotli.decompressSync(proxyResData);
var compressedBuffer = brotli.compressSync(decompressedBuffer);

I can propose a PR with added support if you approve it.

emirotin commented 4 years ago

I can send such PR as well @villadora if you're up to cooperate and get it reviewed/merged. It's an important feature to have because Brotli is getting its popularity and normally things work transparently (the same way this lib does work for gzip)

monkpow commented 4 years ago

I'd be happy to accept a PR for Brotli support that includes tests.

emirotin commented 4 years ago

@monkpow https://github.com/villadora/express-http-proxy/pull/443

Domiii commented 4 years ago

Workaround while we are waiting for @monkpow to merge @emirotin's PR 👯‍♂️

 /**
  * @see https://www.npmjs.com/package/express-http-proxy#proxyreqoptdecorator--supports-promise-form
  * @see https://github.com/villadora/express-http-proxy/blob/master/app/steps/decorateProxyReqOpts.js
  */
proxyReqOptDecorator(proxyReqOpts, srcReq) {
  const BR = 'br';
  const acceptedEncodings = getHeader(proxyReqOpts.headers, 'accept-encoding')?.split(/, ?/);
  if (acceptedEncodings && acceptedEncodings.includes(BR)) {
    pull(acceptedEncodings, BR);
    proxyReqOpts.headers['accept-encoding'] = acceptedEncodings.join(', ');
  }
  return proxyReqOpts;
}

// ...

// utilities

/**
 * NOTE: headers are case insensitive.
 * 
 * @see https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive
 */
export function getHeader(headers, headerName) {
  headerName = headerName.toLowerCase();
  const key = Object.keys(headers).find(h => h.toLowerCase() === headerName);
  return key && headers[key] || null;
}