Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of location configuration example in Nginx Server

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly explains "case analysis of location configuration in Nginx server". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "case analysis of location configuration in Nginx server".

First of all, let me briefly introduce the types and matching rules of location, and take the example of nginx wiki as an 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]} location @ named {# such locations are not used during normal processing of requests, # they are intended only to process internally redirected requests (for example error_page, try_files) [configuration e]}

You can see that there are five different types of location in the above example, and the fourth one with the "~" prefix is the location,nginx that needs regular matching. During url parsing, the location,nginx has different priority rules for these five different types of location. The general rules are as follows:

1, if the string matches exactly to a location with a "=" prefix, it stops and uses the configuration of this location

2. The string matches the remaining non-regular and non-special location, and stops if it matches a location with the prefix "^ ~".

3, regular matching, matching order is the order in which location appears in the configuration file. If a regular location is matched, stop and use the configuration of that location; otherwise, use the location configuration with the maximum string match obtained in step 2.

For example, the following requests are:

1, /-> match exactly to the first location, match stops, using configuration a

The prefix part of the string is matched to the second location first, and then the regular match is performed. Obviously there is no match, then the configuration configurationb of the second location is used.

3 location location images / 1.jpg-> first of all, the prefix part of the string matches to the second location, but then the prefix matches to the third one, and then the maximum string facing this url in the configuration file is matched, and the location is prefixed with "^ ~", then regular matching is no longer performed, and finally configuration c is used.

4 congifuration congifuration: 1.jpg-> first the same string in the prefix part matches to the second jpg, and then the regular match is performed. If the regular match succeeds, use jpg d.

In fact, there is something wrong with nginx's url matching rules. In most cases, a url must do string matching first, and then do regular matching, but in fact, if you do regular matching first and then do string matching without matching, in many cases, you can save time for string matching. Anyway, let's take a look at the implementation in the nginx source code. Before introducing the matching location process, let's introduce the organization of location in nginx. In fact, in the configuration parsing phase, nginx stores string matching location and regular matching location in the following two fields of the loc configuration ngx_http_core_loc_conf_t structure of the http core module:

Ngx_http_location_tree_node_t * static_locations; (ngx_pcre) ngx_http_core_loc_conf_t * * regex_locations; if

From the types of these two fields, we can see that the string matching location is organized into a location tree, while the regular matching location is just an array.

Location tree and regex_locations array creation process in ngx_http_block: / * create location trees * / for (s = 0; s

< cmcf->

Servers.nelts; slots +) {clcf = cscfp [s]-> ctx- > loc_ confs [NGX _ http_core_module.ctx_index]; if (ngx_http_init_locations (cf, cscfp [s], clcf)! = ngx_ok) {return ngx_conf_error;} if (ngx_http_init_static_location_trees (cf, clcf)! = ngx_ok) {return ngx_conf_error;}}

After reading the configuration, all server are saved in the servers array in the main configuration of the http core module, and the location in each server is stored in the locations queue in the loc configuration of the http core module in the order in which they appear in the configuration. In the above code, the location of each server is sorted and classified first, which occurs in the ngx_http_init_location () function:

Static ngx_int_t ngx_http_init_locations (ngx_conf_t * cf, ngx_http_core_srv_conf_t * cscf, ngx_http_core_loc_conf_t * pclcf) {. Locations = pclcf- > locations;... / * sort location by type. The sorted queue: (exact_match or inclusive) (sorted, if an exact_match name is the same as inclusive location, exact_match comes first) | regex (not sorted) | named (sorted) | noname (unsorted) * / ngx_queue_sort (locations, ngx_http_cmp_locations); named = null; n = 0 # if (ngx_pcre) regex = null; r = 0; # endif for (Q = ngx_queue_head (locations); Q! = ngx_queue_sentinel (locations); Q = ngx_queue_next (Q)) {lq = (ngx_http_location_queue_t *) Q; clcf = lq- > exact? Lq- > exact: lq- > inclusive; / * since there may be nested location, that is, the location nested in the location, we need to recursively deal with the nested location * / if (ngx_http_init_locations (cf, null, clcf)! = ngx_ok) {return ngx_error;} # if (ngx_pcre) if (clcf- > regex) under the current location. If (regex = = null) {regex = Q;} continue;} # endif if (clcf- > named) {nails; if (named = = null) {named = Q;} continue;} if (clcf- > noname) {break }} if (Q! = ngx_queue_sentinel (locations)) {ngx_queue_split (locations, Q, & tail);} / * if there are named location, save them in the named_locations array of the server to which they belong * / if (named) {clcfp = ngx_palloc (cf- > pool, (n + 1) * sizeof (ngx_http_core_loc_conf_t * *)) If (clcfp = = null) {return ngx_error;} cscf- > named_locations = clcfp; for (Q = named; Q! = ngx_queue_sentinel (locations); Q = ngx_queue_next (Q)) {lq = (ngx_http_location_queue_t *) Q; * (clcfp++) = lq- > exact;} * clcfp = null Ngx_queue_split (locations, named, & tail) } # if (ngx_pcre) / * if there are regular matching location, save them in the regex_locations array of the loc configuration of the http core module of the server to which they belong. The storage location here is different from that of named location because named location can only exist in server. Regex location can be used as nested location * / if (regex) {clcfp = ngx_palloc (cf- > pool, (r + 1) * sizeof (ngx_http_core_loc_conf_t *)) If (clcfp = = null) {return ngx_error;} pclcf- > regex_locations = clcfp; for (Q = regex; Q! = ngx_queue_sentinel (locations); Q = ngx_queue_next (Q)) {lq = (ngx_http_location_queue_t *) Q; * (clcfp++) = lq- > exact;} * clcfp = null Ngx_queue_split (locations, regex, & tail);} # endif return ngx_ok;}

In the above steps, the regular matching location is saved, and the location tree is established in ngx_http_init_static_location_trees:

Static ngx_int_t ngx_http_init_static_location_trees (ngx_conf_t * cf, ngx_http_core_loc_conf_t * pclcf) {ngx_queue_t * Q, * locations; ngx_http_core_loc_conf_t * clcf; ngx_http_location_queue_t * lq; locations = pclcf- > locations; if (locations = = null) {return ngx_ok } if (ngx_queue_empty (locations)) {return ngx_ok;} / * also because of nested location, we need to recurse * / for (Q = ngx_queue_head (locations); Q! = ngx_queue_sentinel (locations); Q = ngx_queue_next (Q)) {lq = (ngx_http_location_queue_t *) Q; clcf = lq- > exact? Lq- > exact: lq- > inclusive; if (ngx_http_init_static_location_trees (cf, clcf)! = ngx_ok) {return ngx_error }} / * inclusive and exact type location with the same name in the join queue, that is, if the location name of an exact_match is the same as the location name that matches the ordinary string, they are combined into a node and stored under the node's exact and inclusive, respectively. The purpose of this step is actually to remove the duplicates. Prepare for the following establishment of the sort tree * / if (ngx_http_join_exact_locations (cf, locations)! = ngx_ok) {return ngx_error } / * Recursive each location node to get a list of location with its prefix name, save it in the list field of the current node * / ngx_http_create_locations_list (locations, ngx_queue_head (locations)); / * Recursively establish a location ternary sort tree * / pclcf- > static_locations = ngx_http_create_locations_tree (cf, locations, 0) If (pclcf- > static_locations = = null) {return ngx_error;} return ngx_ok;}

After being processed by the ngx_http_init_location () function, the locations queue is already sorted, and the main work of establishing the trigeminal tree is completed in ngx_http_create_locations_list () and ngx_http_create_locations_tree (). These two functions are recursive functions. The first function recurses each node in the locations queue to get the location prefixed with the name of the current node. And save it under the list field of the current node, for example, for the following location:

Location / xyz {} location = / xyz {} location / xyza {} location / xyzab {} location / xyzb {} location / abc {} location / efg {} location / efgaa

The result of sorting is / abc / efg / efgaa = / xyz / xyz / xyza / xyzab/xyzb, and the result of removing duplicates is / abc / efg / efgaa / xyz / xyza / xyzab/xyzb,ngx_http_create_locations_list ():

Finally, take a look at the ngx_http_create_locations_tree function:

Static ngx_http_location_tree_node_t * ngx_http_create_locations_tree (ngx_conf_t * cf, ngx_queue_t * locations, size_t prefix) {. / * the root node is the intermediate node of the locations queue * / Q = ngx_queue_middle (locations); lq = (ngx_http_location_queue_t *) Q; len = lq- > name- > len-prefix Node = ngx_palloc (cf- > pool, offsetof (ngx_http_location_tree_node_t, name) + len); if (node = = null) {return null;} node- > left = null; node- > right = null; node- > tree = null; node- > exact = lq- > exact; node- > inclusive = lq- > inclusive Node- > auto_redirect = (u_char) ((lq- > exact & & lq- > exact- > auto_redirect) | | (lq- > inclusive & & lq- > inclusive- > auto_redirect)); node- > len = (u_char) len; ngx_memcpy (node- > name, & lq- > name- > data [prefix], len); / * disconnect / ngx_queue_split (locations, Q, & tail) from the intermediate node If (ngx_queue_empty (locations)) {/ * ngx_queue_split () insures that if left part is empty, * then right one is empty too * / goto inclusive;} / * get the left subtree from the left half of locations * / node- > left = ngx_http_create_locations_tree (cf, locations, prefix); if (node- > left = = null) {return null } ngx_queue_remove (Q); if (ngx_queue_empty (& tail)) {goto inclusive;} / * get the right subtree from the right half of locations * / node- > right = ngx_http_create_locations_tree (cf, & tail, prefix); if (node- > right = = null) {return null;} inclusive: if (& lq- > list) {return node } / * get tree subtree from list queue * / node- > tree = ngx_http_create_locations_tree (cf, & lq- > list, prefix + len); if (node- > tree = = null) {return null;} return node;} location tree node ngx_http_location_tree_node_s structure: struct ngx_http_location_tree_node_s {ngx_http_location_tree_node_t * left Ngx_http_location_tree_node_t * right; ngx_http_location_tree_node_t * tree; ngx_http_core_loc_conf_t * exact; ngx_http_core_loc_conf_t * inclusive; u_char auto_redirect; u_char len; u_char name [1];}

The location tree structure uses the three fields of left,right,tree. Location tree is actually a ternary string sort tree, and if a node only considers the left and right subtrees, it is a balanced tree, and its establishment process is somewhat similar to the process of establishing a balanced sort binary tree, sorting first and then inserting the nodes found by binary search. The tree node of ngx_http_location_tree_node_s is also a balanced sort tree, which is built using the list obtained by ngx_http_create_locations_list (), that is, the name of the node is the prefix of all the node names in its tree subtree, so the names of all nodes in the tree subtree do not need to save the common prefix, and when looking up, if you turn to the tree node. It is also the string that no longer needs to compare the parent node.

The ngx_http_create_locations_tree () function is very clear, and it takes one parameter, queue locations, which returns a trigeminal tree, the root node is the middle node of locations, its left subtree is the location tree established by the left half of the locations queue, and the right subtree is the tree established by the tree,tree node established by the right half of the location queue for the root node's list queue.

The resulting location tree is as follows (the full name of the tree node is listed in the figure for ease of reading):

Ps: about location modifier

1. =

This exactly matches the specified pattern, and the pattern here is restricted to simple strings, which means regular expressions cannot be used here.

Example:server {server_name jb51.net; location = / abcd {[…] }}

Match:

Http://jb51.net/abcd # exactly matches http://jb51.net/abcd # if the system running nginx server itself is not case-sensitive, such as windows, then it also matches the http://jb51.net/abcd?param1 m2 # ignores the query string parameter (query string arguments), which is the param1 m2 http://jb51.net/abcd/ # mismatch after / abcd Because there is a trailing slash at the end, nginx does not think that this is an exact match http://jb51.net/abcde # mismatch, because it is not an exact match

2. (none)

You don't have to write location modifier, nginx can still match pattern. In this case, match the uri that starts with the specified patern. Note that the uri here can only be a normal string, not a regular expression.

Example:server {server_name jb51.net; location / abcd {[…] }}

Match:

Http://jb51.net/abcd # exactly matches http://jb51.net/abcd # if the system running nginx server itself is case-insensitive, such as windows, then it also matches the http://jb51.net/abcd?param1 m2 # ignore query string parameter (query string arguments) This is what follows / abcd? there is a backslash (trailing slash) at the end of the param1 abcd m2 http://jb51.net/abcd/ # is also within the matching range http://jb51.net/abcde # still matches because the uri begins with pattern

3. ~

The location modifier is case sensitive, and the pattern must be a regular expression

Example:server {server_name jb51.net; location ~ ^ / abcd$ {[…] }}

Match:

Http://jb51.net/abcd # exactly matches http://jb51.net/abcd # mismatch, ~ case-sensitive http://jb51.net/abcd?param1 m2 # ignores the query string parameter (query string arguments), here is the mismatch of / abcd followed by? param1 2 http://jb51.net/abcd/ #, because there is a backslash (trailing slash) at the end Does not match regular expression ^ / abcd$ http://jb51.net/abcde # does not match regular expression ^ / abcd$

Note: for systems that are case-insensitive, such as windows, ~ and * don't work, mainly because of the operating system.

4. ~ *

Similar to ~, but this location modifier is not case-sensitive, and pattern must be a regular expression

Example:server {server_name jb51.net; location ~ * ^ / abcd$ {[…] }}

Match:

Http://jb51.net/abcd # exactly matches http://jb51.net/abcd # match, which is its case-insensitive feature http://jb51.net/abcd?param1 m2 # ignores the query string parameter (query string arguments), here is the param1 2 http://jb51.net/abcd/ # after / abcd does not match because there is a backslash (trailing slash) at the end Does not match regular expression ^ / abcd$ http://jb51.net/abcde # does not match regular expression ^ / abcd$

5. ^ ~

The matching situation is similar to that of 2. (none), where the uri that begins with the specified matching pattern is matched, except that once the match is successful, the nginx stops looking for other location blocks to match (related to the location matching order)

6. @

Used to define a location block that cannot be accessed by an external client and can only be accessed by nginx internal configuration instructions, such as try_files or error_page

Thank you for your reading, the above is the content of "location configuration instance Analysis in Nginx Server". After the study of this article, I believe you have a deeper understanding of the problem of location configuration instance analysis in Nginx server, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report