URL 在 htaccess 重写规则之前解码

URL Decoded Prior to htaccess Rewrite Rule

我在 .htaccess 中有以下重写规则:-

RewriteRule ^.*/-y.* /handleurl.php [L]

其目的是根据url中的值显示合适的页面,例如:

example.com/books/BookA/-y?act=x会显示bookA页

保存书名的变量被编码为...

example.com/books/Book B/-y?act=x 变为 example.com/books/book+B/-y?act=x ...很好(在 handleurl.php 中解码)

但是如果这本书叫 Book A/B 我有...

example.com/books/Book A/B/-y?act=x 变为 example.com/books/Book+A%2FB/-y?act=x

htaccess 似乎在重写规则之前对此进行了解码,因此重写规则在 /.

所描述的 URL 中看到了太多元素

有什么方法可以让重写规则按预期忽略编码的 / 吗?

之前看到过类似问题的回复,不过我只需要忽略/,其他编码字符都不需要。

It appears that htaccess decodes this before the rewrite rule, so the rewrite rule sees too many elements in the URL delineated by the /

这不是问题所在。不管URL-路径/books/Book+A%2FB/-y是否解码在这里都没有区别*1。两者都将匹配 RewriteRule 模式 .

中的(相当慷慨的)正则表达式 ^.*/-y.*

(*1 但是,是的,URL-路径与 RewriteRule 模式匹配 被 URL 解码,即 %-解码。)

问题很可能是 Apache(默认情况下)拒绝 - 使用 404 - 任何包含 % 编码斜杠的 URL 即。 %2F(或反斜杠 %5C)在 URL 的 URL 路径部分。这是一项 安全功能 ,否则“可能会允许不安全的路径”(source)。

但是,这可以用 AllowEncodedSlashes 指令覆盖。但是该指令只能在 servervirtualhost 上下文中使用。它不能在 .htaccess.

中使用

您要么需要设置 AllowEncodedSlashes On 以允许编码的斜杠,它也像其他字符一样被解码。或者设置 AllowEncodedSlashes NoDecode 以允许编码的斜杠,但不要对其进行解码 - 这是首选并且可能是您所期望的。


旁白#1:

RewriteRule ^.*/-y.* /handleurl.php [L]

正则表达式 ^.*/-y.* 非常通用,可能太通用了。这与简单的 /-y 相同。 -y 之后的 .* 是什么意思?从你的例子 URLs 看起来 -y 总是在 URL-path 的末尾,所以这可以被锚定,例如。 /-y$。如果您需要匹配的 URL 始终以 /books/ 开头,那么也许这也应该包含在正则表达式中?


旁白#2:

...the book name is encoded such that ...

example.com/books/Book B/-y?act=x becomes example.com/books/book+B/-y?act=x ... which is fine (it's decoded in handleurl.php)

这不是严格意义上的“URL 编码”,您已经转换 space+ 在 URL 路径中。仅在查询字符串中使用时,+space 的有效“URL 编码”。 URL 路径中的 + 是文字 +(搜索引擎也会看到)。在 URL 路径中,space 将被 URL 编码为 %20。 (您可能使用了错误的 PHP 编码函数,例如 urlencode() 而不是 rawurlencode()?)

当然,您可以自由地 convert/encode URL,但是您希望创建更具可读性的 URL - 只要它是有效的。

重写规则从来都不是问题。我认为这是 Apache 不喜欢编码的 '/' 以及下游 url 处理程序在识别单个 url 元素时使用 '/' 作为分隔符的事实。我必须解决:1)我是否要在构成 freindly url 的元素的变量中允许“/”,以及 2)如果是这样,如何在不扰乱 Apache 的情况下传递它以及如何随后剖析url。也许为了 URL 的好处,我会将“/”转换为“~”,然后在后续显示之前转换回“/”。谢谢怀特先生。