RewriteRule追加不需要的字符串

时间:2019-12-11 21:16:31

标签: regex apache .htaccess mod-rewrite url-routing

我不想怪RewriteRule,但是在我看来,这很重要。

最小示例。在实际的代码中,第一个Rule做一些前置,因此与之相反,它具有一些含义。

RewriteRule ^(.*)$ $1

RewriteCond %{REQUEST_URI} ^/pre
RewriteRule ^(.*)$ /post=$1 [R=301,L]

当提交的URL为example.com/pre/sub时,我得到301到example.com/post=pre/sub/sub。我不知道第二个子从哪里来。

我认为这应该可行。第一条规则$1pre/sub,因此它将pre/sub重写为pre/sub。 cond检查REQUEST_URI是否以/ pre开头并防止循环,并且最后一条规则匹配所有内容,因此$1pre/sub,并将其附加到创建的/post=pre/sub上,然后将其重定向到。但是浏览器得到/post=/pre/sub/sub

我已经做过一些测试:

仅提交example.com/pre会产生预期的/post=pre

当我将示例修改为

RewriteRule ^(.*)$ -$1-

RewriteCond %{REQUEST_URI} ^/pre
RewriteRule ^(.*)$ /post=&$1& [R=301,L]

结果重定向到/post=&-pre/sub-/sub&,这意味着它被附加到第一个规则的“之后”,但第二个规则的“之前”。但是在哪里和如何?

1 个答案:

答案 0 :(得分:0)

Pheeew ...这让我有些头疼。经过一番挖掘之后,我决定为mod_rewrite打开日志记录。 <my-docroot-path>是我机器上文档根目录的绝对路径。

add path info postfix: <my-docroot-path>/pre -> <my-docroot-path>/pre/sub
strip per-dir prefix: <my-docroot-path>/pre/sub -> pre/sub
applying pattern '^(.*)$' to uri 'pre/sub'
rewrite 'pre/sub' -> 'pre/sub'
add per-dir prefix: pre/sub -> <my-docroot-path>/pre/sub
add path info postfix: <my-docroot-path>/pre/sub -> <my-docroot-path>/pre/sub/sub
strip per-dir prefix: <my-docroot-path>/pre/sub/sub -> pre/sub/sub
applying pattern '^(.*)$' to uri 'pre/sub/sub'

正如您在第1行和第6行看到的那样,正在进行一些后缀处理。显然,它会将路径组件附加到当前已处理目录的上方。当前处理的目录(.htaccess的位置)是文档根目录(/),因此它“希望”您处理当前目录级条目(/pre)。完成处理后(使用RewriteRule),它将嵌套的路径组件附加到该结果。

这就是为什么当您在同一目录级别上处理请求时,它不会造成任何问题,因为没有要追加的内容。

可以(通过并建议将其固定)通过在该RewriteRule指令中添加DPI标志来进行修复。 DPI的意思是“丢弃路径信息”,它丢弃嵌套的路径组件,这些组件将被后缀化,因此不附加任何内容。

或者...如果您不想更改嵌套路径,只需在替换字符串中仅包含当前级别目录/文件名即可。其余的将后缀。这(至少对我而言)有些误导,因为该模式是与整个路径匹配的,但是它希望您仅更改(包括在替换字符串中)当前级别的目录/文件名。但这是有道理的……它为您提供了一个进行决策的环境,并希望您仅更改.htaccess所属的目录级别的部分。

这是它的官方错误报告。
https://bz.apache.org/bugzilla/show_bug.cgi?id=38642

DPI标志的文档
https://httpd.apache.org/docs/current/rewrite/flags.html#flag_dpi

还有其他一些SO主题,这很有帮助
https://stackoverflow.com/a/5520004/2468189