Nginx reverse proxy + URL rewrite

Solution 1:

Any redirect to localhost doesn't make sense from a remote system (e.g. client's Web browser). So the rewrite flags permanent (301) or redirect (302) are not usable in your case.

Please try following setup using a transparent rewrite rule:

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://localhost:3200;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}

Use curl -i to test your rewrites. A very subtle change to the rule can cause nginx to perform a redirect.

Solution 2:

Simple location prefix matching works for this without using a rewrite rule as long as you specify a URI in the proxy_pass directive:

location /foo {
  proxy_pass http://localhost:3200/;
}

Notice the additional / at the end of the proxy_pass directive. NGINX will strip the matched prefix /foo and pass the remainder to the backend server at the URI /. Therefore, http://myserver:80/foo/bar will post to the backend at http://localhost:3200/bar.

From the NGINX docs on proxy_pass:

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:


Solution 3:

The absolute most correct way and best practice is usually as follows:

location /foo/ {
    proxy_pass http://localhost:3200/; # note the trailing slash!
}

  • Note the dire importance of the trailing slash in proxy_pass, which automatically alters the $uri variable to have the /foo/ on the front-end correspond with / on the backend. No need for an explicit rewrite directive.

  • Additionally, note that the the trailing / in the location is quite important as well — without it, you risk having weird-looking URLs on your site at one point (e.g., a working /fooen in addition to /foo/en).

    Additionally, the trailing / in the location with proxy_pass also ensures some special handling, as per the documentation of the location directive, to effectively cause an implicit location = /foo {return 301 /foo/;} as well.

    So, by defining a location with the trailing slash as above, you not only ensure that slash-less suffix URLs like /fooen won't be valid, but also that a /foo without a trailing slash will continue to work as well.


Reference documentation:

  • http://nginx.org/r/location
  • http://nginx.org/r/proxy_pass

Solution 4:

try

location /foo {
    proxy_pass http://localhost:3200/;
    ....

or

location ^~ /foo {
    proxy_pass http://localhost:3200/;
    ....