我有一个位置块设置来捕获所有文件请求,并将它们发送到PHP-FPM :
location / { try_files $uri /routing.php?$args; fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock; include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf; }
这可以正常工作,并正确地将请求传递给PHP-FPM ,或者将请求的确切的现有php文件或设置为要运行的脚本的routing.php 。
我试图添加一个错误页面,以便如果路由文件被删除或不可用,将显示错误页面,而不是Nginx的默认错误页面:
location / { try_files $uri /routing.php?$args /50x_static.html; fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock; include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf; }
这将停止正在提供的routing.php文件,而是显示50x_static.html页面。 请求现有的PHP文件仍然工作,即去URL /dynamic.php
我意识到try_files命令中的最后一个参数有点神奇:
在没有find文件的情况下,调用到最后一个参数的内部redirect。 请注意,只有最后一个参数会导致内部redirect,前者只是设置内部URI指针。 最后一个参数是回退URI并且必须存在,否则会引发内部错误。
在调查为什么error_page破坏了configuration的时候,我意识到对于工作的configuration(没有静态错误页面),当试图获取根URL“/”时,根据Nginx重写日志,Nginx确实似乎匹配请求两次。 “:
"^/proxy/(\d+)/(\w+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test" "^/proxy/(\d+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test" "^/staticImage/(\w+)/(.+)\.([^\.]*)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test" "^/proxy/(\d+)/(\w+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test" "^/proxy/(\d+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test" "^/staticImage/(\w+)/(.+)\.([^\.]*)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
即请求以/ , try_files无法为文件提供服务,因此将请求从/更改为/routing.php ,然后重新处理该请求。
为什么在第一次传递时,try文件不能为routing.php文件提供服务? 它存在并且可以访问,否则它不会在第二次服务。
编辑
删除了无关的configuration。
您明确引用的文档说“调用最后一个参数的内部redirect”。 内部redirect的处理方式与来自客户端的初始请求的处理方式相同 – 这包括在日志中看到的服务器级别处理rewrite语句。 但是,如果除最后一个之外的任何其他try_files参数与现有文件匹配,则使用try_files语句所在的locationconfiguration来处理该请求,并且不会有第二次匹配。
至于你的规则,你尝试只是在try_files省略$args ?
location / { try_files $uri /routing.php /50x_static.html; fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock; include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf; }
请注意$uri也不包含$args ; 查询参数仍然会通过QUERY_STRINGparameter passing给FastCGI后端,这个参数大概是在你的fastcgi.conf设置的:
fastcgi_param QUERY_STRING $query_string;
如果$uri和/routing.php都不作为文件存在,请求将被redirect到/50x_static.html并根据configuration文件中的location = /50x_static.html部分进行处理(但第二次重写尝试仍然会被执行,因为你的重写规则被放置在服务器级别)。
一个非常可疑的configuration细节是,无论文件扩展名如何,您都通过PHP传递所有文件 – 这是非常不寻常的,并且可能会导致安全问题,因为在不期望的文件中执行PHP代码。
谢尔盖说得对; 将$args添加到try_files命令会停止匹配文件,因此在另一个处理循环中发送Nginx,这很奇怪,因为这是Nginx 示例所要做的 。
如果您完全按照以下示例进行操作:
try_files $uri $uri/ /index.php?q=$uri&$args;
如果$uri和$uri/不存在,那么Nginx将移到最后一个参数。 它甚至不尝试匹配文件,而是重新处理请求,将新path设置为/index.php $args现在为q=$uri&$args 。
另一方面,如果在index.php之后的try_files有另一个值,例如
try_files $uri $uri/ /index.php?q=$uri&$args /50x_static.html;
Nginx寻找一个名为/index.php?q=$uri&$args的文件,它显然不存在,所以它移动到/50x_static.html并重新处理。
因为$uri在Nginx重新处理请求时被重写,所以避免这个需要一些细微的改变。 如果你设置你的configuration是这样的:
set $originalURI $uri; try_files $uri $uri/ /index.php /50x_static.html; fastcgi_param QUERY_STRING q=$originalURI&$query_string;
Nginxfind的文件是/index.php ,这是正确的名字,所以nginx将停止处理。 我们必须复制$urivariables作为try_files修改它,所以它将只是/index.php如果我们只是在try_files后面使用它。