Nginx location override does not do what I want, opinions welcome

mediawikinginxregex

I have a Nginx configuration file that works for everything except one feature.
I have installed a Mediawiki, it works pretty well except at showing pictures (loading them works fine).

Whereas (sorry for castrating proper links, the site says I don't have enough rep to write them)

www.domain.tld/wiki/File:Rosa_grande.jpg

results in a 404 error,

www.domain.tld/wiki/index.php?title=File:Rosa_grande.jpg

works OK.

So I started digging in the Nginx configuration and noticed how the "/" location takes precedence to the images location. The 404 comes out because I have not installed an index.php file in the root (yet).

In particular, given a file located in:

/wiki/images/7/78/Rosa_grande.jpg

I have manually created a location that should throw (for debugging purposes only!) an error 500:

location /wiki/images/.*\.(js|css|png|jpg|jpeg|gif|ico)$ {
more_set_headers 'Location 6';

return 500;
}

The regexp parses good at http://www.regexplanet.com/advanced/java/index.html and indeed matches with "jpg".

I also tried putting ^~ /wiki/images/…. but to no result.

Every attempt at getting in this location gets overridden by this other location:

    location / {
            more_set_headers 'Location 10';
            try_files $uri $uri/ /index.php?q=$uri&$args =404;
    }

    location ~ \.php$ {
            more_set_headers 'Location 20';
            try_files $uri =404; # This is not needed if you have cgi.fix_pathinfo = 0 in php.ini (you should!)

            include include/php_fpm_pass.conf;
    }

I must keep said / location including the index.php call because it manages other web apps. As you can see I have also added some useful debugging more_set_headers statements to show the actual location(s) being processed.

Typing:

curl -I http://127.0.0.1:8080/wiki/images/7/78/Rosa_grande.jpg

should show an error 500 (/wiki/images location hit) and the header should display "location 6"

but instead it shows a 404 and location 10.

HTTP/1.1 404 Not Found
Server: nginx
Date: Wed, 31 Jul 2013 09:16:01 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: 10

If I put the Rosa_grande.jpg file in place, I get a "200 OK" message and still location 10:

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 31 Jul 2013 09:09:02 GMT
Content-Type: image/jpeg
Content-Length: 19735
Last-Modified: Tue, 30 Jul 2013 09:50:15 GMT
Connection: keep-alive
ETag: "51f78c57-4d17"
Location: 10
Accept-Ranges: bytes

Best Answer

The answer to the first portion of my issue ended up being easy:

I should not have used:

location /wiki/images/.*\.(js|css|png|jpg|jpeg|gif|ico)$ {

but

location ~* /wiki/images/.*\.(png|jpg|jpeg|gif|ico)$ {

because only the latter is going to actually process the regexp before the "/" "catch all".

Next comes the second phase:

Transform a Mediawiki "pretty URL" like:

www.domain.tld/wiki/File:Rosa_grande.jpg

into a

www.domain.tld/wiki/index.php?title=File:Rosa_grande.jpg

call.

In fact I did not find any "obvious" mapping from the

File:Rosa_grande.jpg

URL to the actual

wiki/images/7/78/Rosa_grande.jpg

as I miss a way to find out that File:Rosa_grande.jpg maps to a file stored in a "/7/78/" subdirectoy.

Needless to say, all the other Mediawiki modules worked flawlessy with "pretty URLs", even those with a "/wiki/Action:Something" URL except for "/wiki/File:Something".

The solution ended up being rather simple: a rewrite to the proper, "ugly" URL:

    location ~* ^/wiki/File:(.*\.(png|jpg|jpeg|gif|ico))$ {
            # more_set_headers 'Location 1.7: /wiki/File';
            rewrite ^/wiki/File:(.*\.(png|jpg|jpeg|gif|ico))$ /wiki/index.php?title=File:$1 last;
    }

I am not sure the rewrite regexp is optimized but it has the awesome property of actually getting the job done.