9

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;
        }
}
4
  • 3
    nginx.org/r/location see «If a location is defined by a prefix string that ends with the slash character…»
    – Alexey Ten
    Feb 25, 2016 at 14:58
  • Are you sure it's the server sending a 301? Could it be the browser? Can you see the 301 in the access logs?
    – Tim
    Feb 25, 2016 at 18:39
  • @Tim It can't be the browser because when I try direct Apache web server request there is no redirect. So it must be something from nginx side
    – Geo C.
    Feb 29, 2016 at 21:38
  • 1
    @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.
    – Geo C.
    Feb 29, 2016 at 21:41

1 Answer 1

16

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)

3
  • 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?
    – TomSawyer
    Dec 27, 2016 at 6:33
  • 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.
    – x-yuri
    Jun 15, 2017 at 8:37
  • 3
    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. Apr 9, 2020 at 1:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.