Http-proxy-middleware: Can pathRewrite option be made use of to adjust the Location header in redirects (301, 302, 307, 308)

Created on 22 Dec 2016  路  10Comments  路  Source: chimurai/http-proxy-middleware

Expected behavior

I access my app's UI at http://localhost:9000 and use webpack-dev-server/http-proxy-middleware combo to proxy requests to http://localhost:9000/api/ to http:///mytool-api/*

Now the API server has started redirecting requests for /mytool-api/foo to /mytool-api/bar using HTTP redirect. It sends '/mytool-api/bar' in Location header of response.

How do I make the proxy middleware change the Location header from /mytool-api/bar to /api/bar (or) handle the redirect and return the response from the URL redirected to.

Actual behavior

At the moment the Location header is left as is causing my UI to hit http://localhost:9000/mytool-api/bar which results in 404.

I can get the protocol, hostname & port in Location header corrected/replaced by using http-proxy options but I don't see any option to replace /mytool-api in the path with /api

  autoRewrite: true,
  protocolRewrite: 'http'

(What I want is kind of similar to how Apache proxy modules ProxyPassReverse works https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassreverse)

duplicate enhancement

Most helpful comment

Thanks.... After a few attempts... I got it working with this -

var onProxyRes = function(proxyRes, req, res) {
    //Handling api server redirects
    if ([307, 308].indexOf(proxyRes.statusCode) > -1 && proxyRes.headers.location) {
        var redirect = proxyRes.headers.location;
        logger.warn('Received code ' + proxyRes.statusCode + ' from API Server for URL - ' + redirect);
        redirect = redirect.replace('http://localhost:8080/v1', '/api');
        logger.warn('Manipulating header location and redirecting to - ' + redirect);
        proxyRes.headers.location = redirect;
    }
};

Thanks!

All 10 comments

Hi, it's currently not supported. (related to issue #138)

Any thoughts on the interface/api usage to support this? Given the fact pathRewrite can be used in different ways...

Thanks, I understand because pathRewrite is a function and as well a regex this makes it tricky. I will think about this and suggest probable approach. On a quick thought though

  • adding pathRewriteReverse which is a function like ({pathFromLocationHeader, pathPassedToPathRewrite, reqPassedToPathRewrite, matchingPathRewriteRegex, pathRewriteRegexCaptureGroups}) => { ... return <newLocation> }.

  • (or) adding pathRewriteStrings (renamed to something better) which will be similar to pathRewrite except instead of regex it will be a string supposed to match the initial part of the req.path.

I will check the source code and add the updated comment in #138 after a rethought.

For now you can use the onProxyRes option to manually rewrite the location header.

Thanks for brainstorming along for a solution!

Thanks onProxyRes works for now.

I'm a newbie.. @chimurai .... can you give an example of how to rewrite location header this onProxyRes?

My current setup is some of my api's like /api/v1/NAME get forwarded to /api/v1/ID by the server... I have used the autoRewrite: true ... but this doesnt help me. I understand from this thread that we can get this to work by manually rewriting the location header in onProxyRes .... but, I don't know how. Can you give me an example of how this can be done?

I did put in a console log in onproxyRes and I find the location to be forwarded to is available in header. But, I don't know what to do with it.

Thanks.... After a few attempts... I got it working with this -

var onProxyRes = function(proxyRes, req, res) {
    //Handling api server redirects
    if ([307, 308].indexOf(proxyRes.statusCode) > -1 && proxyRes.headers.location) {
        var redirect = proxyRes.headers.location;
        logger.warn('Received code ' + proxyRes.statusCode + ' from API Server for URL - ' + redirect);
        redirect = redirect.replace('http://localhost:8080/v1', '/api');
        logger.warn('Manipulating header location and redirecting to - ' + redirect);
        proxyRes.headers.location = redirect;
    }
};

Thanks!

Glad to hear you've found a solution. Thanks for sharing it @udayms

For future reference, there is the same need for rewriting Location path on 201 Created responses.

Just ran into this using FastAPI. @abought mentions in the comments of their commit that they had the problem with Flask which includes the host:port in the redirect.

  const apiTarget = 'http://localhost:8080'

  app.use(
    '/api',
    proxy({
      target: apiTarget,
      changeOrigin: true,
      autoRewrite: false,
      logLevel: 'debug',
      pathRewrite(pathname) {
        return pathname.replace(/^\/api/, '')
      },
      onProxyRes,
    })
  )

const onProxyRes = function(proxyRes, req, res) {
  if ([307, 308].indexOf(proxyRes.statusCode) > -1 && proxyRes.headers.location) {
    var redirect = proxyRes.headers.location
    redirect = redirect.replace(api1Target, '/api') // <-- NOTE: `apiTarget`.
    proxyRes.headers.location = redirect
  }
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pwlerke picture pwlerke  路  6Comments

mshindal picture mshindal  路  4Comments

joshiste picture joshiste  路  4Comments

gajus picture gajus  路  8Comments

maks-rafalko picture maks-rafalko  路  8Comments