Nginx proxy_pass代理子目录无末尾斜杠时资源URL路径错误如何解决
问题根因
该问题由两个配置逻辑缺陷共同导致:
- 规则使用正则匹配
location ~ /phpmyadmin形式,Nginx自带的「无末尾斜杠自动补全301跳转」仅对前缀匹配类型的location生效,正则匹配不会自动将/phpmyadmin跳转到/phpmyadmin/。 - 配置中通过rewrite将请求路径内的
/phpmyadmin前缀完全剥离后才转发给后端,后端服务无法感知自身被挂载在/phpmyadmin子路径下,收到不带斜杠的路径请求时(转发后实际为请求后端根路径/),会默认返回301重定向到根路径/;同时配置了proxy_redirect off,Nginx不会改写后端返回的重定向Location头,浏览器收到重定向响应后会直接请求域名根路径资源,丢失/phpmyadmin前缀。
MailCow服务的同类问题触发逻辑完全一致。
修复方案
将原有的正则location替换为前缀匹配规则,补充路径规范化和重定向改写逻辑即可。
phpMyAdmin对应配置如下:
location ^~ /phpmyadmin { # 原有modsecurity、请求大小、超时配置保留不变 modsecurity off; client_max_body_size 100m; client_body_buffer_size 10M; proxy_read_timeout 6000; proxy_send_timeout 6000; # 补全无末尾斜杠的路径跳转 rewrite ^/phpmyadmin$ /phpmyadmin/ permanent; # 转发时剥离子路径前缀 rewrite ^/phpmyadmin/(.*)$ /$1 break; 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; proxy_set_header Host $host; proxy_pass https://docker_phpmyadmin; # 改写后端返回的重定向地址,自动补全子路径前缀 proxy_redirect ~^/(.*)$ /phpmyadmin/$1; }
MailCow对应配置如下:
location ^~ /mailcow { rewrite ^/mailcow$ /mailcow/ permanent; rewrite ^/mailcow/(.*)$ /$1 break; 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; proxy_set_header Host $host; proxy_pass https://docker_nginx_mailcow; proxy_redirect ~^/(.*)$ /mailcow/$1; }
配置说明
- 用
^~前缀匹配替代原有正则匹配,优先级高于后续的静态资源、PHP解析正则规则,避免请求被错误匹配到其他location块 - 第一条rewrite规则统一入口路径格式,所有不带末尾斜杠的子路径请求先301跳转到带斜杠的规范地址
- 打开之前注释的
X-Forwarded-*头,传递正确的客户端IP、访问协议给后端,避免后端生成错误的绝对路径 - 移除
proxy_redirect off配置,通过规则自动改写后端返回的根路径重定向地址,补上对应子路径前缀 - 配置修改完成后先执行
nginx -t校验语法,确认无错误后执行nginx -s reload重载服务即可生效。
内容的提问来源于stack exchange,提问作者NewUser
相关产品推荐
相关产品推荐

