Nginx location regex not working, how to enable regex

nginx

In the nginx config I just want to use a regex for the location but I can't get any regex to work.

With a plain string in the location path it works and I can access the file from the browser. Here from my config:

location /profile/491ecdcd4.png {
    root /srv/www/XXX/code/app/public;
}

But I want to specify the folder for all png files, so I want to do it via regex. But as soon as I switch to regex with the ~* I can't get it to work anymore. None of the following does work:

location ~* ^/profile/.*\.png$ {            # The regex like I would want it
location ~* /profile/491ecdcd4\.png$ {      # File name and line end
location ~* \/profile\/491ecdcd4\.png$ {    # Slashes escaped
location ~* "\/profile\/491ecdcd4\.png$" {  # Quotes around the regex
location ~* profile {                       # Just plain the path

If I specify the location like that, I get a 404 error when I try to access the png in the browser. ~ instead of ~* also doesn't work.

The whole config is like that (shortened):

server {
    listen      443 ssl;
    server_name XXX;

    ssl                 on;
    ssl_certificate     /srv/www/XXX/certs/cacert.chain.pem;
    ssl_certificate_key /srv/www/XXX/certs/privkey.pem;

    # Special treatment and the problematic section
    location ~* /profile/491ecdcd4.png {
        root /srv/www/XXX/code/app/public;
    }

    # For the rest
    location / {
        root /srv/www/XXX/code/app/build;
    }
}

“`

Any ideas?

nginx version: nginx/1.6.2

edit: I edited the answer for clarity.

Best Answer

You should read "understanding Nginx location block selection", particularly this part

location optional_modifier location_match {
   . . .
}

The location_match in the above defines what Nginx should check the request URI against. The existence or nonexistence of the modifier in the above example affects the way that the Nginx attempts to match the location block. The modifiers below will cause the associated location block to be interpreted as follows:

  • (none): If no modifiers are present, the location is interpreted as a prefix match. This means that the location given will be matched against the beginning of the request URI to determine a match.
  • =: If an equal sign is used, this block will be considered a match if the request URI exactly matches the location given.
  • ~: If a tilde modifier is present, this location will be interpreted as a case-sensitive regular expression match.
  • ~*: If a tilde and asterisk modifier is used, the location block will be interpreted as a case-insensitive regular expression match.
  • ^~: If a carat and tilde modifier is present, and if this block is selected as the best non-regular expression match, regular expression matching will not take place.

In short, you're using a prefix match as you have no ~ character. Once you fix that, I don't see any regular expression here. Here's a location with a regex I use for caching images as an example

location ~*  \.(jpg|jpeg|png|gif|css|js|ico|svg)$ {
  expires 8d;
}

You could ask another question if you need help working out the regular expression you need. I don't use them much so it takes me a while to get back up to speed each time I do it.