Why is my Nginx reverse proxy doing a 301 redirect instead of proxying?
Asked Answered
D

3

14

I have an Nginx reverse proxy inside a docker container, which listens to port 3000 and is exposed to 3002: docker run -p "3002:3000" ....

The idea is that this reverse proxy will proxy /my-app to the instance running in my laptop on port 8080; and /my-app/api to the cloud instance, in https://my-domain.

Here's the configuration:

upstream my-laptop {
  server host.docker.internal:8080; # this is a magic hostname for the laptop's IP address.
  keepalive 64;
}

upstream cloud {
  server my-domain.com:443;
  keepalive 64;
}

server {
    listen       3000;

    include ssl/ssl-certs.conf;
    include ssl/ssl-params.conf;

    location /my-app {
        proxy_pass http://my-laptop;
        proxy_set_header Host            $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /my-app/api {
        proxy_pass https://cloud;
        proxy_set_header Host            $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    ...
}

The issues are:

  1. when I hit https://localhost:3002/my-app I get a 301 response to /my-app/ (trailing slash). I don't know why is that. The local app instance is shown in the browser, so I guess I can let it slide for the moment?
  2. when I hit https://localhost:3002/my-app/api/students, I get a 301 response to https://cloud/my-app/api/students. This causes CORS issues, of course, and the endpoint doesn't return data.

Now, I have configured reverse proxies a couple of times, so I am completely shocked that I'm not seeing what's wrong, this is not my first time.

I have tried tweaking with the upstreams, the proxy_set_headers, compared with another reverse proxy that I have for a different app; I'm out of ideas.

What am I doing wrong?

Dinger answered 14/12, 2018 at 21:29 Comment(4)
Have you tried proxy_set_header Host $proxy_hostBoden
using which "trailing slash combination"?Dinger
Something along these lines location /my-app/api { proxy_pass cloud; proxy_set_header Host $proxy_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /my-app/? { proxy_pass my-laptop; proxy_set_header Host $proxy_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }Boden
I am not sure if it matters, but I am wondering if the order of the proxy_set_header and proxy_pass matters, so I would try to move the pass to the bottom maybe.Terra
D
7

The problem was my Host header in the cloud upstream, I had

proxy_set_header Host $http_host;

But it needed to be

proxy_set_header Host my-domain.com;
Dinger answered 19/12, 2018 at 14:35 Comment(1)
My Nginx proxy is behind cloudflare proxy. I have removed server_name. In that case how what should be the value for my Host? Becasue I am facing the same issue you did. I get 405 Method Not Allowed CORS issue if there is no trailing slash in my endpoint.Gather
D
12

Although the questioner's config doesn't have this particular issue, a redirect instead of proxying can also be caused by trailing slash issues, as described in the docs:

If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed. In response to a request with URI equal to this string, but without the trailing slash, a permanent redirect with the code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the URI and location could be defined like this:

location /user/ {
   proxy_pass http://user.example.com;
}

location = /user {
    proxy_pass http://login.example.com;
}
Disclosure answered 2/2, 2021 at 17:58 Comment(1)
Good to note this information here as I have this exact question and this answer is directly applicable to my issue (and others that land here I am sure). (y) also see serverfault.com/questions/801897/…Civilization
D
7

The problem was my Host header in the cloud upstream, I had

proxy_set_header Host $http_host;

But it needed to be

proxy_set_header Host my-domain.com;
Dinger answered 19/12, 2018 at 14:35 Comment(1)
My Nginx proxy is behind cloudflare proxy. I have removed server_name. In that case how what should be the value for my Host? Becasue I am facing the same issue you did. I get 405 Method Not Allowed CORS issue if there is no trailing slash in my endpoint.Gather
T
2

here is an example config for nginx as a reverse proxy which works for me, I simplified it and removed unnecessary parts. I hope it helps.

upstream OAUTH {
    server remote_oauth;
}



server {
    listen  80;
    server_name example.com;

    client_header_timeout       300;


    location = /servies/oauth {
      return 301 /services/oauth/;
    }


    location /services/oauth/ {
        proxy_pass_request_headers on;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://OAUTH/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-ROOT-URI /services/oauth;
        proxy_set_header Accept-Encoding "gzip";
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_http_version 1.1;
        proxy_intercept_errors on;
        proxy_redirect default;
        client_max_body_size 4M;
    }


}

I think you missed this part : proxy_pass_request_headers on

Tesler answered 15/12, 2018 at 0:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.