Nginx's location implements fine-grained processing of requests, some URI s return static content, some distribute to back-end servers, and so on. Understand its matching rules thoroughly today
An example of the simplest location is as follows
server { server_name website.com; location /admin/ { # The configuration you place here only applies to # http://website.com/admin/ } } Copy Code
The syntax supported by location [=|~|~*|^~|@] pattern {...} is complex at first glance, so look at it one by one.
location modifier type
"=" modifier: requires path to match exactly
server { server_name website.com; location = /abcd { [...] } } Copy Code
- http://website.com/abcd match
- http://website.com/ABCD may or may not match, depending on whether the operating system's file system is case-sensitive.ps: Mac defaults to case insensitive, git usage can have pits.
- Http://website.com/abcd?Param1¶m2 match, querystring ignored
- http://website.com/abcd/mismatch, with end/
- http://website.com/abcde mismatch
"~" modifier: case-sensitive regular matching
server { server_name website.com; location ~ ^/abcd$ { [...] } } Copy Code
^/abcd$This regular expression means that the string must start with/end with $and be ABCD in the middle
- http://website.com/abcd match (exact match)
- http://website.com/ABCD mismatch, case sensitive
- Http://website.com/abcd?Param1¶m2 match
- http://website.com/abcd/mismatch, cannot match regular expression
- http://website.com/abcde does not match, cannot match regular expression
'~*'case-insensitive regular matching
server { server_name website.com; location ~* ^/abcd$ { [...] } } Copy Code
- http://website.com/abcd match (exact match)
- http://website.com/ABCD match (case insensitive)
- Http://website.com/abcd?Param1¶m2 match
- http://website.com/abcd/ does not match, cannot match regular expression
- http://website.com/abcde does not match, cannot match regular expression
##'^~'modifier: Prefix matching If the location is the best match, then the modifier will no longer detect regular expressions for strings that match this location.Note that this is not a regular expression match; its purpose is to take precedence over regular expression matching
Order and priority of lookup
When there are multiple location rules, nginx has a more complex set of rules with the following priority:
- Exact Match =
- Prefix matches ^~ (stops subsequent regular searches immediately)
- Regular Matching in File Order ~or ~*
- Matches prefix matches without any modifications.
The general idea behind this rule is
Precise matching, prefix matching with ^~is found for none, regular matching for none, and prefix matching results are returned (if any)
If the above rules are not easy to understand, you can see the following pseudocode (very important)
function match(uri): rv = NULL if uri in exact_match: return exact_match[uri] if uri in prefix_match: if prefix_match[uri] is '^~': return prefix_match[uri] else: rv = prefix_match[uri] // Notice that there is no return,And here is the longest match if uri in regex_match: return regex_match[uri] // Find and return in file order return rv Copy Code
The code written by a simplified Node.js is as follows
function ngx_http_core_find_location(uri, static_locations, regex_locations, named_locations, track) { let rc = null; let l = ngx_http_find_static_location(uri, static_locations, track); if (l) { if (l.exact_match) { return l; } if (l.noregex) { return l; } rc = l; } if (regex_locations) { for (let i = 0 ; i < regex_locations.length; i ++) { if (track) track(regex_locations[i].id); let n = null; if (regex_locations[i].rcaseless) { n = uri.match(new RegExp(regex_locations[i].name)); } else { n = uri.match(new RegExp(regex_locations[i].name), "i"); } if (n) { return regex_locations[i]; } } } return rc; } Copy Code
case analysis
Case 1
server { server_name website.com; location /doc { return 701; # In this way, it is easy to know where the request is going } location ~* ^/document$ { return 702; # In this way, it is easy to know where the request is going } } curl -I website.com:8080/document HTTP/1.1 702 Copy Code
The second has a higher priority according to the above rules
Case 2
server { server_name website.com; location /document { return 701; } location ~* ^/document$ { return 702; } } curl -I website.com:8080/document Copy Code
The second matches the regular expression and takes precedence over the first common prefix match
Case 3
server { server_name website.com; location ^~ /doc { return 701; } location ~* ^/document$ { return 702; } } curl http://website.com/document HTTP/1.1 701 Copy Code
First prefix match ^~No more regular matches will be searched after hits, so the first hit will occur
Case 4
server { server_name website.com; location /docu { return 701; } location /doc { return 702; } } Copy Code
Curl-I website.com:8080/document returns HTTP/1.1 701,
server { server_name website.com; location /doc { return 702; } location /docu { return 701; } } Copy Code
Curl-I website.com:8080/document still returns HTTP/1.1 701
Under prefix matching, returns the longest matching location regardless of the location order
Case 5
server { listen 8080; server_name website.com; location ~ ^/doc[a-z]+ { return 701; } location ~ ^/docu[a-z]+ { return 702; } } Copy Code
Curl-I website.com:8080/document returns HTTP/1.1 701
Change the order
server { listen 8080; server_name website.com; location ~ ^/docu[a-z]+ { return 702; } location ~ ^/doc[a-z]+ { return 701; } } Copy Code
Curl-I website.com:8080/document returns HTTP/1.1 702
Regular matching uses the order in the file to find returns