添加Rewrite与try_files规则后Nginx处理POST请求报405的解决
问题原因
你的POST请求返回405,是因为/v1/productList被错误重写了。Nginx的执行逻辑是:server块里的if和rewrite指令会在location匹配之前执行,你当前的if ($is_pc)规则没有排除/v1开头的API路径,导致符合条件的PC端请求中,/v1/productList会被重写成/pc/dist/v1/productList。之后Nginx会重新匹配location,这个新路径会走到静态文件处理的location,而静态文件不支持POST方法,因此返回405错误。
修复方案
临时快速修复(修改现有if规则)
只需要在rewrite的正则里添加对/v1路径的排除,让API请求跳过重写:
server { listen 80 ; server_name some; gzip on; gzip_types text/javascript; location ^~ /v1 { proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://market; } # 新增(?!v1/)排除API路径 if ($is_pc) { rewrite ^/(?!v1/)(?!pc/)(?!.*\.(js|css))(.*)$ /pc/dist/$1 last; } location / { root /etc/nginx/market/dist; index index.html; try_files $uri $uri/ /index.html; } location /pc/ { root /etc/nginx/market/; index /pc/dist/index.html; try_files $uri $uri/ /pc/dist/index.html; } location ~ ^/assets/.*\.(js|css)$ { rewrite ^(.*)$ https://some.cdn/khd$1 permanent; } location ~ ^/pc/dist/assets/(.*\.(js|css))$ { rewrite ^/pc/dist/assets/(.*)$ https://some.cdn/khd/assets/$1 permanent; } }
更优实现(避免使用server块的if)
Nginx官方不推荐在server块中使用if(存在很多潜在的匹配坑),建议用map指令来实现PC/移动端的路径区分,配置更简洁可靠:
# 在server块外部定义map,根据$is_pc变量映射不同的根路径 map $is_pc $static_root { default /etc/nginx/market/dist; # 移动端默认路径 1 /etc/nginx/market/pc/dist; # PC端路径 } server { listen 80 ; server_name some; gzip on; gzip_types text/javascript; # 优先匹配API路径,^~确保优先级最高 location ^~ /v1 { proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://market; } # 合并CDN跳转规则,简化配置 location ~ ^/(assets|pc/dist/assets)/.*\.(js|css)$ { rewrite ^/(?:assets|pc/dist/assets)/(.*)$ https://some.cdn/khd/assets/$1 permanent; } # 统一处理静态页面和SPA路由 location / { root $static_root; index index.html; try_files $uri $uri/ /index.html; } }
这个方案通过map提前计算好静态文件的根路径,避免了if带来的匹配问题,同时合并了重复的CDN规则,配置更易维护。
内容的提问来源于stack exchange,提问作者stone
相关产品推荐
相关产品推荐

