proxy_pass in nginx to publish webapp under a different directory - nginx

I have this location element:
location ~* ^/publicapp {
proxy_pass https://myserver.domain.local;
}
The server myserver.domain.local hosts a web application located under /myapp.
I want to make it publicly available via https://www.mywebsite.com/publicapp. How do I tell nginx to translate /myapp to /publicapp?
Please keep in mind that I use ~* to allow case-insensitivity. Thus, I cannot use a URI with proxy_pass.
Kind regards,
Kevin

Try this:
location ~* /publicapp/ {
rewrite ^/publicapp/(.*)$ /myapp/$1 break;
proxy_pass https://myserver.domain.local;
}
This will rewrite your path and use new one at the .local server.

It works using
rewrite ^/publicapp/(.*) /myapp/$1 break;
At least it does with my very simple application.
Now I have to figure out how to do proper link translation (sorry for using ISA Server/TMG terms, don't know if it's the same in nginx).
Thanks to pythagor :-)
edit:
Works only if I keep a trailing slash after the url in the browser (https://www.mywebsite.com/publicapp/).
another edit:
To make sure URLs end with a slash:
rewrite ^([^.]*[^/])$ $1/ permanent;
Taken from: here (first answer)

Related

Correct way to remove path from location in nginx with proxy pass

I currently have the following configuration to proxy requests off a single domain to multiple backends:
server {
listen 80;
location /team/app1/location/region/ {
proxy_pass https://this.is.the.backend.app.example/path1/healthcheck;
}
location /team/app2/location/region/ {
proxy_pass https://this.is.the.backend.app.example/path2/healthcheck;
}
location /team/app3/location/region/ {
proxy_pass https://this.is.the.backend.app.example/path3/healthcheck;
}
}
The paths are pretty arbitrary, essentially I just want to be able to proxy from:
https://proxydomain.com/team/app1/location1/region
To:
https://this.is.the.backend.app.example/path3/healthcheck
So
/team/app1/location1/region
Would need to be stripped from the request and just proxy the request to the intended backend. I assume the path is being appended in someway as I just get 404s...
I can pass to a domain without trailing path like so - but when I try and proxy to a domain with trailing paths it gets complicated:
server {
listen 80;
location /one {
proxy_pass http://x.x.x.x/;
}
location /two {
proxy_pass http://x.x.x.x/;
}
}
I have tried the following configuration too - to try and rewrite the url:
rewrite ^/team/app3/location/region/(.*)$ $1 break;
Hopefully it makes sense what I am trying to achieve - any guidance would be greatly appreciated.
Thanks
You were on the right track. The rewrite will look like:
location /team/app3/location/region/ {
rewrite ^/team/app1/location/region/(.*)$ /path3/$1 break;
proxy_pass https://this.is.the.backend.app.example/;
}
You should add the new path path3 in the rewrite rule. With this NGINX will rewrite the $uri and append it to the proxy_pass. In case app3 and path3 are a fixed pattern you can tune the location block as well as the rewrite to simplify your configuration. But I would generally start with the approach mentioned above.
AND we keep in mind. Regex matching in locations will consume CPU. So sometimes it is better to have them fixed / static. Especially if you are using them in health checks and query them every 5s or so.
Thanks for that - definitely helped getting me down the correct track:
In the end the working config was:
location /team/app3/location/region {
rewrite ^/team/app3/location/region(.*) /path3/healthcheck$1 break;
proxy_pass https://this.is.the.backend.app.example;
}
Which correctly proxied through to:
https://this.is.the.backend.app.example/path3/healthcheck

Nginx rewrite requests to subdomain.tld/files/* to external domain

I'd like to rewrite all requests to Nginx matching http://*.examle.tld/files/* to http://$1.otherdomain.tld/files/?file=$2. I'd also like to rewrite the same request without the subdomain i.e. http://example.tld/files/* to http://otherdomain.tld/files/?file=$1
The reason for this is to use production files from local development without having to sync folders.
This is what I've got so far, however without success:
location / {
...
rewrite ^http://(\w+)\.(.*)/files/(.*) http://$1.otherdomain.tld/inc/reader.php?file=$3;
rewrite ^.*/files/(.*) http://$1.otherdomain.tld/inc/reader.php?file=$1;
...
}
Thank you for any assistance.
You cannot use the server name as part of the rewrite directive's regex. If you have a server block with a wild card server_name as described here, you can use a named capture for use later within the block.
For example:
server {
server_name ~^(?<sub>\w+\.)?example\.tld$;
location /files/ {
rewrite ^/files(.*)$ http://${sub}otherdomain.tld/files/?file=$1 permanent;
}
}
See this document for details.

nginx 'proxy_pass' cannot have URI part in location?

I have a location block as
location #test{
proxy_pass http://localhost:5000/1;
}
but nginx complains that "proxy_pass cannot have URI part in location given by regular expression..." Does anyone know what might be wrong?
I'm trying to query localhost:5000/1 when an upload is complete:
location /upload_attachment {
upload_pass #test;
upload_store /tmp;
...
}
Technically just adding the URI should work, because it's documented here and it says that it should work, so
location #test{
proxy_pass http://localhost:5000/1/; # with a trailing slash
}
Should have worked fine, but since you said it didn't I suggested the other way around, the trick is that instead of passing /my/uri to localhost:5000/1, we pass /1/my/uri to localhost:5000,
That's what my rewrite did
rewrite ^ /1$1
Meaning rewrite the whole URL, prepend it with /1 then add the remaining, the whole block becomes
location #test{
rewrite ^ /1$1;
proxy_pass http://localhost:5000;
}
Note: #Fleshgrinder provided an answer explaining why the first method didn't work.
What's actually happening here?
nginx cannot process your desired URI part in the proxy_pass directive because you're within a named location (hence the error message). This is because nginx is built in a modular fashion and each configuration block is read in various stages by the various modules. So just remember that you cannot have a URI within your proxy_pass directive in the following cases:
Regular Expression Locations
Named Locations
if Blocks
How could we solve this problem?
Mohammad AbuShady explained how to do a rewrite and pass the requested URI to the proxy server. I just wanted to clarify the reason.
Try omitting the "/" (URI part) and check.
location #test{
proxy_pass http://localhost:5000;
}

Correct proxy path in nginx.conf

we have two servers, A and B. Server A is accessed worldwide. He has nginx installed. That's what I have in conf:
location /test {
proxy_pass http://localserver.com;
}
What it should do, is translate the addreess http://globalserver.com/test (that is server A) to internal server address http://localserver.com. However, it does append the location path, that is, itries to look for http://localserver.com/test, which is not available at all. How can I make the proxy pass to the correct address, throwing out the last part in the location?
That should work. Nginx should strip the '/test' path on the upstream local server. So what I can say is that is not the cause. To make it a bit better, try this:
location /test/ {
proxy_pass http://localserver.com/;
}
The 2 slashes I added at the first 2 lines will avoid mistakenly match '/testABC' and send the wrong request to the upstream local server, for example.
Do you have a
proxy_redirect
line in the same location block? If your upstream local server has redirects, then a mistake on that line will cause an issue like you described.
[UPDATE] Found the root cause why the original config didn't work and mine works: nginx does NOT replace URI path part if the proxy_pass directive does not have a URI path itself. So my fix of adding a slash (slash is treated as a URI path) at the end triggers the URI path replacement.
Reference: http://wiki.nginx.org/HttpProxyModule#proxy_pass
If it is necessary to transmit URI in the unprocessed form then directive proxy_pass should be used without URI part
location /some/path/ {
proxy_pass http://127.0.0.1;
}
try to add as specified here http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass:
proxy_pass http://localserver.com/;
try rewrite
location /test {
rewrite ^ $scheme://$host/;
proxy_pass http://localserver.com;
}
some helpful links...
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
http://wiki.nginx.org/Pitfalls

Nginx rewrite unencodes url

It seems Nginx it always un-encodes urls when used with a regular expression. I have a rewrite rule:
location /api/ {
rewrite /api/(.*)$ $1 break;
proxy_pass http://127.0.0.1:8000/$1;
}
I would like to remove the api from the usl but keep the rest of the path. Part of the path is an email address someone#somewhere.com. I am passing someone%40somewhere.com but Nginx is turning it back with the # sign.
The correct answer seem to be
location /api/ {
rewrite ^ $request_uri;
rewrite ^/api/(.*) $1 break;
return 400;
proxy_pass http://127.0.0.1:8000/$uri;
}
See Nginx pass_proxy subdirectory without url decoding for full answer and original author.
(I realize this question is older than the one I referenced but I found this in google search and may not be the last one, so ...)
That is how Nginx handles urls. You can bypass it by changing your web application to escape the "%" character as "%25" and pass someone%2540somewhere.com.
This will be unescaped as someone%40somewhere.com.

Resources