Skip to content
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

Can pathRewrite option be made use of to adjust the Location header in redirects (301, 302, 307, 308) #140

Closed
vivekmoosani opened this issue Dec 22, 2016 · 10 comments

Comments

@vivekmoosani
Copy link

vivekmoosani commented Dec 22, 2016

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://api-host:port/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)

@chimurai
Copy link
Owner

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...

@vivekmoosani
Copy link
Author

vivekmoosani commented Dec 22, 2016

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.

@chimurai
Copy link
Owner

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

Thanks for brainstorming along for a solution!

@vivekmoosani
Copy link
Author

Thanks onProxyRes works for now.

@chimurai chimurai removed the bug label Dec 22, 2016
@udayms
Copy link

udayms commented Jan 25, 2017

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.

@chimurai
Copy link
Owner

chimurai commented Jan 25, 2017

@udayms
Copy link

udayms commented Jan 25, 2017

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!

@chimurai
Copy link
Owner

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

@benel
Copy link

benel commented May 3, 2018

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

@vjpr
Copy link

vjpr commented Apr 8, 2020

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
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants