redirect - 仅当目录不存在时,如何从 nginx 中的 URL 中删除尾部斜杠?

标签 redirect configuration nginx trailing-slash

我正在 nginx 1.4.1 上使用 PHP-FastCGI 运行服务器。目前我已对其进行设置,以便它从我的 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 中的服务器 block :

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;

最佳答案

root 指令放在 location block 之外作为 server block 的直接子级解决了该问题。

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;
    }
}

显然这是一个pitfall Nginx wiki 建议避免。

关于redirect - 仅当目录不存在时,如何从 nginx 中的 URL 中删除尾部斜杠?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18422092/

相关文章:

php - 重定向到 Facebook 页面

java - JMeter 中的网站 URL 正在重定向并且未加载测试 URL

mysql - 如何连接到 myslqd.socket?

java - com.sun.proxy.$Proxy219 无法使用 Java Config 进行转换,但它可以与 xml 一起正常工作

ssl - NGINX 中的 gnutls 和 openssl 握手

javascript - 停止表单操作重定向或 href 重定向

http - 我需要使用 http 重定向代码 302 还是 307?

php - 如何配置 nginx 重写规则以使 CakePHP 在 CentOS 上运行?

ruby-on-rails - 使用 nginx 反向代理的 Puma 静默崩溃

amazon-web-services - ELB 和 EC2 之间发生 408 请求超时错误