也许我做的事情很愚蠢,但我无法摆脱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)?$
- >工作,好吧,但它强制点。顺便说一句,更疯狂的事情:
^(function)?.([A-Za-z0-9_-]+)(\.php)?$
- >如果dot没有被转义(想象我想允许任何字符),内部错误也是如此。现在我将尝试单独制作点可选
^(function)?(\.)?([A-Za-z0-9_-]+)(\.php)?$
- >内部错误,我疯了......
这些是我到目前为止的尝试,我将尝试使用可选的lookbehind并使用结果进行更新...无论如何,我很想了解这些正则表达式导致内部错误。
如果有人知道“htaccess特殊正则表达式异常”参考或类似的东西我必须阅读,那将是非常好的。
先谢谢你们所有人。
答案 0 :(得分: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
...我向此规则提供了输入function.myfunc.php
。首先,它将被重写为:
doc.php?functionname=myfunc
但是,下次它会再次匹配。它将被重写为:
doc.php?functionname=doc
...这将一直持续发生,直到达到MaxRedirects
并且Apache将抛出错误 - 您将在客户端看到它作为500响应。
解决方案取决于您的确切用例,但一个常见的解决方案(我上面使用的解决方案)是在应用重写规则之前检查所请求的文件是否存在。通过执行此操作,在第二次迭代时,将不会应用规则,并且将允许请求进行进一步处理。
[L]
标志也常用(过)使用 - 这会导致重写过程的当前迭代停止,并在下一次迭代时重新开始。它实际上与continue
对PHP中的循环做了同样的事情。
从Apache 2.3开始,一个更有用的标志(对于这种情况)可用 - [END]
。这给出了大多数人期望[L]
的行为,它导致重写过程立即停止而没有进一步的迭代,比如PHP中的break
构造。使用这将意味着不再需要上述RewriteCond
。但是,由于这仅适用于2.3+,因此无法安全使用,除非您确定它将在您运行的每个环境中都可用。