Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 890
Christopher Francisco Avatar asked Dec 14 '18 21:12

Christopher Francisco


2 Answers

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;
}
like image 183
Robert Tupelo-Schneck Avatar answered Nov 15 '22 17:11

Robert Tupelo-Schneck


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;
like image 31
Christopher Francisco Avatar answered Nov 15 '22 18:11

Christopher Francisco