Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to control NGINX 'Location' directive matching order?

I'm trying to optimize my 'location' directives and cannot find a good way of determining if a specific location match is even attempted. Using echo inside the location block doesn't help here.

The NGINX ngx_http_core_module documentation is somewhat confusing.

To use regular expressions, you must use a prefix:

  1. ~ For case sensitive matching

  2. ~* For case insensitive matching

How the match is performed:

  1. Directives with the = prefix that match the query exactly. If found, searching stops.

  2. All remaining directives with conventional strings. If this match used the ^~ prefix, searching stops.

  3. Regular expressions, in the order they are defined in the configuration file.

  4. If #3 yielded a match, that result is used. Otherwise, the match from #2 is used.

Number 2 here says "conventional strings" but then says it can be used with the ^~ prefix. Doesn't ~ imply a RegExp? If not, how does it determine what is an isn't a RegExp?

Specifically, I want the following:

  1. Serve anything out of literal /assets directly. STOP SEARCH.

  2. Serve anything matching RegExp \.php$|/$ via fast-CGI STOP SEARCH.

  3. Serve everything else directly via literal /

This way, there is only a / match attempt for non-dynamic files served from outside of assets.

I have:

location ^~ /assets {}      # search-terminating literal? or regex?
location ~ \.php$|/$ {}
location / {}               # is this match always attempted?

From the document, it looks as though the actual order would be 1-3-2, always running the literal / match. Yes, this optimization won't make any difference for real performance, but I just want to clear up some ambiguity.

like image 576
leeoniya Avatar asked Dec 08 '11 20:12

leeoniya


People also ask

Does order of the location blocks matter in Nginx?

Yes, it does and totally depends on different directives specified within the different context supported by Nginx.

How does Nginx match locations?

To find a location match for an URI, NGINX first scans the locations that is defined using the prefix strings (without regular expression). Thereafter, the location with regular expressions are checked in order of their declaration in the configuration file.

What does ~* mean in Nginx?

~ Tilde means that this location will be interpreted as a case-sensitive RE match. ~* Tilde followed by an asterisk modifier means that the location will be processed as a case-insensitive RE match.

What is location in Nginx conf?

By default the file is named nginx. conf and for NGINX Plus is placed in the /etc/nginx directory. (For NGINX Open Source , the location depends on the package system used to install NGINX and the operating system. It is typically one of /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx.)


1 Answers

From the wiki:

location  = / {
  # matches the query / only.
  [ configuration A ] 
}
location  / {
  # matches any query, since all queries begin with /, but regular
  # expressions and any longer conventional blocks will be
  # matched first.
  [ configuration B ] 
}

So, this will be matched first: location ~ \.php$ {}

Even though assets are served out of location / {}

Inside the php block you also want to secure against malicious uploads before passing to fastcgi:

if ($uri ~* "^/uploads/") {
  return 404;
}

As you can see nginx works a little bit differently than you might expect.

like image 73
m33lky Avatar answered Oct 25 '22 18:10

m33lky