Nginx Redirect via Proxy, Rewrite and Preserve URL

Solution 1:

You should use URI part in proxy_pass directive. Also, you mixed up order arguments of proxy_redirect directive, and probably you don't need it at all. Nginx has reasonable default for this directive.

In this case your location block could be really simple:

location /some/path/ {
    proxy_pass http://192.168.1.24/;
    # note this slash  -----------^
    proxy_set_header Host $host;
}

Solution 2:

First, you shouldn't use root directive inside the location block, it is a bad practice. In this case it doesn't matter though.

Try adding a second location block:

location ~ /some/path/(?<section>.+)/index.html {
    proxy_pass http://192.168.1.24/$section/index.html;
    proxy_set_header Host $host;
}

This captures the part after /some/path/ and before index.html to a $section variable, which is then used to set the proxy_pass destination. You can make the regex more specific if you require.


Solution 3:

You can use the following config to have a 100% seamless mapping between /some/path/ on the front-end and / on the backend.

Note that this is the only answer so far that would also seamlessly take care of absolute paths generating 404 Not Found errors, provided that the correct HTTP Referer header is sent by the browser, so, all those gifs should continue to load without any need to modify the underlying HTML (which is not only expensive, but is also not supported without additional modules not compiled by default).

location /some/path/ {
    proxy_pass http://192.168.1.24/; # note the trailing slash!
}
location / {
    error_page 404 = @404;
    return 404; # this would normally be `try_files` first
}
location @404 {
    add_header Vary Referer; # sadly, no effect on 404
    if ($http_referer ~ ://[^/]*(/some/path|/the/other)/) {
        return 302 $1$uri;
    }
    return 404 "Not Found\n";
}

You can find the complete proof-of-concept and minimal-viable-product within the https://github.com/cnst/StackOverflow.cnst.nginx.conf repository.

Here's a testing run to confirm that all the edge cases seem to works:

curl -v -H 'Referer: http://example.su/some/path/page.html' localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
> Referer: http://example.su/some/path/page.html
< HTTP/1.1 302 Moved Temporarily
< Location: http://localhost:6586/some/path/and/more.gif
< Vary: Referer

curl -v localhost:6586/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location
> GET /and/more.gif HTTP/1.1
< HTTP/1.1 404 Not Found

curl -v localhost:6586/some/path/and/more.gif | & fgrep -e HTTP/ -e Referer -e Location -e uri
> GET /some/path/and/more.gif HTTP/1.1
< HTTP/1.1 200 OK
request_uri:    /and/more.gif

P.S. If you have a lot of different paths to map, then instead of doing a regex comparison of $http_referer within an if within location @404, you might want to use the global-based map directive instead.

Also note that the trailing slashes in both the proxy_pass, as well as the location it is contained in, are quite important as per a related answer.

References:

  • http://nginx.org/r/location
  • http://nginx.org/r/error_page
  • http://nginx.org/r/if
  • http://nginx.org/r/return
  • http://nginx.org/r/add_header

Solution 4:

When that slash is added to an nginx proxied jenkins, you are presented with the “It appears that your reverse proxy set up is broken" error.

proxy_pass          http://localhost:8080/;

Remove this -----------------------------^

It should read

proxy_pass          http://localhost:8080;