Nginx causes 301 redirect if there's no trailing slash

UrlRedirectNginx

Url Problem Overview


I'm running nginx in a Virtual Machine using NAT and I'm having redirection issues when I access it from the host machine.

Works as expected
  • http://localhost:8080/test/index.htm: works.
  • http://localhost:8080/test/: works.
Doesn't work as expected
  • http://localhost:8080/test: redirects to http://localhost/test/ . This is not what I want. (notice it strips the port number)
What I've tried

Based on what I've googled, I tried server_name_in_redirect off; and rewrite ^([^.]*[^/])$ $1/ permanent;, both with no success.

My default.conf:
server {
    listen       80;
    server_name  localhost;
    # server_name_in_redirect off;
    
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm index.php;
    }

    location ~ \.php$ {
	# rewrite ^([^.]*[^/])$ $1/ permanent;
        root           /usr/share/nginx/html;
        try_files      $uri =404;
        #fastcgi_pass   127.0.0.1:9000;
        fastcgi_pass   unix:/tmp/php5-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi_params;
    }


    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

Url Solutions


Solution 1 - Url

I posted a possible solution to this problem on serverfault; reproduced here for convenience:

If I understand the question correctly, you want to automatically serve, without using a 301 redirect, http://example.com/foo/index.html when the request is for http://example.com/foo with no trailing slash?

Basic solution that works for me

> If so I've found this try_files configuration to work: > > try_files $uri $uri/index.html $uri/ =404; > > - The first $uri matches the uri exactly > - The second $uri/index.html matches a directory containing the index.html where the last element of the path matches the directory > name, with no trailing slash > - The third $uri/ matches the directory > - The fourth =404 returns the 404 error page if none of the preceding patterns match.

Taken from Serverfault answer

My updated version

If you add in the server block:

index index.html index.htm;

And modify try_files to look like this:

try_files $uri $uri/ =404;

It should work too.

Solution 2 - Url

A somewhat simpler solution, that worked for me, is to disable absolute redirects with absolute_redirect off; as in the following example:

server {
    listen 80;
    server_name  localhost;
    absolute_redirect off;

    location /foo/ {
        proxy_pass http://bar/;
    }

If I run curl on on http://localhost:8080/foo, I can see that the Location header in the redirect HTTP response is given as /foo/ and not http://localhost/foo/.

$ curl -I http://localhost:8080/foo
HTTP/1.1 301 Moved Permanently
Server: nginx/1.13.8
Date: Tue, 03 Apr 2018 20:13:28 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: /foo/

From that, I assume any web-browser would do the right thing with the relative location. Tested on Chrome and it works fine.

Solution 3 - Url

try :

server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm index.php;
        if (-d $request_filename) {
            rewrite [^/]$ $scheme://$http_host$uri/ permanent;
        }
    }
}

Solution 4 - Url

Try changing

server_name  localhost;
# server_name_in_redirect off;

to

server_name  localhost:8080;
server_name_in_redirect on;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThat Brazilian GuyView Question on Stackoverflow
Solution 1 - UrlJohn WeldonView Answer on Stackoverflow
Solution 2 - UrlguiccbrView Answer on Stackoverflow
Solution 3 - Urlluc2View Answer on Stackoverflow
Solution 4 - UrlDave TurnerView Answer on Stackoverflow