nginx responding “301 moved permanently”

2019-07-11 07:11发布

问题:

Consider the following nginx config file:

server {
    listen 443;
    ssl    on;
    ssl_certificate     /etc/tls/cert.pem;
    ssl_certificate_key /etc/tls/key.pem;
    location / {
        proxy_pass http://api.default.svc.cluster.local;
    }
}

All incoming TCP requests on 443 should redirect to my server running on api.default.svc.cluster.local:80 (which is a node REST-Api btw). This works fine, I can curl https://<nginx-IP>/ nginx and get a correct response, as expected.

Now, I'd like to change the location from / to /api, so I can fire a curl https://<nginx-IP>/api in order to get the same response as before.

1. Attempt

So I change the location line in the config to:

location /api {

Unfortunately this won't work, instead I get an error Cannot GET /api which is a node error, so obviously it gets routed to the api but something's still smelly.

2. Attempt

It seems as the trailing slash in an URI is required so I added it to the location:

location /api/ {

Now something changed. I won't get the same error as before, instead I get an "301 moved permanently". How can I fix my nginx config file?

Additional information regarding the environment

I'm using a kubernetes deployment that deploys the nginx reverse proxy incl. the config introduced. I then expose nginx using a kubernetes service. Also, I tried using kubernetes ingress to deal with this situation, using the same routes, however, the ingress service would respond with a default backend - 404 message.

回答1:

As mentioned in the question, trailing slashes in URIs are important. I fixed this in the location, however, I didn't add it to the URI I pass using proxy_pass.

As for the nginx proxy I got it to work using the following config:

server {
    listen 443;
    ssl    on;
    ssl_certificate     /etc/tls/cert.pem;
    ssl_certificate_key /etc/tls/key.pem;
    location /api/ {
        proxy_pass http://api.default.svc.cluster.local/;
    }
}

Concerning the ingress solution, I was not able to get it to work by adding the missing trailing slash to the path. The service is specified due its name and therefore no trailing slash can be added (i.e. it would result in an error).