Nginx/Location

From WhyAskWhy.org Wiki
Jump to: navigation, search

Location blocks

Pay close attention to what version of nginx a book or web resource is based on as behavior may change between releases [1]


According to the official documentation [2], this is how nginx processes a request:

nginx first searches for the most specific prefix location given by literal strings regardless of the listed order. In the configuration above the only prefix location is "/" and since it matches any request it will be used as a last resort. Then nginx checks locations given by regular expression in the order listed in the configuration file. The first matching expression stops the search and nginx will use this location. If no regular expression matches a request, then nginx uses the most specific prefix location found earlier.

The same thing, said a little differently according to Samuel at the RackCorp Industry Blog [3]:

The best way to think of things is that as a request comes in, Nginx will scan through the configuration to find a "location" line that matches the request. There are TWO modes that nginx uses to scan through the configuration file: literal string matching and regular expression checks. Nginx first scans through ALL literal string location entries in the order that they occur in the configuration file, and secondly scans through ALL the regular expression location entries in the order that they occur in the configuration file. So be aware – location ordering order DOES matter.


The information below is heavily borrowed from the Official nginx wiki.

Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location { } @ name { ... }
Default:
Context: server
location
Reference: location

This directive allows different configurations depending on the request URI. It can be configured using both literal strings and regular expressions. To use regular expressions, you must use a prefix:

  • ~ for case sensitive matching
  • ~* for case insensitive matching


There is no syntax for NOT matching a regular expression. Instead, match the target regular expression and assign an empty block, then use location / to match anything else.


Location Modifiers
Search Order Modifier Description Match Type Stops search on match
1st = The location URI must match the specified pattern exactly Simple string Yes
2nd ^~ The location URI must begin with the specified pattern Simple string Yes
3rd (None) The location URI must begin with the specified pattern Simple string No[1]
4th ~ The requested URI must be a case-sensitive match to the specified regular expression[4] Perl Compatible Regular Expressions Yes (first match)
4th ~* The requested URI must be a case-insensitive match to the specified regular expression Perl Compatible Regular Expressions Yes (first match)
N/A @ Defines a named location block.[5] Simple string Yes


The order in which location directives are checked is as follows:

  1. Directives with the = prefix that match the query exactly (literal string). 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.


-- The following needs to be cleaned up --

The matching is performed against a normalized URI, after decoding a text encoded in the “%XX” form, resolving references to relative path components “.” and “..”, and possible compression of two or more adjacent slashes into a single slash.

A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified by prepending them with the “~*” prefix (for case-insensitive matching), or with the “~” prefix (for case-sensitive matching). To find a location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the most specific one is searched. Then regular expressions are checked, in the order of their appearance in a configuration file. A search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then a configuration of the most specific prefix location is used.

Locations can be nested, with some exceptions mentioned below.



Details below.

To determine which location directive matches a particular query, the literal strings are checked first. Literal strings match the beginning portion of the query - the most specific match will be used. Afterwards, regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search. If no regular expression matches are found, the result from the literal string search is used.

For case-insensitive operating systems, like Mac OS X or Windows with Cygwin, literal string matching is done in a case insensitive way (0.7.7). However, comparison is limited to single-byte locale's only.

Regular expression may contain captures (0.7.40), which can then be used in other directives.

It is possible to disable regular expression checks after literal string matching by using "^~" prefix. If the most specific match literal location has this prefix: regular expressions aren't checked.

The "=" prefix forces an exact (literal) match between the request URI and the location parameter. When matched, the search stops immediately. A useful application is that if the request "/" occurs frequently, it's better to use "location = /", as that will speed up the processing of this request a bit, since the search will stop after the first comparison.

On exact match with literal location without "=" or "^~" prefixes search is also immediately terminated.[6].

It is important to know that nginx does the comparison against decoded URIs. For example, if you wish to match "/images/%20/test", then you must use "/images/ /test" to determine the location.

Example:

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 ] 
}
location ^~ /images/ {
  # matches any query beginning with /images/ and halts searching,
  # so regular expressions will not be checked.
  [ configuration C ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # matches any request ending in gif, jpg, or jpeg. However, all
  # requests to the /images/ directory will be handled by
  # Configuration C.   
  [ configuration D ] 
}

Example requests:

  • / -> configuration A
  • /documents/document.html -> configuration B
  • /images/1.gif -> configuration C
  • /documents/1.jpg -> configuration D

Note that you could define these 4 configurations in any order and the results would remain the same.

The prefix "@" specifies a named location. Such locations are not used during normal processing of requests, they are intended only to process internally redirected requests (see error_page, try_files).

References

  1. 1.0 1.1 In versions from 0.7.1 to 0.8.41, if a request matched the prefix location without the "=" and "^~" prefixes, the search also terminated and regular expressions were not checked.
  2. How nginx processes a request, A simple PHP configuration
  3. Nginx location and rewrite configuration made easy
  4. For case-insensitive operating systems such as Mac OS X and Cygwin, matching with prefix strings ignores a case (0.7.7). However, comparison is limited to one-byte locales.
  5. The prefix "@" specifies a named location. Such locations are not used during normal processing of requests, they are intended only to process internally redirected requests (see error_page, try_files).
  6. I've asked on the nginx forums whether this is still true with recent versions because it sounds like this page contradicts that information

Additional Info