Some URIs return static content, some are distributed to back-end servers, etc. Today, to understand its matching rules
The simplest example of a location is as follows
server {
server_name website.com;
location /admin/ {
# The configuration you place here only applies to
# http://website.com/admin/}}Copy the code
Location support of syntactic location [= | | | ~ ~ * ^ ~ | @] pattern {… }, it looks complicated at first glance. Let’s take a look at each one.
Location decorator type
The “=” modifier: Requires paths to match exactly
server {
server_name website.com;
location = /abcd {
[…]
}
}
Copy the code
http://website.com/abcd
matchinghttp://website.com/ABCD
Might matchOr not, depending on whether the operating system’s file system is case-sensitive. Ps: Mac is case insensitive by default, git use will be a big hole.http://website.com/abcd?param1¶m2
matchingThe querystring are ignored.http://website.com/abcd/
Don’t match“With an ending/
http://website.com/abcde
Don’t match
“~” modifier: case-sensitive regular match
server { server_name website.com; Location ~ ^/abcd${[... }}Copy the code
^/abcd$This regular expression indicates that the string must start with a slash, end with $, and be abcd in the middle
http://website.com/abcd
matching(Perfect match)http://website.com/ABCD
Don’t match, case sensitivehttp://website.com/abcd?param1¶m2
matchinghttp://website.com/abcd/
Don’t matchCannot match the regular expressionhttp://website.com/abcde
Don’t matchCannot match the regular expression
“~*” is a case-insensitive regular match
server { server_name website.com; Location ~* ^/abcd${[... }}Copy the code
http://website.com/abcd
matching(Perfect match)http://website.com/ABCD
matching(Case insensitive)http://website.com/abcd?param1¶m2
matchinghttp://website.com/abcd/
Don't match
Cannot match the regular expressionhttp://website.com/abcde
Don't match
Cannot match the regular expression
## “^~” modifier: prefix match If the location is the best match, then regular expression checking is no longer performed on strings that match the location. Note that this is not a regular expression match; it is intended to take precedence over regular expression matches
Order and priority of the search
When there are multiple location rules, nginx has a set of complex rules with the following priorities:
- An exact match
=
- Prefix matching
^ ~
(Stop subsequent re searches immediately) - Regex matches in order of file
~
or~ *
- Matches prefix matches without any decorations.
The general idea of the rule is this
A prefix match with ^~ is searched for if there is none, a regular match is performed if there is none, and the result of the prefix match (if any) is returned.
If the above rules are hard to understand, look at 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] // Note that this is not presentreturn, and here is the longest matchif uri in regex_match:
returnRegex_match [uri] // Return if foundreturn rv
Copy the code
A simplified Node.js code looks like this
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) {
returnregex_locations[i]; }}}return rc;
}
Copy the 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 702Copy the code
According to the above rules, the second will have higher priority
Case 2
server {
server_name website.com;
location /document {
return 701;
}
location ~* ^/document$ {
return 702;
}
}
curl -I website.com:8080/document
Copy the code
The second matches the regular expression and takes precedence over the first regular prefix match
Case 3
server {
server_name website.com;
location ^~ /doc {
return 701;
}
location ~* ^/document$ {
return702; }} curl http://website.com/document HTTP / 1.1 701Copy the code
After the first prefix match ^~ is hit, the re match is not searched, so it is hit first
Case 4
server {
server_name website.com;
location /docu {
return 701;
}
location /doc {
return702; }}Copy the code
The curl -i website.com: 8080 / document to return to the HTTP / 1.1 701,
server {
server_name website.com;
location /doc {
return 702;
}
location /docu {
return701; }}Copy the code
The curl -i website.com: 8080 / document still returns the HTTP / 1.1 701
Under prefix matching, the longest location matching is returned, regardless of the location order
Case 5
server {
listen 8080;
server_name website.com;
location ~ ^/doc[a-z]+ {
return 701;
}
location ~ ^/docu[a-z]+ {
return702; }}Copy the code
The curl -i website.com: 8080 / document back to HTTP / 1.1 701
Let’s switch the order
server {
listen 8080;
server_name website.com;
location ~ ^/docu[a-z]+ {
return 702;
}
location ~ ^/doc[a-z]+ {
return701; }}Copy the code
The curl -i website.com: 8080 / document back to HTTP / 1.1 702
Re matching is returned using the order found in the file