前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nginx - location中的匹配规则和动态Proxy

Nginx - location中的匹配规则和动态Proxy

作者头像
小小工匠
发布2024-05-26 13:43:38
920
发布2024-05-26 13:43:38
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构

官网

https://nginx.org/en/docs/http/ngx_http_core_module.html#location


location 规则详解

Nginx的location指令工作原理如下:

  1. 位置匹配
    • Nginx根据规范化的URI进行位置匹配。
    • 解码以"%XX"形式编码的文本。
    • 解析相对路径组件".“和”…"的引用。
    • 可能将两个或多个相邻的斜杠压缩为单个斜杠。

  1. 位置定义
    • 位置可以由前缀字符串或正则表达式定义。
    • 正则表达式可以是不区分大小写的(~*修饰符)或区分大小写的(~修饰符)。
    • 首先检查前缀位置,并选择具有最长匹配前缀的位置。
    • 正则表达式按照它们在配置文件中出现的顺序进行检查。
    • 一旦找到正则表达式匹配项,将使用相应的配置,并终止进一步检查。

  1. 修饰符
    • ^~修饰符:如果具有最长匹配前缀的位置具有此修饰符,则不会检查正则表达式。
    • =修饰符:定义URI和位置的精确匹配。一旦找到,搜索终止。
    • @前缀:为请求重定向定义了一个命名位置,而不是用于常规请求处理。不能嵌套,也不能包含嵌套位置。

  1. 匹配指令
    • ~:执行区分大小写的正则表达式匹配。
    • ~*:执行不区分大小写的正则表达式匹配。
    • ^~:执行普通字符匹配,不是正则表达式。如果匹配成功,只使用该选项,不再匹配其他选项,通常用于匹配目录。
    • =:执行精确匹配,即普通字符的精确匹配。
    • @:定义一个命名的location,用于内部重定向,例如error_pagetry_files

  1. 匹配优先级
    • 精确匹配(=)优先级最高。如果找到精确匹配,Nginx停止搜索其他匹配。
    • 普通字符匹配,正则表达式匹配以及长的块规则将优先于其他查询匹配。换句话说,如果某个项匹配成功,Nginx还会继续检查是否有正则表达式匹配和更长的匹配。
    • 如果使用了^~,则只匹配该规则,Nginx停止搜索其他匹配;否则,Nginx会继续处理其他location指令。
    • 最后,按照匹配程度最高的逐字匹配指令,如果找到相应的匹配,Nginx停止搜索其他匹配。

这些规则确保了location指令的匹配行为,并使得开发者能够有序地控制请求的路由和处理。


  1. 特殊处理
    • 如果位置由以斜杠结尾的前缀字符串定义,并且请求由某些指令(如proxy_pass)处理,则如果请求的URI没有尾部斜杠,则执行永久重定向(301)。

以下是基于提供的配置的示例:

代码语言:javascript
复制
location = / {
    [ 配置 A ]
}

location / {
    [ 配置 B ]
}

location /documents/ {
    [ 配置 C ]
}

location ^~ /images/ {
    [ 配置 D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    [ 配置 E ]
}
  • 请求:
    • “/”: 匹配配置 A。
    • “/index.html”: 匹配配置 B。
    • “/documents/document.html”: 匹配配置 C。
    • “/images/1.gif”: 匹配配置 D。
    • “/documents/1.jpg”: 匹配配置 E。

特殊处理的示例:

代码语言:javascript
复制
location /user/ {
    proxy_pass http://user.example.com;
}

location = /user {
    proxy_pass http://login.example.com;
}
  • 请求:
    • “/user/”: 代理到http://user.example.com
    • “/user”: 代理到http://login.example.com

动态Proxy

使用多个 if 指令指定不同的 proxy_pass

代码语言:javascript
复制
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; 
        } 
    }
}

当希望根据不同的条件执行不同的proxy_pass时,可以使用多个if指令。例如,在上述配置中,如果多个条件都满足,比如在第一个if中没有使用break,那么下一个条件也会被执行。为了确保匹配到第一个条件后就执行相应的proxy_pass,可以在第一个if指令中加上break关键字。(在Nginx中没有if-else这样的结构)

在这种情况下,可以使用多个if语句来满足不同条件下的处理逻辑。但需要注意的是,if语句是在Nginx的rewrite模块中执行的,并且在性能方面可能会有一些影响。另外,需要小心使用if语句,因为它们可能会引起一些意想不到的问题


根据参数选择不同的 proxy_pass

代码语言:javascript
复制
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. 请求路径中的 usg=0usg=1 这两个参数是固定的,因此可以使用 $query_string 进行正则匹配。
  2. 接下来,如果要对参数 uid 的值以 A 或 B 结尾的请求进行处理,就无法使用 query_string 进行匹配了;因此,需要使用 arg_uid 进行正则匹配。
  3. 由于 usg=0usg=1 这两个参数是互斥的,因此放在 location 块的顶部即可正确处理。而对于 uid 的匹配,则应放在最底部或者使用 break 关键字,以避免与 usg 参数的匹配冲突。

对于固定参数值,可以使用query_string进行正则匹配,而对于变量参数值,则需要使用arg_parameter进行匹配。对于可能互斥的参数匹配条件,确保按照正确的优先级进行排列,或者在适当的地方使用break来终止后续的if语句执行

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 官网
  • location 规则详解
  • 动态Proxy
    • 使用多个 if 指令指定不同的 proxy_pass
      • 根据参数选择不同的 proxy_pass
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档