preventing rewrite loops with "index"

Marcus Clyne ngx.eugaia at gmail.com
Mon Jan 25 09:58:18 MSK 2010


Hi,

Maxim Dounin wrote:
> Hello!
>
> On Sun, Jan 24, 2010 at 10:45:32PM +0100, Piotr Sikora wrote:
>
>   
>>> 2. Note "internal" in location /users/.  It means "only visible
>>> for internal redirects", so even user called "users" should be
>>> correctly processed by the first location.
>>>       
>> Actually, this isn't true. Any attempt to access internal location
>> results in 404 response.
>>
>> You can verify this with very simple configuration:
>>
>> server {
>>    listen 8000;
>>    location / { return 500; }
>>    location /x { internal; return 500; }
>> }
>>
>> Accessing /x will result in 404 response.
>>     
The example is obviously correct, but it doesn't truly explain the 
reason for getting the 404 for accessing /users/xxx URLs (even though 
the result is almost the same).  The reason is to do with the order that 
locations are handled, specifically that ^~ locations are handled before 
~* and ~ ones, and if they match, then the regex ones aren't tested.  If 
you try to access the URL /users/xxx, it will therefore match the second 
location given by ^~, and return 404 because it's an internal location.  
Therefore, trying access anything under a user named 'users' will fail 
(though the URL /users on its own is ok, because that will match the 
regex location and not the ^~ location).

Using location /users in the original locations will result in an 
internal server error, because the regex will be caught before the 
/users location each time the URL is checked, creating an infinite loop.
>
> True, I was wrong here.  Actually I wasn't sure and that's why I 
> used "should".  :)
>
>   
>> This is a bug and it's somewhere on my TODO list.
>>     
>
> Strictly - it's not bug, it's just how internal locations work 
> now.  But I agree it's a probably good idea to change semantics 
> and make them just invisible for external requests.
>   
I was under the impression that the way internal requests currently work 
was a consciously-chosen decision, and was considered a feature.  It's a 
useful one IMHO.  Surely if you want to make a location fully 
'invisible' (i.e. both internally and externally), you can just add the 
directive 'return 404;' to the location.

Marcus.




More information about the nginx mailing list