How can I rewrite parts of a Location header with nginx? - nginx

I'm trying to setup a reverse proxy nginx in a docker-compose setup I have. It works fairly well, but I have a problem with a 302 redirect.
The nginx server runs on https://localhost:1253. When I return the redirect within my internal server, nginx will use the internal name (serviceweb) of my docker container in the redirect uri. This is my redirect uri:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&<...>&redirect_uri=https%3A%2F%serviceweb%2Fsignin-google...
I'd like to change serviceweb to localhost:1253.
How can I do this with nginx?
I've tried this simple setup:
location / {
proxy_pass https://serviceweb;
proxy_redirect serviceweb localhost:1253;
}
But this does not quite work. The location header still contains the original value. I'm sure I somehow have a problem in the proxy_redirect rule , but I'm not sure how. There's a regex based way of doing it according to http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect, and I think my current setup would work with that.
What am I doing wrong?

Related

Can a response from an http request alter the base address in the next client request?

I have an octoprint server running at http://192.168.1.205. I also have an nginx server hosting myDomain. I want to be able to use the nginx server to pass on a request for http://myDomain/octo to http://192.168.1.205 using a reverse proxy. Here is my nginx code...
server {
server_name myDomain;
location /octo/ {
rewrite ^/octo/(.*) /$1 break; #strip /octo from url
proxy_pass http://192.168.1.205;
}
}
The first http://myDomain/octo request is passed on to http://192.168.1.205 correctly. But after the first response the code in the client makes another request to http://myDomain/moreUri. Since this uri doesn't have /octo nginx doesn't know to send it to http://192.168.1.205/moreUri. Is there a way to have nginx change something in the first response so that the client then makes following requests to http://myDomain/octo/moreUri?
I was able to accomplish this for a case where the octoprint server responded with a redirect. I used ...
proxy_redirect http://192.168.1.205/ http://myDomain/octo/;
and it worked. But that only works on redirects and the following requests were wrong again.
Is there a way to have nginx change something in the first response so
that the client then makes following requests to
http://myDomain/octo/moreUri?
I am not aware that this is possible.
What about to adjust the nginx configuration accordingly ? using location / to process all requests within that block and add an additional redirect directive to address the "Since this uri doesn't have /octo nginx doesn't know to send it to http://192.168.1.205/moreUri" should do the trick.
server {
server_name myDomain;
location / {
rewrite ^/octo/(.*) /$1 break; #strip /octo from url
rewrite ^/(.*)/(.*) /octo/$2 break; #rewrite /moreURI to /octo/moreURI
proxy_pass http://192.168.1.205;
}
}
No matter if the above nginx reconfiguration fixes your issue, i assume the root cause why you need to configure the nginx as reverse proxy in this way might be a misconfigured (or not optimally configured) application. Check the config file if it is possible to configure the applications base path. If so, set it to /octo/ (so the application itself prepends /octo/ to all the links it presents to the user and all requests to the backend automatically) and adjust the rewrite rules accordingly.

Nginx - Passing parameters through to proxy_pass

I'm new to nginx - am using Vouch proxy and trying to utilise its logout redirect: https://github.com/vouch/vouch-proxy#logout-endpoint-redirection
In my app I'm hitting a URL like: mydomain.com/tools/app/logout?url={somevalue}
Then in nginx I'm passing this onto vouch proxy with
location /tools/app/logout {
proxy_pass http://vouch/logout;
}
However is it possible to pass that ?url={somevalue} parameter too? Basically append to proxy_pass http://vouch/logout?
Any help appreciated.
Thanks.

How to escape "?" in nginx rewrite rule output

I am trying to reverse proxy in nginx, rewriting a front end page like "/a/b?page=2" into a backend request to "/a/b%3fpage=2"
I cannot figure out how to get nginx to make reverse proxy requests which include "%3f".
With the following config:
rewrite ^/one$ /a%3fb;
rewrite ^/two$ /a?b;
rewrite ^/three$ /a\?b;
/one makes a backend request like GET /a%253fb HTTP/1.0
/two makes a backend request like GET /a?b HTTP/1.0
/three makes a backend request like GET /a\?b HTTP/1.0
How can I get a backend request like GET /a%3fb HTTP/1.0?
Thanks to #Richard Smith's comment, I was able to fix this for my specific case with the following code:
location / {
set $backend_uri $request_uri;
if ($args ~* "page=(\d+)") {
set $page $1;
set $backend_uri $uri%3fpage=$1;
}
proxy_pass http://example.com$backend_uri;
}
I think that I might also have been able to do something more general with the lua rewrite directive, but I was unable to install mod-lua on an Amazon Linux 2 machine, see https://serverfault.com/questions/961337/how-to-install-nginx-mod-lua-on-amazon-linux-2

With nginx proxy/rewrite can I keep the original URL in the browser's Location field?

Using nginx.conf features like proxy-pass/rewrite, can I keep the original URL in the browser's Location field?
I have several PlayFramework apps running on different ports (9001, 9002, ...) with proxy forwarding set up via nginx.conf. People browse to them as:
http://domain.name/App1/
http://domain.name/App2/
etc.
My nginx.conf entries look like this:
location /App1/ {
proxy_pass http://localhost:9001/;
rewrite ^/App1/(.*) http://domain.name:9001/$1;
}
If I ask for http://domain.name/App1/, what I see in the browser's Location field is http://domain.name:9001. What I wish I saw was http://domain.name/App1/, that is, I want the name App1 to remain in the URI, and I'd rather not expose the port number.
Let's say App1 has a link /location/ABC. When I click on it I see http://domain.name:9001/location/ABC when I wish I saw http://domain.name/App1/location/ABC.
Can I achieve this with nginx.conf?
P.S. I put http://domain.name explicitly in the rewrite rule because without it I was getting localhost in the browser, and my browser's localhost is not the same as the server's.
Rewrites issue redirects for browser.
If you just want to mount several locations from upstreams - you do not need rewrites, just use:
location /App1/ {
proxy_pass http://localhost:9001/;
}
But apps should use relative links or account for their absolute location.
For more complex url manipulation you can use break-rewrites:
location /App1/ {
rewrite ^/App1/(.*) /$1 break;
proxy_pass http://localhost:9001;
}

Nginx proxy redirect without changing url

I have a nginx (:80) and an upstream server (:8080) running on my machine.
I want to proxy all requests to /assets/(*.?) to upstream's /upstream/$1 location.
The upstream server redirects (302) /upstream/file_id to the /real/file/location.ext
Here is my code:
location /assets/ {
rewrite ^/assets/(.*) /upstream/$1 break;
proxy_pass http://127.0.0.1:8000;
}
This seems to work, but on the client side I get the redirected location:
http://myserver.com/real/file/location.ext
I kinda want to hide it so that it stays:
http://myserver.com/assets/file_id
The idea behind this is to make the upstream server find the real file's location, but let the nginx serve the file without giving away its real location. Is this even possible?
first you're using 8000 in proxy_pass, but you're mentioning your port is 8080.
Second, remove the rewrite line should do the trick, because youre actually using the rewrite rule here and never get to the proxy_pass line. Something like the following should work:
location /assets/ {
include proxy_params;
proxy_pass http://127.0.0.1:8080;
}
There are also proxy_rewrite and proxy_redirect commands which might help you in getting this upstream-redirect handled internally by nginx.
Hope that helps!

Resources