用.htaccess中的连字符替换下划线但卡在循环中

时间:2017-02-20 14:48:06

标签: .htaccess mod-rewrite

我已经按照各种示例使用mod-rewrite从包含下划线的网址重定向到包含连字符的网址。但它陷入了困境,我无法理解错误。

我想重定向以下网址:

http://www.example.org/blog/archive/2016/12/31/my_post_slug_here.html

为:

http://www.example.org/blog/2016/12/31/my-post-slug-here/

所有这些都很简单,除了下划线到连字符。我目前在.htaccess文件中有这个:

RewriteRule ^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]*)_([^_]*_.*).html$ blog/archives/$1/$2-$3.html [N]
RewriteRule ^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]*)_([^_]*).html$ /blog/$1/$2-$3/ [R=301,L]

如果我使用的网址只包含一个下划线(例如.../my-post-slug_here.html),则第二条规则会重定向。但是第一个 - 它应该递归地用连字符替换下划线,直到只剩下一个 - 被卡在一个循环中。我的日志看起来像:

[Mon Feb 20 14:35:47.430250 2017] [rewrite:trace3] [pid 7844] mod_rewrite.c(476): 
[client 192.168.33.1:54128] 192.168.33.1 - - [www.example.dev/sid#7f6f3fcdecc8][rid#7f6f3fbb20a0/initial] 
[perdir /var/www/public/] applying pattern 
'^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]*)_([^_]*_.*).html$' to uri 
'blog/archives/2016/12/31/my-post-slug-here.html/archives/2016/12/31/my-post-slug-here.html/archives/2016/12/31/my-post-slug-here.html/archives/2016/12/31/my-post-slug-here.html/archives/2016/12/31/my-post-slug-here.html/archives/2016/12/31/my-post-slug-...

所以看起来它取代了下划线,然后以某种方式卡住......

2 个答案:

答案 0 :(得分:1)

你的规则几乎是正确的。问题是Apache正在将原始路径信息附加到重写的URI,并且它将进入无限循环(由于标记N到位)。

您需要添加DPI flag (Discard Path) N来阻止此行为。

经过一些重构后,您的规则可以是:

# redirect when we have only one underscore in URI
RewriteRule ^blog/archives/(\d{4}/\d{2}/\d{2})/([^_]*)_([^_]*)\.html$ /blog/$1/$2-$3/ [R=301,NC,NE,L]

# otherwise keep replacing underscore with hyphen in a loop
RewriteRule ^(blog/archives/\d{4}/\d{2}/\d{2})/([^_]*)_([^_]*_.*\.html)$ $1/$2-$3 [N,NC,DPI]

答案 1 :(得分:0)

不确定这是否有所不同,但可以尝试通过在前面添加/来使规则的目标成为绝对目标:

RewriteRule ^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]*)_([^_]*_.*).html$ /blog/archives/$1/$2-$3.html [N]

您可以尝试的另一件事是在没有下划线时重定向:

RewriteCond %{THE_REQUEST} blog/archives/[0-9]{4}/[0-9]{2}/[0-9]{2)/[^\ \?]*_
RewriteRule ^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]+).html$ /blog/$1/$2/ [R=301,L]

RewriteRule ^blog/archives/([0-9]{4}/[0-9]{2}/[0-9]{2})/([^_]*)_(.*).html$ /blog/$1/$2-$3.html [L]