Nginx 上没有尾部斜线的虚荣 URL

Vanity URLs without trailing slashes on Nginx

在@jon-lin 的帮助下,我们找到了在 Apache 上删除尾部斜杠的方法 ();现在,当我们计划 运行 我们的网站在 Nginx 上时,我们也想这样做。我们尝试了在 Whosebug 和其他地方找到的几个建议,但都导致无限循环(可能是因为浏览器试图将斜杠放回原处)。我们当前的配置(我们的三个尝试 -- rewrite ^/(.*)/$ https://www.example.com/ permanent; rewrite ^/(.*)/$ https://www.example.com/;rewrite ^/(.*)/$ / 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/ permanent;
        #rewrite ^/(.*)/$ https://www.example.com/;
        #rewrite ^/(.*)/$ / 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 ^(.*[^/])$ //

然后,重写 /profiles/ 中的所有条目是这样完成的:

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

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

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

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

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

如果您想要一个类似于您以前的 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/; 
  }
  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$  permanent; }
}

它是无斜杠和无扩展名的混合体php,您的个人资料会有所调整。

将@richard-smith 在他的回答中的第一个选项与 "evil" if 相结合,我们成功了:

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

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

现在所有尾部斜杠都消失了,example.com/profiles/profile/ 中的配置文件被重写为 example.com/profile