How to stop nginx 301 auto redirect when trailing slash is not in URI?

16,756

There is a special kind of processing for this scenario, as per 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, or memcached_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;
}

(http://nginx.org/en/docs/http/ngx_http_core_module.html#location)

Share:
16,756

Related videos on Youtube

Geo C.
Author by

Geo C.

Updated on September 18, 2022

Comments

  • Geo C.
    Geo C. over 1 year

    Every time I try foobar.com/test in browser, nginx seems to redirect (301) the client to foobar.com/test/. This behaviour is unacceptable. The proxied server is a remote Apache web server. I have tried direct calls to the Apache server (without a proxy), and it does not redirect the client.

    Considering the nginx server configuration below, any idea how should I solve this?

    server {
            listen 80;
            server_name fooBar.com;
    
            location /test {
                    proxy_redirect off;
                    proxy_pass http://1.1.1.1:80/;
                    proxy_set_header Host $http_host;
                    proxy_set_header X-Forwarded-Host $http_host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto $scheme;
            }
    
    
            location /test/ {
                    proxy_redirect off;
                    proxy_pass http://1.1.1.1:80/;
                    proxy_set_header Host $http_host;
                    proxy_set_header X-Forwarded-Host $http_host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto $scheme;
            }
    }
    
    • Alexey Ten
      Alexey Ten about 8 years
      nginx.org/r/location see «If a location is defined by a prefix string that ends with the slash character…»
    • Tim
      Tim about 8 years
      Are you sure it's the server sending a 301? Could it be the browser? Can you see the 301 in the access logs?
    • Geo C.
      Geo C. about 8 years
      @AlexeyTen Thanks alot. I've read the docs and somehow that one sliped my eyes. You can put it as an answer and I will accept/upvote.
  • TomSawyer
    TomSawyer over 7 years
    what's different between using ip vs domain in proxy_pass? It fixes my trouble but i don't know how it works? Does nginx need to request some where for domain looking or reduce speed load?
  • x-yuri
    x-yuri almost 7 years
    It also seems to redirect if request without a trailing slash resolves to a directory. That may be its way of making relative links work in html.
  • user2163960
    user2163960 about 4 years
    Oh, how I wish I had found this nugget sooner. There seems to be a bug in this "special processing" as the 301 that is returned seems to ALWAYS use the port of the listen portion of the server config, and seems to ignore all proxy port related parameters. This breaks things when the server is visible on 443 externally, but is listening on port 8443 inside a docker container, for example. The 301 redirect ends up with port 8443 in it, and fails. The above solution is perfect.