在Nginx上没有尾部斜杠的虚荣URL

时间:2015-12-05 19:59:55

标签: nginx rewrite trailing-slash

在@ jon-lin的帮助下,我们想出了如何删除Apache上的尾部斜杠(Vanity URLs without trailing slashes on Apache);现在,当我们计划在Nginx上运行我们的网站时,我们也想做同样的事情。我们在stackoverflow和其他地方尝试了几个建议,但都导致了无限循环(可能是因为浏览器试图将斜杠放回去)。我们当前的配置(我们的三次尝试 - rewrite ^/(.*)/$ https://www.example.com/$1 permanent; rewrite ^/(.*)/$ https://www.example.com/$1;rewrite ^/(.*)/$ /$1 permanent; - 已注释掉)是:

server {
        listen 80;
        server_name  example.com;
        return 301 https://www.example.com$request_uri;
}
server {
        listen 80;
        server_name  www.example.com;
        return 301 https://www.example.com$request_uri;
}
server {
        listen 443;
        server_name  example.com;
        return 301 https://www.example.com$request_uri;
}

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        server_name www.example.com;

        #rewrite ^/(.*)/$ https://www.example.com/$1 permanent;
        #rewrite ^/(.*)/$ https://www.example.com/$1;
        #rewrite ^/(.*)/$ /$1 permanent;

        root /var/www/example.com/html;
        index index.php index.html index.htm;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
        }

        ssl on;
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECD$
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        ssl_dhparam /etc/ssl/certs/dhparam.pem;

}

如何做到这一点?

在我们的特定情况下,我们需要删除所有URL的尾部斜杠;我们通过在Apache的httpd.conf中添加以下内容来实现这一点:

DirectorySlash Off

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/

然后,重写/profiles/中的所有条目都是通过以下方式完成的:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /profiles/$1 [NC,L]

2 个答案:

答案 0 :(得分:1)

如果您不再使用/ profiles /目录,这应该有效:

server {
  ...
  root /var/www/example.com/html;
  index index.php index.html index.htm;

  location / {
    try_files $uri @rewrite;
  }
  location @rewrite {   
    rewrite ^(.*[^/])$ $1/; 
  }
  location ~ \.php$ { ... }
}

在上面的配置中,我们避开$uri/上的try_files元素,因为它会触发向当前网址添加尾随/的重定向。

如果您想要一个类似于以前的Apache配置的配置,那么这应该可行:

server {
  ...
  root /var/www/example.com/html;
  index index.php index.html index.htm;

  location / {
    try_files $uri $uri/ @rewrite;
  }
  location @rewrite {   
    rewrite ^(.*[^/])$ /profiles$1/; 
  }
  location ~ \.php$ { ... }
}

正如您所看到的,$uri/元素在这种情况下没有任何危害。

根据您的评论和最近的编辑,这第三个(不太优雅)的配置结合了其他两个的功能,并且是Apache配置的紧密(但不是确切)实现:

server {
  ...
  root /var/www/example.com/html;
  index index.php index.html index.htm;

  location = / { rewrite ^ /index.php; }
  location / {
    try_files $uri @rewrite;
  }
  location @rewrite {
    if (-d $document_root/profile$uri) { rewrite ^ /profiles$uri/ last; }
    if (-d $request_filename) { rewrite ^(.*[^/])$ $uri/ last; }
  }
  location ~ \.php$ { ... }
}

最后,这个版本略有偏离。 php执行块由命名位置替换。但确实允许使用级联try_files指令,删除讨厌的if指令,并在此过程中丢弃index。享受:

server {
  ...
  root /var/www/example.com/html;

  location / {
    try_files $uri $uri.html $uri/index.html /profiles$uri/index.html @php;
  }
  location @php {
    try_files $uri.php $uri/index.php /profiles$uri/index.php =404;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
  }
  location ~ \.php$ { rewrite ^(.*)\.php$ $1 permanent; }
}

它是无斜线和无扩展的php的混合体,可以调整你的个人资料。

答案 1 :(得分:0)

将@ richard-smith在答案中的第一个选项与“邪恶”if相结合,我们让它发挥作用:

    location / {
        if (!-e $request_filename) {
        rewrite ^(.*)$ /profiles$1/ break;
        }
        try_files $uri @rewrite;
    }

    location @rewrite {
        rewrite ^(.*[^/])$ $1/;
    }

现在所有尾随斜杠都消失了,example.com/profiles/profile/中的个人资料被重写为example.com/profile