proxy_pass 末尾带不带斜杠?带斜杠替换 location 前缀,不带则原样转发,配错后端全 404

来源:互联网 时间:2026-11-03

接口迁到新服务上,nginx加了一条location /api/把请求转过去。后端日志里收到的路径是/user/list,不是/api/user/list,接口全404。后端是新起的服务,路由前缀配的是/,跟前端的/api对不上,两边的路径约定不一样。

proxy_pass后面写的地址带不带路径,行为完全不同。写成proxy_pass http://127.0.0.1:8080/,末尾有一个斜杠,nginx会把location匹配到的那段前缀替换成这个斜杠,/api/user/list变成/user/list。写成proxy_pass http://127.0.0.1:8080,末尾没有斜杠,请求原样转发,后端收到的还是/api/user/list。判断依据是末尾有没有URI,一个斜杠也算URI。这个替换只发生在匹配到的那一段,后缀保持不动。/api/user/list里location匹配的是/api/,替换后剩下user/list,接在斜杠后面就是/user/list。记不住就记一句话,带斜杠是把前缀切掉,不带是整条送过去。带变量的时候规则反过来,proxy_pass写成http://$backend/这种形式,nginx原样转发,不做前缀替换,配动态上游时要留意。

这条规则跟rewrite不是一回事,rewrite是改完再转,proxy_pass是转发那一刻做替换。location /api/配proxy_pass http://backend/v1/,等于把所有/api/开头的请求映射到后端的/v1/下面,两边的前缀长度不必相同。rewrite写在location里,改的是nginx自己看到的URI,proxy_pass再拿这个结果去转发。两个都用的时候,先rewrite后转发,顺序错了结果就不一样。用rewrite的好处是路径怎么变都能算清楚,缺点是规则多了难维护。

你先看后端access日志,一行里就是实际收到的路径。没有后端日志的,在nginx上开error_log debug,或者临时加一条add_header X-Orig $request_uri,比对转发前后的差别。curl -sv打一次能看到实际请求行,Location只在3xx上才有。add_header默认只在200、201、204、206、301、302、303、304这些状态码上加,404和500不加。error_log debug会打出一大段内部状态,调完要关掉,日志涨得很快。

正则location里proxy_pass不能带URI,写了nginx -t会直接报错,提示proxy_pass cannot have URI part in location given by regular expression。这类location只能用rewrite把路径改好再转。if和limit_except里同样不能带URI,规则是一样的。正则location做整段替换,只能靠rewrite last把URI改完,再交给一条不带URI的proxy_pass。这类写法在伪静态和API网关里很常见,改之前先把现有rewrite列出来。

带斜杠的写法适合后端路径和前端对不上、需要整段替换的场景。不带斜杠适合后端自己就认这个前缀。两种都能用的时候选不带,前端加前缀、后端减前缀这种双向映射,排查时最费时间。双向映射最容易出错的地方是分页和搜索参数,前缀对了参数也要跟着对。

改完把常用的几个路径挨个打一遍,后端日志里的路径对得上再上线。同类问题在静态资源目录上也常见,/static/转到对象存储时多一个斜杠,图片就全挂。对象存储的路径通常要求带桶名,多一个斜杠就多一层目录。

相关文章

标签:

A5创业网 版权所有

返回顶部