NGINX路径重写配置问题:兼容POST请求的Symfony旧API URL改写
Symfony遗留API的NGINX内部URL重写配置方案
问题背景
维护的Symfony(2.8升级至3.4)遗留API有两个入口文件:app_dev.php(仅开发环境使用)和app.php(生产环境入口),但生产环境中仍有外部应用通过https://domain/app_dev.php/the/path访问。需要内部改写URL(不能用301重定向,避免丢失POST请求数据),将这类请求转发到https://domain/app.php/the/path或更简洁的https://domain/the/path。
此前尝试添加rewrite /app_dev\.php/(.*) /app.php$1 break;等规则返回500错误;修改location匹配为^/(app|app_dev)\.php(/|$)虽能运行,但未实现路径重写的需求。
解决方案
方案1:将app_dev.php请求内部转发到app.php
在php-prod.conf的server块中,新增专门匹配app_dev.php的location规则,内部改写请求路径并复用原app.php的PHP-FPM配置:
## php-prod.conf 修改后的完整server块 upstream php { server 127.0.0.1:9000; } server { listen 80; client_max_body_size 50M; client_body_buffer_size 128k; fastcgi_param REMOTE_USER $remote_user; root /var/www/web; location = /favicon.ico { break; } # 新增:匹配app_dev.php请求,内部转发到app.php location ~ ^/app_dev\.php(/|$) { # 复用OPTIONS请求处理逻辑 if ($request_method = OPTIONS ) { add_header Content-Length 0; add_header Content-Type text/plain; add_header Access-Control-Allow-Headers "x-custom-auth, content-type, x-requested-with, authorization, mobile"; add_header Access-Control-Allow-Methods "POST, PUT, PATCH, GET, DELETE"; add_header Access-Control-Allow-Origin "$http_origin"; add_header Access-Control-Max-Age 1728000; return 204; } # 内部改写路径:替换app_dev.php为app.php rewrite ^/app_dev\.php(/.*)$ /app.php$1 break; # 转发到PHP-FPM,复用原app.php的fastcgi配置 fastcgi_pass php; fastcgi_read_timeout 3600; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; } location / { try_files $uri /app.php$is_args$args; } # 保留原app.php的生产环境配置 location ~ ^/app\.php(/|$) { if ($request_method = OPTIONS ) { add_header Content-Length 0; add_header Content-Type text/plain; add_header Access-Control-Allow-Headers "x-custom-auth, content-type, x-requested-with, authorization, mobile"; add_header Access-Control-Allow-Methods "POST, PUT, PATCH, GET, DELETE"; add_header Access-Control-Allow-Origin "$http_origin"; add_header Access-Control-Max-Age 1728000; return 204; } fastcgi_pass php; fastcgi_read_timeout 3600; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; internal; } # 拦截其他未授权的PHP文件请求 location ~ \.php$ { return 404; } error_log /var/log/nginx/error.log; access_log off; }
方案2:直接改写为无入口文件的干净路径(推荐)
如果希望直接去掉入口文件,将https://domain/app_dev.php/the/path改写为https://domain/the/path,只需修改location /块的逻辑:
## php-prod.conf 修改后的location /块 location / { # 优先处理app_dev.php开头的请求,去掉入口文件路径 rewrite ^/app_dev\.php(/.*)$ $1 break; # 执行原有的静态文件匹配和入口转发逻辑 try_files $uri /app.php$is_args$args; } # 保留原app.php和其他location配置不变
此前尝试报错原因
之前添加rewrite规则返回500的核心原因:
- 原配置中
location ~ \.php$会拦截所有未被^/app\.php匹配的PHP文件请求,直接返回404; - 当rewrite后的请求仍携带
.php后缀时,会被该规则拦截,或触发fastcgi配置中的路径解析错误; - 新增专门的
location ~ ^/app_dev\.php(/|$)可以优先匹配请求,避免被404规则拦截,同时直接复用合法的fastcgi配置处理改写后的请求。
内容的提问来源于stack exchange,提问作者Alex Bailey
相关产品推荐
相关产品推荐

