I have a running web-application at http://example.com/
, and want to "mount" another application, on a separate server on http://example.com/en
. Upstream servers and proxy_pass
seem to work, but for one issue:
upstream luscious {
server lixxxx.members.linode.com:9001;
}
server {
root /var/www/example.com/current/public/;
server_name example.com;
location /en {
proxy_pass http://luscious;
}
}
When opening example.com/en
, my upstream application returns 404 not found /en
. This makes sense, as the upstream does not have the path /en
.
Is proxy_path
the right solution? Should I rewrite "upstream" so it listens to /en
instead, as it root path? Or is there a directive that allows me to rewrite the path passed along to upstream?
This is likely the most efficient way to do what you want, without the use of any regular expressions:
I'd like to address a newer regex-based answer that's been rising in popularity.
The solution may seem more cute at first glance, but it's wrong for multiple reasons.
The above regex would match a request uri of
/enjoy
, redirecting it to/joy
upstream. Is this really intended?A request for
/en
will not result in any redirects, directly serving a/
from the upstream (almost as if a request for/en/
was made instead, but not quite). If you use relative URIs within your root page upstream (otherwise, why wouldn't you have the/en/
prefix right there within the upstream URIs?), e.g.src="style.css"
(which might reference a language-specificurl("menu.png")
, for example), then the browser will request that as/style.css
instead of/en/style.css
. (Or even if you use absolute URIs everywhere, what if someone references an obscure semi-optional resource relatively?) Oops, suddenly the site may not work, but only sometimes or in edge cases.As per my earlier advice at another question already mentioned by the OP's own answer, using regular expressions prevents the
proxy_redirect
directive from having the default value ofdefault
, turning it down tooff
instead. This means that if the upstream replies withLocation: http://127.0.0.1:8080/en/dir/
when a request for/en/dir
is made, then that's what the client will see, which obviously won't work correctly. (Which would have been especially ironic for a/en
request which prompts regex use in the first place, yet this specific implementation instead suffers from another problem as already mentioned above.) Plus, if you're already using theupstream
directive, then it might get extra ugly if you just try to go with a custom one, especially if you may have more than one upstream server — how do you have a separateproxy_redirect
for each one of those? You could use regular expressions withinproxy_redirect
, too, maybe even to match any host, but then what if you decide to give a cross-domain redirect in the future?To try to address some of the above points with a single regex-based location, we could do the following (note that in
proxy_pass
we also had to drop the reference to a server from anupstream
-based directive, to makeproxy_redirect
more straightforward):So, if you ask me, the original solution with the two sibling top-level locations would still be a better idea than digging yourself into a rabbit hole by going the regex route instead.
So, I found the answer on stackoverflow:
Basically: passing a regex into location and passing the backref along to the proxy_pass url.
Accounting to Nginx documents
To pass a request to an HTTP proxied server, the proxy_pass directive is specified inside a location. For example:
This example configuration results in passing all requests processed in this location to the proxied server at the specified address. This address can be specified as a domain name or an IP address. The address may also include a port:
Note that in the first example above, the address of the proxied server is followed by a URI, /link/. If the URI is specified along with the address, it replaces the part of the request URI that matches the location parameter. For example, here the request with the /some/path/page.html URI will be proxied to http://www.example.com/link/page.html. If the address is specified without a URI, or it is not possible to determine the part of URI to be replaced, the full request URI is passed (possibly, modified).
I had a play with the accepted solution above but found it was causing dodgy redirects for all the CSS and JS assets. In the end, I found inspiration from the way that the LinuxServer SWAG Nginx configurations are done. You can find them here. Take a look at
pihole.subfolder.conf.sample
.As such, my solution looks like this: