3

This seems ridiculous but I've not found a working answer in over an hour of searching. When I access "http://oa.wechat.com/screen/index.html", it will cause a 301 redirect loop, like this:

"GET /screen/ HTTP/1.1" 301
"GET /screen/index.html/ HTTP/1.1" 301 
"GET /screen/index.html/index.html/ HTTP/1.1" 301 
... 

nginx verson: 1.5.6 nginx.conf

    server {
        listen  80;
        server_name oa.wechat.com;

        location ~ ^/screen/ {
            alias /data/screen/static/;
            index index.html;
        }  
    } 

Could anyone tell me the reason? Thanks very much.

i have checked nginx document. the right usage of 'alias':

    # use normal match like this
    location  /i/ {
      alias  /spool/w3/images/;
    }

    # use regex match like this
    location ~ ^/download/(.*)$ {
      alias /home/website/files/$1;
    }

the wrong way to use 'alias' is:

    location ~ ^/screen/ {
        alias /data/screen/static/;
        index index.html;
    }  

In this case, the request would be considered as a directory request, not file request, which will lead a redirect loop.

Anyway, Thanks Flesh very much!

3
  • I can't really figure out what's wrong, are you sure the 301 isn't generated from your app ? Commented Feb 11, 2014 at 15:01
  • from nginx access log, I can see that the request wasn't passed to backend server, just handled by nginx Commented Feb 12, 2014 at 1:44
  • I met the same issue today, still don't understand why nginx considered the request as a directory request, could you please explain this more specifically ? Thanks. Commented May 28, 2016 at 6:55

2 Answers 2

5

It's already trying to access index.html in that directory because it's the default of nginx's index directive. The problem is that you're using the index directive within a location block where it has a special meaning and executes an internal redirect (as documented).

Unless you know what you're doing, set the index directive within the server block. We end up with the following server block (be sure to read the comments).

server {
    # Both default values and not needed at all!
    #index      index.html;
    #listen     80;
    server_name oa.wechat.com;

    # Do not use regular expressions to match the beginning of a
    # requested URI without protecting it by a regular location!
    location ^~ /screen/ {
        alias /data/screen/static/;
    }

}

location examples

server {

    # Won't work because the /data is considered the new document root and
    # the new location matches the regular expression again.
    location ~ ^/screen/ {
        alias /data/screen/static/;
    }

    # Should work because the outer location limits the inner location
    # to start with the real document root (untested)
    location / {
        location ~ ^/screen/ {
            alias /data/screen/static/;
        }
    }

    # Should work as well above reason (untested)
    location / {
        location ~ ^(/screen/) {
            alias /data$1static/;
        }
    }

    # Might work as well because we are using the matching group
    # VERY BAD because we have a regular expression outside any regular location!
    location ~ ^(/screen/) {
        alias /data$1static/;
    }

    # Always works and allows nesting of more directives and is totally save
    location ^~ /screen/ {
        alias /data/screen/static/;
    }

}

Weblinks

Sign up to request clarification or add additional context in comments.

6 Comments

it works, no more redirect loop. But I really want to know why my previous config will cause a 301 loop, could you explain it for me?
As written in my answer, the index directive within a location block has a special meaning and will start redirecting indefinitely (well, up to 10 times because nginx is breaking the cascade itself afterwards).
location ~ ^/screen/ { alias /data/screen/static/; }this code will still cause a loop, but location ^~ /screen/ { alias /data/screen/static/; } this works fine. I will be appreciate if you could tell me the big difference
You're using a regular expression outside of any protecting regular location. That's just bad practice and might cause problems (like you found it here). Either enclose it (e.g. location / { location ~ ^/screen/ {} }) or don't use a regular expression (see my answer). Oh and the reason why this is causing the loop is the fact that both locations (/screen/ and /data/screen/static/) contain the /screen/ part.
when i changed to location ~ ^/screen/ { alias /data/abc/static/; } , it will also cause a loop.
|
1

you should move ^ location modifier from ^/screen/, then add ^ before ~, like this:

 `location ^~ /screen/ {
     alias /data/screen/static/;
     index index.html;
  }`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.