Nginx的location匹配规则:优先级和路径替换

本文详细介绍了Nginx中location配置的各种特性和优先级规则,包括不同类型的匹配方式(如完全匹配、无正则普通匹配、正则表达式匹配及普通匹配)以及路径替换的具体应用。

Nginx是反向代理和负载均衡的首选工具,nginx的location配置有许多细节内容在网上不容易找到资料,或者解释不清。本文对locaiton的常见特性进行介绍。

 

location的优先级

Nginx的server中往往有多个location共存,每个location定义自己的匹配规则和proxy信息,对于每一个请求,需要有一定的优先级来找到自己合适的location。

locaiton有四种类型的匹配规则,分别为

  • 完全匹配(=)
  • 无正则普通匹配(^~)^ 表示“非”,~ 表示“正则”,字符意思是:不要继续匹配正则
  • 正则表达式匹配(~或者~*)
  • 普通匹配(/xxx)

规则

  • 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他location的匹配项
  • 剩下的几种匹配优先级略复杂,具体可以参考Nginx文档(http://nginx.org/en/docs/http/ngx_http_core_module.html#location
    • ^~和普通匹配使用前缀匹配,不支持正则表达式,如果有多个location匹配成功的话,不会终止匹配过程,会记忆表达式最长的那个
    • 如果上一步得到的最长的location为^~类型,则表示阻断正则表达式,不再匹配正则表达式
    • 如果上一步得到的最长的location不是^~类型,继续匹配正则表达式,只要有一个正则成功,则使用这个正则的location,立即返回结果,并结束解析过程

“最长”命中

^~和普通命中,都是优先使用匹配最长的结果,示例如下:

location ^~ /a {
    root /;
}
location ^~ /aaa {
    root /aaa;
}

如果url为/aaa,则上面两个location都匹配成功,但用于location ^~ /aaa较长,所以最终会以/aaa作为root

上例中如果是普通匹配(把location的^~去掉),结果也是一样的

 

示例

location /test_1 {
    return 400;
}
location ^~ /test {
    return 401;
}

如上如果path为/test_1,返回的是400,说明^~优先级并不比普通匹配高

 

location /test_1 {
    return 400;
}
location ^~ /test {
    return 401;
}
location ~ /test {
    return 402;
}

如上如果path为/test_1,返回的是402,此时^~和普通匹配只记住了最长一个location /test_1,不会阻止正则

如果path为/test,返回401,此时^~和普通匹配只记住了最长一个location ^~ /test,会阻止正则

 

 

路径替换

规则

配置proxy_pass时,可以实现URL路径的部分替换。

proxy_pass的目标地址,默认不带/,表示只代理域名,url和querystring部分不会变(把请求的path拼接到proxy_pass目标域名之后作为代理的URL)

如果在目标地址后增加/,则表示把path中location匹配成功的部分剪切掉之后再拼接到proxy_pass目标地址

比如请求 /a/b.html

location /a {
    proxy_pass http://server;
}
location /a/ {
    proxy_pass http://server/;
}

如上两个匹配成功后,实际代理的目标url分别是

http://server/a/b.html (把/a/b.html拼接到http://server之后)

http://server/b.html (把/a/b.html的/a/去掉之后,拼接到http://server/之后)

要求

注意的是,对于location为正则表达式的匹配,proxy_pass的目标地址不可以带/

比如,如下配置会报错:

location ~ /abc(.*) {
    proxy_pass   http://127.0.0.1/x;
}

正则表达式的替换

如果是正则表达式,想要实现proxy_pass的路径替换,可以使用如下方式:

location ~ /abc(.*) { # 注意,使用这种方式,location内部不能包含if语句,否则proxy_pass不会生效
    proxy_pass   http://127.0.0.1/x$1;
}

如上可以把(.*)所匹配的内容拼接到http://127.0.0.1/x 之后,关于$1的使用,可以参考各种编程语言的正则表达式

另一种方法是:

location  /abc { # 这里也可以是正则
    proxy_pass http://127.0.0.1/x$request_uri;
}

 

<think>我们正在配置Nginx反向代理,目标是指定端口并附加路径。这意味着当客户端访问Nginx的某个地址时,Nginx会将请求转发到后端服务器的指定端口,并且在原始请求路径前附加一个路径。 根据引用[2],我们需要在Nginx的配置文件中定义一个server块来配置反向代理。通常,我们会在`/etc/nginx/conf.d/`目录下创建一个新的配置文件(例如`reverse-proxy.conf`)或者在`nginx.conf`中的http块内直接配置。 关键指令是`proxy_pass`,它用于设置后端服务器的地址。同时,我们需要注意路径的处理。如果我们在`proxy_pass`的URL中指定了路径,那么Nginx会将匹配到的location路径部分替换为该URL路径。但是,如果我们要在原始请求路径前附加一个路径,我们需要在`proxy_pass`中指定这个附加路径,并且可能需要使用`rewrite`指令来修改请求的URI。 例如,假设我们想要将访问Nginx的`/app/`路径的请求转发到后端服务器`http://backend_server:8080/base/`,那么我们可以这样配置: 步骤: 1. 在Nginx配置中,创建一个server块。 2. 在server块中,定义一个location块来匹配我们想要代理的路径(比如`/app/`)。 3. 在location块中,使用`proxy_pass`指定后端服务器的地址端口,并在后面加上我们想要附加的路径(比如`http://backend_server:8080/base/`)。 4. 注意:由于我们在`proxy_pass`中使用了URI路径(`/base/`),Nginx会将原始请求中匹配location路径(`/app/`)替换为`/base/`。但是,这样替换后,原始请求的URI中除了`/app/`的部分会直接附加到`/base/`后面。这可能会导致路径错误,因为原始请求的URI中可能包含`/app/`之后的路径。 为了确保路径正确,我们可能需要使用`rewrite`指令来修改请求的URI。常见的做法是使用`rewrite`将匹配到的location路径(`/app/`)从请求URI中去除,然后将剩余部分附加到新的路径后面。 具体配置示例: ``` server { listen 80; server_name example.com; location /app/ { # 重写请求URI:将/app/(.*)捕获到$1,然后重写为/base/$1 rewrite ^/app/(.*)$ /base/$1 break; # 将请求转发到后端服务器,注意这里proxy_pass后面不再带路径(因为已经通过rewrite修改了URI) proxy_pass http://backend_server:8080; # 传递必要的头部 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` 解释: - `rewrite ^/app/(.*)$ /base/$1 break;`:这个重写规则匹配`/app/`开头的请求,并将`/app/`后面的部分(用(.*)捕获)附加到`/base/`后面。`break`标志表示停止处理当前的重写指令集,并使用当前重写后的URI进行后续处理(即proxy_pass)。 - 然后,`proxy_pass`指令将请求转发到`http://backend_server:8080`,此时请求的URI已经被重写为`/base/...`。 另一种情况:如果我们不想在location匹配路径(`/app/`)被去除,而是希望在后端路径中直接附加,那么我们可以不用rewrite,但需要在proxy_pass中指定附加路径,并确保后端服务器能够处理带有附加路径的请求。但是,这样可能会导致路径重复,因为location匹配路径也会被传递。所以通常我们会使用rewrite来去除location匹配的前缀。 注意:如果附加路径原始请求路径需要合并,我们通常使用rewrite来调整路径。 根据引用[1][2],我们还需要配置一些请求头部信息,以便后端服务器能够获取到真实的客户端信息。 因此,针对用户的问题“配置反向代理指定端口并附加路径”,我们可以总结出以下步骤: 1. 打开Nginx配置文件(如`/etc/nginx/nginx.conf`或在`/etc/nginx/conf.d/`下新建配置文件)。 2. 在http块内,添加一个server块。 3. 配置server监听的端口server_name。 4. 添加一个location块,匹配需要代理的路径(例如`/app/`)。 5. 在该location块内,使用rewrite指令修改请求URI(去除location匹配的前缀,并附加新的路径前缀)。 6. 使用proxy_pass指令指向后端服务器的地址端口(注意这里不需要再写附加路径,因为已经在rewrite中处理了)。 7. 配置必要的proxy_set_header指令。 下面是一个完整的配置示例: ``` http { # ... 其他配置 server { listen 80; server_name your_domain.com; location /app/ { # 重写URL:将请求路径中的/app/替换为/base/,并保留后续路径 rewrite ^/app/(.*)$ /base/$1 break; # 代理到后端服务器,端口为8080 proxy_pass http://localhost:8080; # 设置代理请求头 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } } ``` 注意:上面的配置假设后端服务器运行在本地(localhost)的8080端口上,并且我们希望将`/app/`路径下的请求转发到后端的`/base/`路径下。例如,客户端请求`http://your_domain.com/app/test`将被转发到`http://localhost:8080/base/test`。 保存配置文件后,记得测试配置并重新加载Nginx: ``` nginx -t nginx -s reload ``` 如果后端服务器不在本地,请将`http://localhost:8080`替换为实际的后端服务器地址端口。 另外,如果附加的路径不需要保留原始请求路径location匹配的部分,则rewrite规则需要相应调整。例如,如果我们希望所有匹配`/app/`的请求都转发到后端的`/base/`,而不管原始请求路径中`/app/`后面是什么,并且希望后端接收到的请求路径就是`/base/`,那么我们可以这样写rewrite: ``` rewrite ^/app/ /base/ break; ``` 这样,任何以`/app/`开头的请求都会被重写为`/base/`,然后转发给后端。例如: 请求`/app/test` -> 后端接收到的请求路径为`/base/` 请求`/app/user/profile` -> 后端接收到的请求路径为`/base/` 这通常不是我们想要的,因为我们丢失了原始请求的后续路径。所以通常我们会使用第一种方式,保留后续路径。 因此,根据实际需求,调整rewrite规则。 总结:配置Nginx反向代理指定端口并附加路径的关键在于使用rewrite指令修改请求URI,然后使用proxy_pass转发到指定端口。</think>### Nginx 配置反向代理指定端口并附加路径 以下是配置 Nginx 反向代理指定端口并附加路径的完整步骤: #### 核心配置示例 ```nginx server { listen 80; server_name example.com; # 路径匹配规则 location /prefix/ { # 重写URL路径(关键步骤) rewrite ^/prefix/(.*)$ /newpath/$1 break; # 反向代理配置(带端口路径) proxy_pass http://backend_server:8080; # 必需的头信息传递 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` #### 配置说明 1. **路径处理逻辑** - 客户端请求:`http://example.com/prefix/api` - 经过 `rewrite` 转换:`/newpath/api` - 最终代理到:`http://backend_server:8080/newpath/api` 2. **关键指令解析** - `rewrite ^/prefix/(.*)$ /newpath/$1 break;`: 将原始路径中的 `/prefix/` 替换为 `/newpath/`,`$1` 捕获后续路径 - `proxy_pass http://backend_server:8080;`: 指定后端服务器的 **IP:端口**(端口可自定义) - `proxy_set_header`:确保后端获取真实客户端信息[^1][^2] 3. **完整配置流程** ```bash # 1. 编辑配置文件(通常路径) sudo vim /etc/nginx/conf.d/reverse-proxy.conf # 2. 粘贴上述配置 # 3. 测试配置语法 sudo nginx -t # 4. 重载配置 sudo systemctl reload nginx ``` #### 常见问题解决 1. **路径404错误** - 检查 `rewrite` 规则是否遗漏 `break` 标志 - 确认后端服务是否包含 `/newpath` 基础路径 2. **端口不通** - 验证防火墙设置:`sudo ufw allow 8080/tcp` - 测试后端连通性:`telnet backend_server 8080` 3. **特殊字符处理** 在 `location` 中使用转义符处理特殊路径: ```nginx location ~ ^/user\/(.*)$ { rewrite ^/user\/(.*)$ /profile/$1 break; proxy_pass http://backend:3000; } ``` #### 典型应用场景 - 将 `http://domain.com/app` 代理到 `http://localhost:3000/admin` - 统一多个服务的访问路径前缀 - 端口隐藏(对外暴露80/443,内部使用不同端口)[^3][^5] > **提示**:使用 `curl -v http://localhost/prefix/test` 测试时,检查响应头中的 `X-Proxy-Pass` 可验证路径转换结果[^4]。 --- ###
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值