Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx causes 301 redirect if there's no trailing slash

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;     }  } 
like image 273
That Brazilian Guy Avatar asked Mar 21 '13 18:03

That Brazilian Guy


2 Answers

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.

like image 57
John Weldon Avatar answered Sep 24 '22 04:09

John Weldon


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.

like image 26
guiccbr Avatar answered Sep 21 '22 04:09

guiccbr