删除多个尾随斜杠 mod_rewrite

Posted

技术标签:

【中文标题】删除多个尾随斜杠 mod_rewrite【英文标题】:remove multiple trailing slashes mod_rewrite 【发布时间】:2011-02-20 05:35:55 【问题描述】:

我知道这个问题仅在这个网站上就被问过很多次,但是浏览相关帖子我找不到解决方案。尝试在域后删除多个尾随斜杠。以下 mod_rewrite 表达式似乎适用于http://www.domain.com//path1///path2//// 等 URL,但不适用于域//

DirectorySlash Off

RewriteEngine on

# Canonical fix
RewriteCond %HTTP_HOST !^www.domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301]
RewriteRule ^/main.do http://www.domain.com/ [R=301,L]
RewriteRule ^/index.jsp http://www.domain.com/ [R=301,L]

# Remove bogus query strings
RewriteCond %query_string q= [NC]
RewriteRule (.*) http://www.domain.com/$1? [R=301,L]

# Remove multiple slashes after domain - DOESN'T WORK!!!
#RewriteCond %REQUEST_URI ^//+(.*)$ [OR]
#RewriteCond %REQUEST_URI ^(.*/)/+$
#RewriteRule / http://www.domain.com/%1 [R=301,L]

# Remove multiple slashes anywhere in URL
RewriteCond %REQUEST_URI ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

# Externally redirect to get rid of trailing slash except for home page, ads
RewriteCond %REQUEST_URI !^/ads/
RewriteRule ^(.+)/$ $1 [R=301,L]

【问题讨论】:

但是 'domain//' 不是一个有效的 URI?!?,因为 'domain' 不是 TLD 格式。如果这是内部设置,请使用 domain.lan 或者如果您的意思是“localhost//”,则在您的主机文件中添加一个条目。 艾登,我不允许发布多个 URL,因此我必须缩写。澄清 domain.com// 不起作用。感谢您抽出宝贵时间回复,博彦 对于最短的解决方案,请查看 Gerben 对此问题的回答。 ***.com/questions/8460015/… 【参考方案1】:

无法复制。域之后的额外斜杠永远不会传递给 mod_rewrite,即使 DirectorySlashes 关闭——我还没有检查是 Opera 还是 Apache 删除了斜杠)。但除此之外,一切正常:

RewriteBase /
RewriteCond %REQUEST_URI ^//+(.*)$ [OR]
RewriteCond %REQUEST_URI ^(.*/)/+$
RewriteRule .* http://domain/%1 [R=301,L]

请求http://localhost//abc/b//

127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (3) [perdir C:/HTTP/htdocs/] add path info postfix: C:/HTTP/htdocs/abc -> C:/HTTP/htdocs/abc/b/
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (3) [perdir C:/HTTP/htdocs/] strip per-dir prefix: C:/HTTP/htdocs/abc/b/ -> abc/b/
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (3) [perdir C:/HTTP/htdocs/] applying pattern '.*' to uri 'abc/b/'
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (4) [perdir C:/HTTP/htdocs/] RewriteCond: input='/abc//b//' pattern='^//+(.*)$' => not-matched
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (4) [perdir C:/HTTP/htdocs/] RewriteCond: input='/abc//b//' pattern='^(.*/)/+$' => matched
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (2) [perdir C:/HTTP/htdocs/] rewrite 'abc/b/' -> 'http://domain//abc//b/'
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (2) [perdir C:/HTTP/htdocs/] explicitly forcing redirect with http://domain//abc//b/
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (1) [perdir C:/HTTP/htdocs/] escaping http://domain//abc//b/ for redirect
127.0.0.1 - - [17/May/2010:12:26:36 +0100] [localhost/sid#c08fb0][rid#2756540/initial] (1) [perdir C:/HTTP/htdocs/] redirect to http://domain//abc//b/ [REDIRECT/301]

注意:考虑不要对主机进行硬编码:

RewriteCond %HTTP_HOST !=""
RewriteCond %REQUEST_URI ^//+(.*)$ [OR]
RewriteCond %REQUEST_URI ^(.*/)/+$
RewriteRule .* http://%HTTP_HOST/%1 [R=301,L]

还要注意内部的“//”没有被替换。您将添加另一个规则来替换内斜线。

新编辑: 好的,这似乎可以防止 URL 以 //:

开头或结尾
RewriteEngine on
RewriteBase /
RewriteCond %HTTP_HOST !=""
RewriteCond %THE_REQUEST ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %THE_REQUEST ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
RewriteRule .* http://%HTTP_HOST/%1 [R=301,L]

【讨论】:

Artefacto,localhost//abc//b// 可以正常工作,localhost// 不行。感谢 %HTTP_HOST 提示。我已经列出了表达式以及日志的摘录。 # 删除域后的多个斜杠 - 仍然不起作用!!! RewriteCond %HTTP_HOST !="" RewriteCond %REQUEST_URI ^//+(.*)$ [OR] RewriteCond %REQUEST_URI ^(.*/)/+$ RewriteRule .* http://%HTTP_HOST /%1 [R=301,L] RewriteCond %REQUEST_URI ^(.*)//(.*)$ RewriteRule 。 %1/%2 [R=301,L] 127.0.0.1 - - [18/May/2010:06:13:19 -0700] "GET /// HTTP/1.1" 200 10626 谢谢,博彦 也许它可以使用 THE_REQUEST 而不是 REQUEST_URI。我回家后会检查一下 第一个解决方案不适用于域后的双斜杠,但适用于结束域的双斜杠。对我来说,使用 THE_REQUEST 的解决方案适用于这两种情况。使用 rewriteloglevel 9 发布您的重写日志。【参考方案2】:

以下是似乎有效的完整清单:

DirectorySlash Off
RewriteEngine on

# Fix Canonical URLs
RewriteCond %HTTP_HOST !^www.domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301]
RewriteRule ^/main.do http://www.domain.com/ [R=301,L]
RewriteRule ^/index.jsp http://www.domain.com/ [R=301,L]

# Remove bogus query strings
RewriteCond %HTTP_HOST !=""
RewriteCond %query_string q= [NC]
RewriteRule (.*) http://%HTTP_HOST/$1? [R=301,L]

# Remove multiple slashes after domain
RewriteCond %HTTP_HOST !=""
RewriteCond %THE_REQUEST ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %THE_REQUEST ^[A-Z]+\s(.*/)/+\sHTTP/[0-9.]+$
RewriteRule .* http://%HTTP_HOST/%1 [R=301,L]

# Remove multiple slashes anywhere in URL
RewriteCond %REQUEST_URI ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

# Externally redirect to get rid of trailing slash except for home page and ads
RewriteCond %REQUEST_URI !^/ads/
RewriteRule ^(.+)/$ $1 [R=301,L]

【讨论】:

【参考方案3】:

您是在告诉 Apache 将包括第一个斜杠在内的所有内容映射到 $1

RewriteRule ^(.*)$ domain/$1 [R=301]

RewriteRule (.*) domain/$1? [R=301,L]

RewriteRule ^(.+)/$ $1 [R=301,L]

在插入符号后添加一个斜杠或在您的域名后删除一个斜杠

【讨论】:

【参考方案4】:

以下代码将去除所有多余的斜杠,包括域后的多余斜杠。

RewriteCond %THE_REQUEST //
RewriteRule ^(.*)$ /$1 [L,R=301]

【讨论】:

【参考方案5】:

这个在发送重定向之前删除了所有的斜线

# if match set environment variable and start over
RewriteRule ^(.*?)//+(.*)$ $1/$2 [E=REDIR:1,N]

# if done at least one. redirect with 301
RewriteCond %ENV:REDIR 1
RewriteRule ^/(.*) /$1 [R=301,L]

【讨论】:

以上是关于删除多个尾随斜杠 mod_rewrite的主要内容,如果未能解决你的问题,请参考以下文章

带有 nginx 的 Gatsby - 重定向被破坏 - 尾随 /(斜杠)

将多个空间合并为单个空间;删除尾随/前导空格

sh 删除多个文件中的尾随空格

在两种不同的场景中,尾随斜杠在URL中扮演什么实际角色?

如何删除前导和尾随的空格以及字符串中的多个空格? [复制]

GNU Make - 尾随“/”被删除?