nginx location match visible
Table of Contents
#Purpose
This project aims to help guys understand how does nginx location match work. Wish you can learn something from this project
In Nginx Website, it include these docs as the following:
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: β
Context: server, location
A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding β*β modifier (for case-insensitive matching), or the ββ modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The 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 the configuration of the prefix location remembered earlier is used.
location blocks can be nested, with some exceptions mentioned below.
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.
Regular expressions can contain captures (0.7.40) that can later be used in other directives.
If the longest matching prefix location has the β^~β modifier then regular expressions are not checked.
Also, using the β=β modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a β/β request happens frequently, defining βlocation = /β will speed up the processing of these requests, as search terminates right after the first comparison. Such a location cannot obviously contain nested locations.
Let's explain something about this:
- the exact match is the best priority
- the prefix match is the second priority, but there are two type prefix match like
^~
and/
, if you are ^~, nginx will skip regular match else it will continue to match all the regular match.
a little fake code as the following:
def 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]
if uri in regex_match:
return regex_match[uri]
return rv
Letβs illustrate the above by an example:
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
- if we are requesting "/index.html", it will match
configureation B
. - if we are requesting "/1.jpg", it will find
configuration B
at first, then regular matchconfiguration E
finally. - if we are requesting "/images/xxx", it will match
configuration D
, but never match regular location becasuse of ^~
#Detail Letβs talk about the something about nginx location data struct when nginx match location.
Firstly Nginx will sort the location list by the order
extra_match(alpha order)->prefix(alpha order)->regular(order write by conf)->named(alpha order)->noname(order write by conf)
Then Nginx will move named and noname location from the list, because normal request will not hit these location directly.
And Nginx will split regular location to signle list like the following.
Finally Nginx transform the location list only have match and prefix to a ternary tree like the following.
Contributing
To contribute to ngx_http_updown, clone this repo locally and commit your code on a separate branch.
PS: PR Welcome
This project consist of the three parts:
-
Parse the nginx conf: nginx conf parser are not implement like compiler, it's just string manipulate. And now it cannot support rewrite directive.
-
Construct the nginx static location treeγregular location list and Implement the nginx_find_location method: it translate nginx c code to js code by manual
-
Render nginx match process: now render the process is deal with by canvas api, it could be implmented better actually.
The code of this project is a little dirty but workaround. It's enough to help guys to know how to work when nginx match location.
Wish it can help you as more as what I have learn from nginx code.
Author
GitHub @detailyang
License
nginx-location-match-visible is licensed under the MIT license.