1

也许我在做一些愚蠢的事情,但我无法摆脱 htaccess 的问题。

我正在尝试匹配文档站点中的函数名称,但遇到了我无法理解的错误。我必须指出我(认为我)知道正则表达式转义,并且我知道点和反斜杠点的含义。

所以:我想允许所有这些:

example.com/foofunction
example.com/foofunction.php
example.com/function.foofunction
example.com/function.foofunction.php

这些是我尝试过的线条。那些导致错误的人被误解了,非常感谢任何可以向我解释的人:

^function\.([A-Za-z0-9_-]+)(\.php)?$-> 有效,但function.强制

^(function\.)?([A-Za-z0-9_-]+)(\.php)?$-> 内部错误...好吧,我们不要转义点,最后,它将匹配任何字符并且可以工作...

^(function.)?([A-Za-z0-9_-]+)(\.php)?$-> 内部错误!好的,只是为了尝试,点外条件?

^(function)?\.([A-Za-z0-9_-]+)(\.php)?$-> 工作,好的,但它使 dot 成为强制性的。顺便说一句,更疯狂的事情:

^(function)?.([A-Za-z0-9_-]+)(\.php)?$-> 如果 dot 没有被转义(想象一下我想允许任何字符),也会出现内部错误。现在我将尝试单独使 dot 可选

^(function)?(\.)?([A-Za-z0-9_-]+)(\.php)?$-> 内部错误,我快疯了...

这些是我到目前为止的尝试,我将尝试可选的后视并更新结果......无论如何,我很想了解这些正则表达式会导致内部错误。

如果有人知道“htaccess 特殊正则表达式异常”参考或我必须阅读的类似内容,将非常欢迎。

在此先感谢大家。

4

1 回答 1

3

对除实际函数名之外的所有内容使用非捕获组:

^(?:function\.)?([A-Za-z0-9_\-]+)(?:\.php)?$

让我们分解一下:

^                   # assert start of string
  (?:function\.)?   # optionally allow the string "function."
  ([A-Za-z0-9_\-]+) # capture the function name - this could be shortened to ([-\w]+)
  (?:\.php)?        # optionally allow the string ".php"
$                   # assert end of string

所以你的 .htaccess 看起来(我猜)是这样的:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?:function\.)?([A-Za-z0-9_\-]+)(?:\.php)?$ doc.php?functionname=$1 [L,QSA]

重要点和这种情况下的实际解决方案:

必须使用RewriteCond和(通常)[L]标志的合理组合,以确保规则只匹配一次。

mod_rewrite 的行为方式有点违反直觉,并不总是很明显:它会一遍又一遍地运行规则,直到没有更多的匹配项。所以,假设我使用上面列出的规则:

RewriteRule ^(?:function\.)?([A-Za-z0-9_\-]+)(?:\.php)?$ doc.php?functionname=$1

...我向这条规则提供 input function.myfunc.php。首先,它将被重写为:

doc.php?functionname=myfunc

但是,下次它会再次匹配。它将被重写为:

doc.php?functionname=doc

...这将不断发生,直到MaxRedirects达到,Apache 将抛出一个错误 - 您将在客户端看到 500 响应。

对此的解决方案取决于您的确切用例,但一个常见的解决方案(我上面使用的那个)是在应用重写规则之前检查请求的文件是否存在。通过这样做,在第二次迭代中将不会应用该规则,并且将允许请求通过以进行进一步处理。

[L]标志也经常(过度)使用 - 这会导致重写过程的当前迭代停止,并在下一次迭代中重新开始。continue它有效地执行与PHP 中的循环相同的操作。

从 Apache 2.3 开始,一个更有用的标志(对于这种情况)可用 - [END]。这给出了大多数人期望的行为[L],它会导致重写过程立即停止而不再进行迭代,就像breakPHP 中的构造一样。使用它意味着上述RewriteConds 不再是必需的。但是,因为这仅在 2.3+ 中可用,所以除非您确定它在您运行的每个环境中都可用,否则无法安全使用它。

于 2012-12-17T12:54:28.877 回答