current position:Home>Analysis of location configuration in nginx server

Analysis of location configuration in nginx server

2022-04-29 19:26:56Billion cloud speed

Nginx Server location Configuration example analysis

This article mainly explains “Nginx The server in location Configuration example analysis ”, The explanation in the text is simple and clear , Easy to learn and understand , Next, please follow Xiaobian's ideas and go deeper slowly , Study and learn together “Nginx Server location Configuration example analysis ” Well !

        First of all, let me briefly introduce location Types and matching rules , With nginx wiki To illustrate :

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 ]  }

        As you can see in the above example 5 Different types of location, Among them the first 4 Strip “~” The prefix number is the one that needs regular matching location,nginx It's going on url When parsing this 5 Different types of location Have different priority rules , The general rules are as follows :

1, The string matches exactly to a band “=” Prefixed with location, Then stop , And use this location Configuration of ;

2, String matches the rest of the non regular and non special location, If it matches a band "^~" Prefixed location, Then stop ;

3, Regular matching , The matching order is location The order in which they appear in the configuration file . If it matches a regular location, Then stop , And use this location Configuration of ; otherwise , Use steps 2 With the largest string match location To configure .

       for example , For the following request :

1, /   ->   Match exactly to the... Th 1 individual location, Match stop , Use configuration a
2,/some/other/url    ->  First, the prefix part of the string matches to the 2 individual location, Then we do regular matching , Obviously there is no match , Then use the 2 individual location Configuration of configurationb
3,/images /1.jpg  ->  First, the prefix part of the string matches to the 2 individual location, But then on the second 3 individual location Also the prefix matches , And this is already in the configuration file url The largest string of matches , also location with "^~" Prefix , Then regular matching is no longer performed , End use configuration c
4,/some/other/path/to/1.jpg  -> First, the prefix part of the same string matches to the 2 individual location, Then we do regular matching , At this time, the regular matching is successful , Then use congifuration d

      nginx Of url The matching rule is actually a little inappropriate , Most of the time, one url String matching must be done first , Then do regular matching , But in fact, if you do regular matching first , There is no match Do string matching , In many cases, you can save the time of string matching . No matter what , Let's take a look first nginx The implementation in the source code , In introducing matching location Before the process , Let's introduce Give me a break nginx In the face location Organization style , In fact, in the configuration resolution phase ,nginx Match the string to location Regular matching location , respectively, Stored in http core Modular loc To configure ngx_http_core_loc_conf_t Below the structure 2 A field :

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

From here 2 The types of fields can be seen , String matching location Organized into a location tree, And regular matching location Just an array ,

location tree and regex_locations The array building process is in ngx_http_block in :/* create location trees */    for (s = 0; s < cmcf->servers.nelts; s++) {      clcf = cscfp[s]->ctx->loc_conf[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 configured reading , all server It's all stored in the http core Modular main The configuration of the servers Array , And each server Inside location Are saved in the order in which they appear in the configuration http core Modular loc Configured locations In line , In the above code, first for each server Of location Sort and sort , This step takes place in 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 by type location, The queue after sorting : (exact_match  or  inclusive) ( Well, sort it out , If a exact_match Name and inclusive location identical ,exact_match At the top )     | regex( unsorted )| named( Well, sort it out ) | 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;     /*  Because there may be nested location, That is to say location Nested inside location, Here we need to deal with the current... Recursively location Below nested location */     if (ngx_http_init_locations(cf, null, clcf) != ngx_ok) {       return ngx_error;     }  #if (ngx_pcre)      if (clcf->regex) {       r++;        if (regex == null) {         regex = q;       }        continue;     }  #endif      if (clcf->named) {       n++;        if (named == null) {         named = q;       }        continue;     }      if (clcf->noname) {       break;     }   }    if (q != ngx_queue_sentinel(locations)) {     ngx_queue_split(locations, q, &tail);   }   /*  If there is named location, Save them in their server Of named_locations Array  */   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 is a regular match location, Save them in their server Of http core Modular loc Configured regex_locations  Array ,      Here and named location The reason why the storage location is different is due to named location There can only be server Inside , and regex location It 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; }

       The above steps will be regular matching location It's preserved ,location tree Based on ngx_http_init_static_location_trees In the middle of :

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;   }   /*  This is also due to nested location, You 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;     }   }   /* join The same name in the queue inclusive and exact type location, That is, if one of them exact_match Of location The name matches the normal string location If the name is the same ,      Just combine them into one node , Save them in the nodes respectively exact and inclusive Next , The purpose of this step is actually to remove the weight , Prepare for the establishment of sorting tree later  */   if (ngx_http_join_exact_locations(cf, locations) != ngx_ok) {     return ngx_error;   }   /*  Recursive each location node , Get the name of the current node as its prefix location A list of , Saved in the current node list Under the field  */   ngx_http_create_locations_list(locations, ngx_queue_head(locations));    /*  Recursive establishment location Trident 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 ngx_http_init_location() After function processing ,locations The queue is already in order , The main work in the process of establishing trigeminal tree is ngx_http_create_locations_list() and ngx_http_create_locations_tree() Finish in , this 2 individual Functions are recursive functions , The first 1 A function recurses locations Each node in the queue , Get the name prefixed with the name of the current node location, And save it in the of the current node list Field Next , 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, The result is /abc  /efg   /efgaa   /xyz  /xyza /xyzab/xyzb,ngx_http_create_locations_list() The result after execution is :

Nginx Server location Configuration example analysis

  Last , Take a look 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 locations The intermediate node of the 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 from the middle node  */   ngx_queue_split(locations, q, &tail);    if (ngx_queue_empty(locations)) {     /*      * ngx_queue_split() insures that if left part is empty,      * then right one is empty too      */     goto inclusive;   }    /*  from locations The left half gets the left subtree  */   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;   }      /*  from locations The right half gets the right subtree  */   node->right = ngx_http_create_locations_tree(cf, &tail, prefix);   if (node->right == null) {     return null;   }  inclusive:    if (ngx_queue_empty(&lq->list)) {     return node;   }    /*  from list The queue gets tree subtree  */   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]; };

         location tree The structure uses left,right,tree this 3 A field , location tree It's actually a trident string sorting tree , And here, if a node only considers the left , Right subtree , It is a balance tree , Its establishment process is a bit similar to the establishment process of a balanced sort binary tree , Sort first, and then insert the found nodes in the order of binary search ,ngx_http_location_tree_node_s Of tree The node is also a balanced sort tree , This node is used by ngx_http_create_locations_list() Got list The establishment of a , That is, the name of the node is its tree The prefix of all node names in the subtree , therefore tree The names of all nodes in the subtree do not need to save the public prefix , And when searching , If it's a turn tree Node words , There is no need to compare the string of the parent node .
         ngx_http_create_locations_tree() The function is written clearly , One of its parameters is queue locations, It returns to a trident tree , The root node is locations Middle node of , Its left subtree is locations The left half of the queue is established location tree, The right subtree is location The right half of the queue is established tree,tree The root of this node is list Queue establishment tree.

       Finally established location tree as follows ( For ease of reading , The picture shows tree The full name of the node ):

Nginx Server location Configuration example analysis

ps: About location modifier
1. =
This will exactly match the specified pattern , And here pattern Limited to simple strings , That is, regular expressions cannot be used here .

example:server {  server_name;  location = /abcd {  […]  }}

Match :    #  It's a perfect match    #  If you run  nginx server  The system itself is not case sensitive , such as  windows , So it also matches;m2  #  Ignore query string parameters (query string arguments), Here is the  /abcd  hinder  ?param1&para;m2  #  Mismatch , Because there's a backslash at the end (trailing slash),nginx  I don't think it's a perfect match  #  Mismatch , Because it's not a perfect match 

2. (none)
Don't write location modifier ,nginx Can still match pattern . In this case , Match those to specify patern At the beginning uri, Notice the uri It can only be a normal string , You can't use regular expressions .

example:server {  server_name;  location /abcd {  […]  }}

Match :    #  It's a perfect match    #  If you run  nginx server  The system itself is not case sensitive , such as  windows , So it also matches;m2  #  Ignore query string parameters (query string arguments), Here is the  /abcd  hinder  ?param1&para;m2  #  There is a backslash at the end (trailing slash) It's also within the scope of matching  #  Still match , because  uri  In order to  pattern  At the beginning 

3. ~
This location modifier Case sensitive , And pattern Must be a regular expression

example:server {  server_name;  location ~ ^/abcd$ {  […]  }}

Match :    #  perfect match    #  Mismatch ,~  Case sensitive;m2  #  Ignore query string parameters (query string arguments), Here is the  /abcd  hinder  ?param1&para;m2  #  Mismatch , Because there's a backslash at the end (trailing slash), Does not match regular expressions  ^/abcd$  #  Does not match regular expression  ^/abcd$

Be careful : For some case insensitive systems , such as windows ,~ and ~* It doesn't work , This is mainly because of the operating system .

4. ~*
And ~ similar , But this location modifier Case insensitive ,pattern Must be a regular expression

example:server {  server_name;  location ~* ^/abcd$ {  […]  }}

Match :    #  perfect match    #  matching , This is its case insensitive feature;m2  #  Ignore query string parameters (query string arguments), Here is the  /abcd  hinder  ?param1&para;m2  #  Mismatch , Because there's a backslash at the end (trailing slash), Does not match regular expressions  ^/abcd$  #  Does not match regular expression  ^/abcd$

5. ^~
The match is similar 2. (none) The situation of , Beginning with the specified matching pattern uri Matched , The difference is , Once the match is successful , that nginx Just stop looking for something else location Blocks are matched ( And location It's about the order of matching )

6. @
Used to define a location block , And the block cannot be externally client Visited , Can only be nginx Internal configuration instructions , such as try_files or error_page

Thank you for reading , That's all “Nginx Server location Configuration example analysis ” Content. , After learning this article , I'm sure you're right Nginx Server location I have a deeper understanding of the problem of configuration example analysis , The specific use needs to be verified by practice . This is billion speed cloud , Xiaobian will push you articles with more relevant knowledge points , Welcome to your attention !

copyright notice
author[Billion cloud speed],Please bring the original link to reprint, thank you.

Random recommended