Method of proxy_pass in multiple if in nginx location

  • 2021-09-11 21:51:06
  • OfStack

1. First, we review the knowledge of location in nginx under 1

1) Match instruction for location:

~ # Wavy lines indicate performing a regular match, case-sensitive ~ * # Indicates performing 1 regular match, case-insensitive ^ ~ # ^ ~ indicates a normal character match, not a regular match. If this option matches, only this option is matched, and other options are not matched. 1 is generally used to match directories = # Accurate matching of ordinary characters @ # "@" Defines a named location for internal orientation, such as error_page, try_files

2) Priority of location matches (regardless of the order of location in the configuration file)

1.= The exact match will be processed first. If an exact match is found, nginx stops searching for other matches.
2. Ordinary character matches, regular expression rules, and long block rules will be preferentially matched to the query, that is, if the item matches, it needs to see if there are regular expression matches and longer matches.
3. ^ ~ only matches the rule, and nginx stops searching for other matches, otherwise nginx continues to process other location instructions.
4. Finally, the match manager has the instructions of "~" and "~ *". If the corresponding match is found, nginx stops searching for other matches; When there is no regular expression or no regular expression is matched, the verbatim matching instruction with the highest degree of matching will be used.

2. nginx proxy_pass in multiple if:


server {
listen 127.0.0.1:80;
    set $test A; 
  
    set $testB B;
    location / {
      if ($test ~* "A") { 
         proxy_pass http://www.so.com; 
         break; 
      } 
      if ($testB ~* "B") { 
         proxy_pass http://www.sogou.com; 
         #break; 
      } 
    }
}

When you want to meet a certain condition, go to an proxy_pass. However, if multiple if are satisfied, as in the above example: when there is no break in the first if, the following will be executed; To execute proxy_pass after the first match, you can add break. (There seems to be no instruction for if else in nginx.)

3. Judge the parameters and carry out different proxy_pass:

rewrite can only be matched through url path, but can't match parameters, so $arg_parameter is needed to judge parameters.


location / {
    root  html;
    index  index.html index.htm index.php;
    proxy_redirect   off;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header  Connection "";

    if ( $query_string ~* "usg=0" ) {
      proxy_pass   http://local_workera;
    }

    if ( $query_string ~* "usg=1" ) {
      proxy_pass   http://local_workerb;
    }

    if ( $arg_uid ~* "(.*[AB]$)" ) {
  proxy_pass   http://local_workerf;
    }

    proxy_pass  http://local_workera;
}

1) The parameters usg=0 and usg=1 in the request path are deterministic, so regular matching with $query_string is sufficient; (The value of $query_string is all the parameters in the request)

2) Next, if the value of uid is a request ending in A, B, we want to turn to local_workerf processing, and then we can't do regular matching with $query_string; (Because for/? uid = 1A & t=1 & usg=1 and/? uid=123 & t=A & usg=0 is not a good match.) At this time, you can only use $arg_uid for regular matching.

3) Because usg=0 and usg=2 are mutually exclusive, according to the logic of if instruction in location above, it can be handled correctly without break and placed at the top. For the matching of uid, because it will conflict with usg, it can only be placed at the bottom or added with break, that is:


location / {
    root  html;
    index  index.html index.htm index.php;
    proxy_redirect   off;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header  Connection "";
 
 if ( $arg_uid ~* "(.*[AB]$)" ) {
  proxy_pass   http://local_workerf;
  break;
    }

    if ( $query_string ~* "usg=0" ) {
      proxy_pass   http://local_workera;
    }

    if ( $query_string ~* "usg=1" ) {
      proxy_pass   http://local_workerb;
    }

    proxy_pass  http://local_workera;
}


Related articles: