Many posters have problems debugging their RewriteRule and RewriteCond statements within their .htaccess files. Most of these are using a shared hosting service and therefore don't have access to the root server configuration. They cannot avoid using .htaccess files for rewriting and cannot enable a RewriteLogLevel" as many respondents suggest. Also there are many .htaccess-specific pitfalls and constraints are aren't covered well. Setting up a local test LAMP stack involves too much of a learning curve for most.

所以我的问题是我们建议他们如何自己调试他们的规则。以下是我的一些建议。其他建议将不胜感激。

Understand that the mod_rewrite engine cycles through .htaccess files. The engine runs this loop: do execute server and vhost rewrites (in the Apache Virtual Host Config) find the lowest "Per Dir" .htaccess file on the file path with rewrites enabled if found(.htaccess) execute .htaccess rewrites (in the user's directory) while rewrite occurred So your rules will get executed repeatedly and if you change the URI path then it may end up executing other .htaccessfiles if they exist. So make sure that you terminate this loop, if necessary by adding extra RewriteCond to stop rules firing. Also delete any lower level .htaccess rewrite rulesets unless explicitly intent to use multi-level rulesets. Make sure that the syntax of each Regexp is correct by testing against a set of test patterns to make sure that is a valid syntax and does what you intend with a fully range of test URIs. See answer below for more details. Build up your rules incrementally in a test directory. You can make use of the "execute the deepest .htaccess file on the path feature" to set up a separate test directory (tree) and debug rulesets here without screwing up your main rules and stopping your site working. You have to add them one at a time because this is the only way to localise failures to individual rules. Use a dummy script stub to dump out server and environment variables. (See Listing 2)If your app uses, say, blog/index.php then you can copy this into test/blog/index.php and use it to test out your blog rules in the test subdirectory. You can also use environment variables to make sure that the rewrite engine in interpreting substitution strings correctly, e.g. RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html] and look for these REDIRECT_* variables in the phpinfo dump. BTW, I used this one and discovered on my site that I had to use %{ENV:DOCUMENT_ROOT_REAL} instead. In the case of redirector looping REDIRECT_REDIRECT_* variables list the previous pass. Etc.. Make sure that you don't get bitten by your browser caching incorrect 301 redirects. See answer below. My thanks to Ulrich Palha for this. The rewrite engine seems sensitive to cascaded rules within an .htaccess context, (that is where a RewriteRule results in a substitution and this falls though to further rules), as I found bugs with internal sub-requests (1), and incorrect PATH_INFO processing which can often be prevents by use of the [NS], [L] and [PT] flags.

还有什么评论或建议吗?

清单1——phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);

当前回答

也许调试重写规则的最好方法是根本不使用重写规则,而是将URL处理从htaccess文件推迟到PHP文件(让我们称之为router.php)。然后,您可以使用PHP进行任何您喜欢的操作,并使用适当的错误检测和常规的调试方法。这甚至运行得更快,因为您不必使用重写模块。

对于文件系统中没有的URL,要立即将控制权从.htaccess转移到router.php,只需在.htaccess中放入以下一行:

FallbackResource router.php

是的,真的很简单。是的,它确实有效。试一试。

注意:你可能需要在你的。htaccess文件中使用一个ErrorDocument指令来在HTTP状态404时显式地将某些url的控制权传递给你的router.php文件,特别是如果你继承了处理状态404的父htaccess文件。这样一来,将控制权传递到路由器文件总共需要两行。

其他回答

如果您正在创建重定向,请使用curl进行测试,以避免浏览器缓存问题。 使用-I只获取http头信息。 使用-L跟随所有重定向。

(类似Doin的想法) 为了显示正在匹配的内容,我使用以下代码

$keys = array_keys($_GET);
foreach($keys as $i=>$key){
    echo "$i => $key <br>";
}

将其保存到服务器根目录下的r.php,然后在.htaccess中进行一些测试 例如,我想匹配不以语言前缀开始的url

RewriteRule ^(?!(en|de)/)(.*)$ /r.php?$1&$2 [L] #$1&$2&...
RewriteRule ^(.*)$ /r.php?nomatch [L] #report nomatch and exit

as pointed out by @JCastell, the online tester does a good job of testing individual redirects against an .htaccess file. However, more interesting is the api exposed which can be used to batch test a list of urls using a json object. However, to make it more useful, I have written a small bash script file which makes use of curl and jq to submit a list of urls and parse the json response into a CSV formated output with the line number and rule matched in the htaccess file along with the redirected url, making it quite handy to compare a list of urls in a spreadsheet and quickly determine which rules are not working.

我在调试我的mod_rewrite问题时发现了这个问题,它肯定有一些有用的建议。但最后最重要的事情是确保你的正则表达式语法正确。由于我自己的RE语法存在问题,安装regexpCheck.php脚本不是一个可行的选择。

但是由于Apache使用与perl兼容的正则表达式(PCRE),任何有助于编写PCRE的工具都应该有帮助。我曾经在Java和Javascript REs中使用过RegexPlanet的工具,并且很高兴地发现它们也支持Perl。

只需输入正则表达式和一个或多个示例URL,它就会告诉你正则表达式是否匹配(“~=”列中的“1”),如果适用,任何匹配组(“split”列中的数字将对应于Apache期望的数字,例如$1,$2等)。他们声称PCRE支持是“测试版”,但这正是我解决语法问题所需要的。

http://www.regexplanet.com/advanced/perl/index.html

我本可以简单地在已有的答案上添加一条评论,但我的声誉还没有达到那个水平。希望这能帮助到一些人。

设置环境变量并使用报头接收它们:

你可以用RewriteRule行创建新的环境变量,如OP所述:

RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

但是,如果不能让服务器端脚本工作,那么如何读取这个环境变量呢?一个解决方案是设置一个头文件:

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

该值接受格式说明符,包括用于环境变量的%{NAME}e说明符(不要忘记小写e)。有时,您需要添加REDIRECT_前缀,但我还不知道什么时候添加前缀,什么时候不添加前缀。