Nginx如何将所有404请求(含PHP脚本返回的)代理至其他服务器
你当前的配置已经实现了核心需求——不管是Nginx自身返回的404,还是PHP脚本输出的404,都能转发到备用服务器http://anotherserver。不过结合实际运维经验,这里还有几个容易忽略的问题,以及对应的优化方法:
1. 确认PHP真的返回了404状态码
虽然你说PHP返回404时能正常回退,但要注意:如果PHP脚本只是输出了“404 Not Found”的内容,但HTTP状态码还是200,Nginx是不会触发error_page规则的。
所以一定要确保PHP脚本明确返回404状态码,比如:
// 现代PHP版本 http_response_code(404); // 兼容旧版本PHP header("HTTP/1.1 404 Not Found");
2. 覆盖所有静态资源的404场景
当前的location /里的try_files会先找静态文件/目录,找不到才交给index.php。但如果你的Nginx配置了单独的静态资源规则(比如专门处理图片、CSS、JS的location块),这些块里的404可能不会触发代理。
举个例子,如果你有这样的静态资源配置:
location ~* \.(jpg|png|css|js)$ { try_files $uri =404; }
那就要在这个块里加上error_page 404 = @missing;,确保静态资源的404也能被代理:
location ~* \.(jpg|png|css|js)$ { try_files $uri =404; error_page 404 = @missing; }
3. 防止代理循环
你已经设置了recursive_error_pages off;,这步很关键——如果备用服务器也返回404,这个配置能避免Nginx反复代理,防止死循环,继续保持这个设置就好。
4. 给备用服务器传递完整的请求信息
默认情况下,proxy_pass会把请求转发到备用服务器的根路径,但备用服务器可能需要知道原始请求的URI、主机头、客户端IP等信息才能正确处理。可以在@missing块里补充这些配置:
location @missing { proxy_pass http://anotherserver; proxy_read_timeout 60s; # 传递原始请求的完整URI proxy_set_uri $request_uri; # 传递原始请求的主机头 proxy_set_header Host $host; # 传递客户端真实IP proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
5. 保留POST请求的方法和内容
默认的error_page 404 = @missing;会把POST请求转换成GET请求转发到备用服务器,这对需要处理POST数据的场景不友好。如果要保留原始请求方法和请求体,把规则改成:
error_page 404 =404 @missing;
这样Nginx会以404状态码原样转发请求到备用服务器。
内容的提问来源于stack exchange,提问作者Vinay Aggarwal

