我正在使用PHP-FastCGI在nginx 1.4.1上运行服务器。目前我进行了设置,以便从我的URL中删除尾部斜杠并发出301重定向。但是,当我访问存在的目录时,我被迫进入重定向循环。我当前的文档根目录如下:
- index.php (app)
- webgrind
- index.php
- static
- css
目前我无法访问example.com/webgrind或任何其他目录。我的访问日志反复读取类似于:
GET /webgrind/ HTTP/1.1" 301 178 "-"
GET /webgrind HTTP/1.1" 301 178 "-"
这是我的nginx.conf中的服务器块:
server {
listen 80;
server_name example.com;
location / {
try_files $uri $uri/ /index.php?$args;
root /var/www/example/public;
index index.php index.html index.htm;
}
rewrite ^/(.*)/$ /$1 permanent;
location = /favicon.ico {
access_log off;
log_not_found off;
}
location ~ \.php$ {
try_files $uri $uri/ /index.php?$args;
root /var/www/example/public;
index index.php index.html index.htm;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example/public$fastcgi_script_name;
fastcgi_param APPLICATION_ENV testing;
fastcgi_param PATH /usr/bin:/bin:/usr/sbin:/sbin;
fastcgi_intercept_errors on;
include fastcgi_params;
}
}
我知道rewrite ^/(.*)/$ /$1 permanent;
是违规行。如果我将其删除并访问example.com/webgrind,则会发出301以重定向到example.com/webgrind/,因为它是一个目录。但是,我的应用程序现在将接受尾随斜杠和非尾随斜杠(例如example.com/users/和example.com/users),这不是我想要的。
如下所示,围绕我的重写包含'if'指令仍会为我的目录创建一个重定向循环(if is evil,显然,但在这种情况下,重写指令被认为是安全的):
if (!-d $request_filename) {
rewrite ^/(.*)/$ /$1 permanent;
}
(我知道访问webgrind / index.php会解决我的问题,但是当我的生产目录被推送时,我想避免代价高昂且不专业的重定向循环。)
那么我怎样才能有条件地删除不存在的资源(我的Web应用程序路径)的尾部斜杠?
更新:我的(未更改)fastcgi_params配置:
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
答案 0 :(得分:7)
将root
指令放在location
块之外作为server
块的直接子节点修复了该问题。
server {
listen 80;
server_name example.com;
# This WORKS!
root /var/www/example/public;
location / {
try_files $uri $uri/ /index.php?$args;
index index.php index.html index.htm;
}
if (!-d $request_filename) {
rewrite ^/(.*)/$ /$1 permanent;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location ~ \.php$ {
try_files $uri $uri/ /index.php?$args;
index index.php index.html index.htm;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example/public$fastcgi_script_name;
fastcgi_param APPLICATION_ENV testing;
fastcgi_param PATH /usr/bin:/bin:/usr/sbin:/sbin;
fastcgi_intercept_errors on;
include fastcgi_params;
}
}
显然,这是Nginx wiki建议避免的pitfall。