动态 Url 段的 Nginx 位置块
Nginx Location Block for Dynamic Url Segment
我的 PHP 应用程序自动检测到请求通过 url 中的关键字 manage 路由到管理区域,即:
这个目录实际上并不存在。
请求应该路由到 index.php 文件,该文件在初始请求上执行以管理/但任何链接都会在 nginx 中产生 "No input file specified." 错误。
我需要一个可以在不存在的 url 段上工作的位置块。
我试过像这样将它重写到主索引文件中:
location /manage {
try_files $uri $uri/ @back;
}
location @back {
rewrite ^/manage/(.*)$ /index.php?_route_= last;
}
这对 Apache 工作正常,但在 Nginx 中这会产生 500 错误。
如有任何建议,我们将不胜感激。
更新:
评论中要求的完整配置:
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name my.domain.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location /asset {
rewrite ^/asset/(.*)$ /public/asset/ break;
}
location /image {
rewrite ^/image/(.*)$ /public/image/ break;
}
location / {
try_files $uri $uri/ @front;
}
location @front {
rewrite ^/(.+)$ /index.php?_route_= last;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
}
更新:
请求错误日志。
15/05/14 10:42:04 [error] 32704#0:
*5 FastCGI sent in stderr:
"Unable to open primary script: /srv/users/username/apps/myapp/public/manage/index.php (No such file or directory)"
while reading response header from upstream, client: 129.349.569.789,
server: myapp.example.com,
request: "GET /manage/index.php?route=common/forgotten HTTP/1.1",
upstream: "fastcgi://127.0.0.1:9002",
host: "myapp.example.com",
referrer: "http://myapp.example.com/manage"
更新:
请求的 .htaccess
文件:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/$ / [L,R=301]
RewriteRule ^asset/(.*)$ public/asset/ [L,QSA]
RewriteRule ^image/(.*)$ public/image/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|txt|html|woff|ttf|eot|svg|css|js)
RewriteRule ^([^?]*) index.php?_route_= [L,QSA]
</IfModule>
根据您发布的错误日志和配置,/manage/index.php?route=common/forgotten
的请求将匹配 /
和 php
位置块。
鉴于 Nginx Location Matching Order 的设置方式,PHP 位置块将始终优先,因此请求将传递给 FastCGI 进行处理,并且由于 site.com/manage/index.php
不存在,你得到一个错误。也就是说,/
中的 try_files
和 @front
中的重写根本不会出现。
你需要做的是添加一个位置匹配顺序比PHP位置块更高的位置块来处理这样的请求。
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location /asset {
rewrite ^/asset/(.*)$ /public/asset/ break;
}
location /image {
rewrite ^/image/(.*)$ /public/image/ break;
}
location / {
try_files $uri $uri/ @front;
}
location ~ ^/manage {
rewrite ^([^?]*)$ /index.php?_route_=;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location @front {
rewrite ^([^?]*)$ /index.php?_route_=;
}
}
通过这种安排,请求将匹配 /
、/Manage
和 php
位置块。 /Manage
和 php
是正则表达式类型的块,将优先并在两者中,/Manage
,因为它首先出现,将优先并相应地重定向。
对于重定向,请求将匹配 /
和 php
位置块。 php
将优先,并且 site.com/index.php
确实存在,因此进行相应处理。
PS。我注意到您的配置中有 _route_
,日志中有 route
。拿去那只是为了测试。
**** 替代配置 ****
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location ~ ^/asset/(.*)$ {
rewrite ^ public/asset/;
}
location ~ ^/image/(.*)$ {
rewrite ^ public/image/;
}
location / {
rewrite ^/(.+)/$ / permanent;
try_files $uri $uri/ @front;
}
location @front {
rewrite ^/([^?]*)$ /index.php?_route_=;
}
}
原来一直就在我眼皮子底下
upstream myapp {
server localhost:9002;
}
server {
listen 80;
server_name myapp.example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.html index.htm index.php;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location / {
try_files $uri $uri/ @front;
}
location ~ ^/manage {
rewrite ^/(.+)$ /index.php?_route_= last;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location @front {
rewrite ^/(.+)$ /index.php?_route_= last;
}
}
感谢@Dayo 的所有帮助。
我的 PHP 应用程序自动检测到请求通过 url 中的关键字 manage 路由到管理区域,即:
这个目录实际上并不存在。
请求应该路由到 index.php 文件,该文件在初始请求上执行以管理/但任何链接都会在 nginx 中产生 "No input file specified." 错误。
我需要一个可以在不存在的 url 段上工作的位置块。
我试过像这样将它重写到主索引文件中:
location /manage {
try_files $uri $uri/ @back;
}
location @back {
rewrite ^/manage/(.*)$ /index.php?_route_= last;
}
这对 Apache 工作正常,但在 Nginx 中这会产生 500 错误。
如有任何建议,我们将不胜感激。
更新:
评论中要求的完整配置:
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name my.domain.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location /asset {
rewrite ^/asset/(.*)$ /public/asset/ break;
}
location /image {
rewrite ^/image/(.*)$ /public/image/ break;
}
location / {
try_files $uri $uri/ @front;
}
location @front {
rewrite ^/(.+)$ /index.php?_route_= last;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
}
更新:
请求错误日志。
15/05/14 10:42:04 [error] 32704#0:
*5 FastCGI sent in stderr:
"Unable to open primary script: /srv/users/username/apps/myapp/public/manage/index.php (No such file or directory)"
while reading response header from upstream, client: 129.349.569.789,
server: myapp.example.com,
request: "GET /manage/index.php?route=common/forgotten HTTP/1.1",
upstream: "fastcgi://127.0.0.1:9002",
host: "myapp.example.com",
referrer: "http://myapp.example.com/manage"
更新:
请求的 .htaccess
文件:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/$ / [L,R=301]
RewriteRule ^asset/(.*)$ public/asset/ [L,QSA]
RewriteRule ^image/(.*)$ public/image/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|txt|html|woff|ttf|eot|svg|css|js)
RewriteRule ^([^?]*) index.php?_route_= [L,QSA]
</IfModule>
根据您发布的错误日志和配置,/manage/index.php?route=common/forgotten
的请求将匹配 /
和 php
位置块。
鉴于 Nginx Location Matching Order 的设置方式,PHP 位置块将始终优先,因此请求将传递给 FastCGI 进行处理,并且由于 site.com/manage/index.php
不存在,你得到一个错误。也就是说,/
中的 try_files
和 @front
中的重写根本不会出现。
你需要做的是添加一个位置匹配顺序比PHP位置块更高的位置块来处理这样的请求。
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location /asset {
rewrite ^/asset/(.*)$ /public/asset/ break;
}
location /image {
rewrite ^/image/(.*)$ /public/image/ break;
}
location / {
try_files $uri $uri/ @front;
}
location ~ ^/manage {
rewrite ^([^?]*)$ /index.php?_route_=;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location @front {
rewrite ^([^?]*)$ /index.php?_route_=;
}
}
通过这种安排,请求将匹配 /
、/Manage
和 php
位置块。 /Manage
和 php
是正则表达式类型的块,将优先并在两者中,/Manage
,因为它首先出现,将优先并相应地重定向。
对于重定向,请求将匹配 /
和 php
位置块。 php
将优先,并且 site.com/index.php
确实存在,因此进行相应处理。
PS。我注意到您的配置中有 _route_
,日志中有 route
。拿去那只是为了测试。
**** 替代配置 ****
upstream myapp {
server unix:/srv/users/serverpilot/run/myapp.php-fpm.sock;
}
server {
listen 80;
server_name example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.php index.html index.htm;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location ~ ^/asset/(.*)$ {
rewrite ^ public/asset/;
}
location ~ ^/image/(.*)$ {
rewrite ^ public/image/;
}
location / {
rewrite ^/(.+)/$ / permanent;
try_files $uri $uri/ @front;
}
location @front {
rewrite ^/([^?]*)$ /index.php?_route_=;
}
}
原来一直就在我眼皮子底下
upstream myapp {
server localhost:9002;
}
server {
listen 80;
server_name myapp.example.com;
root /srv/users/serverpilot/apps/myapp/public;
index index.html index.htm index.php;
access_log /srv/users/serverpilot/log/myapp/myapp_nginx.access.log;
error_log /srv/users/serverpilot/log/myapp/myapp_nginx.error.log;
location / {
try_files $uri $uri/ @front;
}
location ~ ^/manage {
rewrite ^/(.+)$ /index.php?_route_= last;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass myapp;
}
location @front {
rewrite ^/(.+)$ /index.php?_route_= last;
}
}
感谢@Dayo 的所有帮助。