How to preserve request url with nginx proxy_pass
Asked Answered
C

8

114

I was trying to use Thin app server and had one issue.

When nginx proxies the request to Thin (or Unicorn) using proxy_pass http://my_app_upstream; the application receives the modified URL sent by nginx (http://my_app_upstream).

What I want is to pass the original URL and the original request from client with no modification as the app relies heavily on it.

The nginx' doc says:

If it is necessary to transmit URI in the unprocessed form then directive proxy_pass should be used without URI part.

But I don't understand how exactly to configure that as the related sample is actually using URI:

location  /some/path/ {
  proxy_pass   http://127.0.0.1;
}

So could you please help me figuring out how to preserve the original request URL from the client?

Clausen answered 29/4, 2011 at 15:28 Comment(1)
"Thin" now points to a 404Rosaleerosaleen
C
179

I think the proxy_set_header directive could help:

location / {
    proxy_pass http://my_app_upstream;
    proxy_set_header Host $host;
    # ...
}
Clamber answered 29/4, 2011 at 16:25 Comment(7)
Note to other people finding this: The heart of the solution to make nginx not manipulate the URL, is to remove the slash at the end of the proxy_pass directive. http://my_app_upstream vs http://my_app_upstream/Vaunting
For me what was happening is that when JSP was doing redirect, my_app_upstream host name was showing up. Using proxy_set_header Host $host modified and made Tomcat/JSP to think that it's an actual client requested domain. Thanks for the helpMithgarthr
@HugoJosefson wow thanks god I notice your post. This should be explicit in the answerAideaidedecamp
In my case, @HugoJosefson's solution would not work. I was pointing to localhost:port; I had to set the header.Rehnberg
It's an improvement but the scheme (http or https) is not preserved. Now my https://example.com/page uris become http://example.com/pageSocle
@HugoJosefson should be knightedPalmore
I'm trying the same thing but it's not preserving the url.. I'm getting just "GET / HTTP/1.0" instead of url.. What should I do?Oilcan
T
15

Just proxy_set_header Host $host miss port for my case. Solved by:



    location / {
     proxy_pass http://BACKENDIP/;
     include /etc/nginx/proxy.conf;
    }

and then in the proxy.conf



    proxy_redirect off;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Update according @iwein comment for nginx 1.8.x (see https://mcmap.net/q/189896/-why-is-proxy_set_header-host-host-no-longer-working-in-nginx-1-8-0):

iso proxy_set_header Host $host:$server_port; use proxy_set_header Host $http_host

Tardif answered 12/6, 2013 at 19:37 Comment(3)
Thanks, this was the piece I was missing (the $server_port) to get OAuth verification working on the endpoint behind the proxy.Hydrolysis
I'm using rack-protection with sinatra and was getting Forbidden on POST URLs. Adding the port to the Host proxy header fixed it for me.Francesco
this doesn't work anymore in latest versions of Nginx I think #31483296Orabelle
F
12

nginx also provides the $http_host variable which will pass the port for you. its a concatenation of host and port.

So u just need to do:

proxy_set_header Host $http_host;
Flopeared answered 18/1, 2018 at 4:49 Comment(0)
D
9

In case something modifies the location that you're trying to serve, e.g. try_files, this preserves the request for the back-end:

location / {
  proxy_pass http://127.0.0.1:8080$request_uri;
}
Drew answered 3/10, 2018 at 4:27 Comment(0)
C
8

Note to other people finding this: The heart of the solution to make nginx not manipulate the URL, is to remove the slash at the end of the Copy: proxy_pass directive. http://my_app_upstream vs http://my_app_upstream/ – Hugo Josefson

I found this above in the comments but I think it really should be an answer.

Crematory answered 16/5, 2019 at 19:28 Comment(0)
G
5

To perfectly forward without chopping the absoluteURI of the request and the Host in the header:

server {
    listen 35005;

    location / {
        rewrite            ^(.*)$   "://$http_host$uri$is_args$args";
        rewrite            ^(.*)$   "http$uri$is_args$args" break;
        proxy_set_header   Host     $host;

        proxy_pass         https://deploy.org.local:35005;
    }
}

Found here: https://opensysnotes.wordpress.com/2016/11/17/nginx-proxy_pass-with-absolute-url/

Git answered 13/7, 2017 at 7:58 Comment(4)
Velkan, but why it is cannot be done in one rewrite?Sir
@MikhailPolitaev the first "rewrite" seems unnecessary. The source article has a "break" in the first "rewrite" and a comment that says to remove that "break" to make it work. So the source isn't really reliable.Git
First break is unnecessary, agreed. But already realized why 2 rewrite required. Because if rewrite start with "https://" Nginx will respond 301 or 302 to the client and here 2 rewrite split https:// to 2 parts "https" and "://" in result redirect not returned to the client and send in absolute form "https://..." in GET request what is required by proxy protocol. I didn't find another way how to make GET request in absolute form – starts with scheme http(s):// it's strange that not obvious in Nginx.Sir
This is the only solution that worked for me. This is what I was looking for.Lorelle
C
2

In my scenario i have make this via below code in nginx vhost configuration

server {
server_name dashboards.etilize.com;

location / {
    proxy_pass http://demo.etilize.com/dashboards/;
    proxy_set_header Host $http_host;
}}

$http_host will set URL in Header same as requested

Charlettecharley answered 3/5, 2018 at 21:39 Comment(0)
L
-1

for my auth server... this works. i like to have options for /auth for my own humanized readability... or also i have it configured by port/upstream for machine to machine.

.

at the beginning of conf

####################################################
upstream auth {
    server 127.0.0.1:9011 weight=1 fail_timeout=300s;
    keepalive 16;
  }

Inside my 443 server block

          if (-d $request_filename) {
          rewrite [^/]$ $scheme://$http_host$uri/ permanent;
      }

  location /auth {
          proxy_pass http://$http_host:9011;
          proxy_set_header Origin           http://$host;
          proxy_set_header Host             $http_host:9011;
          proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade          $http_upgrade;
          proxy_set_header Connection       $http_connection;
          proxy_http_version 1.1;
      }

At the bottom of conf

#####################################################################
#                                                                   #
#     Proxies for all the Other servers on other ports upstream     #
#                                                                   #
#####################################################################


#######################
#        Fusion       #
#######################

server {
    listen 9001 ssl;

#############  Lock it down  ################

# SSL certificate locations
    ssl_certificate /etc/letsencrypt/live/allineed.app/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/allineed.app/privkey.pem;

# Exclusions

    include snippets/exclusions.conf;

# Security

    include snippets/security.conf;
    include snippets/ssl.conf;

# Fastcgi cache rules

    include snippets/fastcgi-cache.conf;
    include snippets/limits.conf;
    include snippets/nginx-cloudflare.conf;

###########  Location upstream ##############

    location  ~ / {
        proxy_pass http://auth;
        proxy_set_header Origin           http://$host;
        proxy_set_header Host             $host:$server_port;
        proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade          $http_upgrade;
        proxy_set_header Connection       $http_connection;
        proxy_http_version 1.1;
    }
        if (-d $request_filename) {
        rewrite [^/]$ $scheme://$http_host$uri/ permanent;
    }
}
Lupulin answered 6/11, 2018 at 22:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.