Conflicting location blocks...

Maxim Dounin mdounin at
Tue Sep 16 11:56:37 MSD 2008


On Mon, Sep 15, 2008 at 05:00:04PM -0700, mike wrote:

>I have this config -
>The location block to set expires headers breaks the alias location.
>Is there a way to get them to both work?
>Everything that matches should issue an expires header.
>However, I want to alias /icommon to another path. According to the
>wiki this is the right syntax, but once again I am stuck with location
>confusion :)
>server {
>                listen 80;
>                server_name;
>                index index.php;
>                root /home/test/web/;
>                location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|html)$ {

Unrelated comment: there is no sense in leading '^.+'.

-                location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|html)$ {
+                location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {

>                        expires max;
>                }
>                location /icommon/ {
>                        alias /home/test/web/;
>                }
>I have to comment out the expires block for now, or it won't work. Is
>this a bug?

You misunderstood how locations work.  Only *one* location will be 
used for particular request.  Regex locations isn't an exception - 
if they match, *only* their configuration is used.  So with your 
config any match on regex will leave you with configuration 
without alias defined.

See for 
details on location matching.

> How else can I do an alias? I tried setting "root" for
>that location, and it "sorta" works, the problem is is it tries to
>append the location, which doesn't work for me, unless I rename the
>file paths and set the "root" to the directory above it...
>                location /icommon/ {
>                        root /home/test/web/;
>                }
>Maps to this then /home/test/web/;
>Would have to set root to /home/test/web/, and
>then rename "icommon" to "common" on the filesystem...

The root directive defines filesystem path for '/' request (i.e.  
root).  All requests are mapped to filesystem by appending request 
uri to root, i.e.  /icommon/blah ->  <root>/icommon/blah.  It 
doesn't matter where root was defined.

>I think there might be a slight bug in how "alias" handling is done?
>Shouldn't it basically be like redefining a "root" ?

These beasts are completely different.  While root defines fs path 
for '/', the alias defines fs path for the location itself, i.e:

     location /blah/ {
         alias  /path/to/files/;

will map '/blah/xxx' to '/path/to/files/xxx'.  Note that 
'/blah/' (the location itself) was stripped from uri before it was 
appended to path.

With root, 

     location /blah/ {
         root  /path/to/files/;

will map the same request ('/blah/xxx') to '/path/to/files/blah/xxx'.

The only problem with alias is that it can't be used in regex 
locations (well, not really problem - it doesn't make sense in 
regex locations), and thus your configuration above can't be easily 
converted to correct one be defining one more regex location for 
images in /icommon/.  Workaround is to use 'root' and 'rewrite ...  
break' instead of alias, e.g.:

     location /icommon/ {
         alias ...;
     location ~* ^/icommon/.*\.(jpg|...)$ {
         rewrite ^/icommon/(.*)  /common/$1  break;
         expires ...;
     location ~* \.*(jpg|...)$ {
         expires ...;

(alternatively, you may use expiremental nested locations, but 
there are issues with alias)

But generally better aproach is to restructure site so you may 
just add expires to normal location and doesn't bother with regex 
locations at all.

Maxim Dounin

More information about the nginx mailing list