调试 .htaccess 重写规则的提示

Tips for debugging .htaccess rewrite rules

提问人:TerryE 提问时间:2/6/2012 最后编辑:CommunityTerryE 更新时间:12/2/2022 访问量:141335

问:

许多发帖者在其 .htaccess 文件中调试其 RewriteRule 和 RewriteCond 语句时遇到问题。其中大多数都使用共享托管服务,因此无权访问根服务器配置。他们无法避免使用文件进行重写,也无法启用 RewriteLogLevel“,正如许多受访者所建议的那样。此外,还有许多特定的陷阱和约束没有得到很好的涵盖。对于大多数人来说,设置本地测试LAMP堆栈涉及太多的学习曲线。.htaccess.htaccess

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

  1. 了解 mod_rewrite 引擎循环处理 .htaccess 文件。引擎运行以下循环:

    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
    

    因此,您的规则将被重复执行,如果您更改 URI 路径,那么它最终可能会执行其他文件(如果存在)。因此,请确保在必要时通过添加额外的内容来终止此循环以停止规则触发。此外,删除任何较低级别的重写规则集,除非明确打算使用多级规则集。.htaccessRewriteCond.htaccess

  2. 通过针对一组测试模式进行测试,确保每个正则表达式的语法正确无误,以确保该语法是有效的,并且对各种测试 URI 执行预期操作。有关更多详细信息,请参阅下面的答案

  3. 在测试目录中以增量方式构建规则。您可以利用“在路径上执行最深的文件”功能来设置单独的测试目录(树)并在此处调试规则集,而不会搞砸您的主要规则并停止您的站点工作。您必须一次添加一个,因为这是将故障本地化为单个规则的唯一方法。.htaccess

  4. 使用虚拟脚本存根转储服务器和环境变量。(见清单 2)例如,如果您的应用程序使用,那么您可以将其复制到子目录中并使用它来测试您的博客规则。您还可以使用环境变量来确保重写引擎正确解释替换字符串,例如blog/index.phptest/blog/index.phptest

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

    并在 phpinfo 转储中查找这些 REDIRECT_* 变量。顺便说一句,我使用了这个,并在我的网站上发现我不得不使用。在重定向器循环的情况下,REDIRECT_REDIRECT_* 变量列出上一遍。 等等。%{ENV:DOCUMENT_ROOT_REAL}

  5. 确保您不会被浏览器缓存不正确的 301 重定向所困扰。请参阅下面的答案。我感谢乌尔里希·帕尔哈(Ulrich Palha)。

  6. 重写引擎似乎对上下文中的级联规则很敏感(即 a 导致替换的地方,这属于其他规则),因为我发现了内部子请求 (1) 的错误,以及不正确的PATH_INFO处理,这通常可以通过使用 [NS]、[L] 和 [PT] 标志来防止。.htaccessRewriteRule

还有什么意见或建议吗?

清单 1 -- phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);
Apache .htaccess mod-rewrite

评论

11赞 w00t 2/9/2012
这些都很好...也许你应该把它们从问题转移到答案中。
0赞 TerryE 2/13/2012
@w00t,我已经按照您的建议拆分了正则表达式检查器,因为我想在其他答案中通过链接引用它。
3赞 SáT 8/18/2012
您可能希望将文档中的控制流程图添加到您的第一个建议中。IMO 它比任何伪代码或解释都容易理解,这确实是 mod-rewrite voodoo 中最黑暗的部分。
0赞 Iain Collins 1/29/2013
数字 6 是一件大事。重写规则在标准apache配置文件中的行为与在.htaccess文件中的行为不同,必须吸引很多人。
0赞 Chris 12/19/2015
可能值得添加到这些提示中的一些内容:我花了一些时间调试一个问题,即重定向而不是重写。事实证明,当我想要“/comment/”时,我将其重写为“/comment”。它正在重写为“/comment”,然后服务器正在重定向到“/comment/”。对于那些习惯于Apache的人来说,这是显而易见的行为,但对于像我这样的菜鸟来说可能就不那么重要了。

答:

147赞 Ulrich Palha 2/9/2012 #1

以下是有关测试规则的一些其他提示,这些提示可能会简化共享主机上用户的调试

1. 使用假用户代理

测试新规则时,请添加一个条件,以仅使用将用于请求的用户代理执行该规则。这样,它就不会影响您网站上的任何其他人。fake

例如

#protect with a fake user agent
RewriteCond %{HTTP_USER_AGENT}  ^my-fake-user-agent$
#Here is the actual rule I am testing
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC] 
RewriteRule ^ http://www.domain.com%{REQUEST_URI} [L,R=302] 

如果您使用的是 Firefox,则可以使用 User Agent Switcher 创建虚假的用户代理字符串并进行测试。

2. 在完成测试之前不要使用 301

我看到很多帖子,人们仍在测试他们的规则,他们正在使用 301。不要

如果您没有在您的网站上使用建议 1,那么不仅您,而且当时访问您网站的任何人都会受到 301 的影响。

请记住,它们是永久性的,并且由您的浏览器主动缓存。 改用 302,直到您确定为止,然后将其更改为 301。

3. 请记住,301 会积极缓存在您的浏览器中

如果您的规则不起作用,并且您看起来正确,并且您没有使用建议 1 和 2,请在清除浏览器缓存后或在隐私浏览时重新测试。

4. 使用 HTTP 捕获工具

使用 HTTP 捕获工具(如 Fiddler)查看浏览器和服务器之间的实际 HTTP 流量。

虽然其他人可能会说你的,但你可以反而看到并报告,迅速缩小问题范围。site does not look rightall of the images, css and js are returning 404 errors

当其他人会报告你时,你将能够看到他们从 开始。即使 URL C 是最终目标,您也会知道这对 SEO 不利,需要修复。started at URL A and ended at URL CURL A, were 302 redirected to URL B and 301 redirected to URL C

您将能够看到在服务器端设置的缓存标头,重放请求,修改请求标头以进行测试......


评论

9赞 TerryE 2/12/2012
乌尔里希,非常感谢您的输入。你已经挑选了一些我没有想过要放在我的清单中的方面。关于 301 调试问题,我在“隐私浏览”(又名“色情模式”)中使用 Chrome,因为当您关闭窗口时,这会转储此状态信息。我希望你不介意我不“接受”这一点,因为这是一个重要的点,但不是一个好的答案。再次感谢。:)
1赞 icc97 2/12/2013
为了明确这一点(您的代码中确实有它,但没有发现它),但要确保您使用的是 302 而不是 301 重定向,您需要[L,R=302]
8赞 Rahil Wazir 6/6/2014
您无需显式指定,只需执行默认为[L, R=302][L,R]302
4赞 johnsnails 3/11/2016
@goodeye,还要查看“Chrome >设置>常规>在 DevTools 打开时禁用缓存”复选框。
10赞 TerryE 2/13/2012 #2

确保每个正则表达式的语法正确

通过针对一组测试模式进行测试,以确保该语法是有效的语法,并使用各种测试 URI 执行预期操作。

请参阅下面的 regexpCheck.php 以获取一个简单的脚本,您可以将其添加到站点中的私有/测试目录以帮助您执行此操作。我一直保持简短而不是漂亮。只需将其传递到测试目录中的文件中即可在您的网站上使用它。这将帮助您构建任何正则表达式,并在执行此操作时根据测试用例列表对其进行测试。我在这里使用的是PHP PCRE引擎,但是在查看了Apache源代码后,这与Apache中使用的引擎基本相同。有许多 HowTos 和教程提供了模板,可以帮助您培养正则表达式技能。regexpCheck.php

清单 1 -- regexpCheck.php

<html><head><title>Regexp checker</title></head><body>
<?php 
    $a_pattern= isset($_POST['pattern']) ? $_POST['pattern'] : "";
    $a_ntests = isset($_POST['ntests']) ? $_POST['ntests'] : 1;
    $a_test   = isset($_POST['test']) ? $_POST['test'] : array();
    
    $res = array(); $maxM=-1; 
    foreach($a_test as $t ){
        $rtn = @preg_match('#'.$a_pattern.'#',$t,$m);
        if($rtn == 1){
            $maxM=max($maxM,count($m));
            $res[]=array_merge( array('matched'),  $m );
        } else {
            $res[]=array(($rtn === FALSE ? 'invalid' : 'non-matched'));
        }
    } 
?> <p>&nbsp; </p>
<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME'];?>">
    <label for="pl">Regexp Pattern: </label>
    <input id="p" name="pattern" size="50" value="<?php echo htmlentities($a_pattern,ENT_QUOTES,"UTF-8");;?>" />
    <label for="n">&nbsp; &nbsp; Number of test vectors: </label>
    <input id="n" name="ntests"  size="3" value="<?php echo $a_ntests;?>"/>
    <input type="submit" name="go" value="OK"/><hr/><p>&nbsp;</p>
    <table><thead><tr><td><b>Test Vector</b></td><td>&nbsp; &nbsp; <b>Result</b></td>
<?php 
    for ( $i=0; $i<$maxM; $i++ ) echo "<td>&nbsp; &nbsp; <b>\$$i</b></td>";
    echo "</tr><tbody>\n";
    for( $i=0; $i<$a_ntests; $i++ ){
        echo '<tr><td>&nbsp;<input name="test[]" value="', 
            htmlentities($a_test[$i], ENT_QUOTES,"UTF-8"),'" /></td>';
        foreach ($res[$i] as $v) { echo '<td>&nbsp; &nbsp; ',htmlentities($v, ENT_QUOTES,"UTF-8"),'&nbsp; &nbsp; </td>';}
        echo "</tr>\n";
    }
?> </table></form></body></html>

评论

1赞 Jeff Lambert 5/28/2013
快速说明:在 PHP 5.3 中已弃用,并在 5.4 中删除。 coupled with 可以执行相同的功能,但所有变量都需要从其名称中删除前缀。来源:php.net/manual/en/function.import-request-variables.phpimport_request_variablesextract($_GET)extract($_POST)
0赞 TerryE 6/1/2013
@watcher,谢谢。一年前,我将本地版本更新为兼容 5.4,但忘记更改此帖子。现在完成了。
0赞 hexerei software 4/1/2015
哦,天哪,即使经过编辑,仅通过复制代码也无法获得良好的结果......但是有了正则表达式小提琴手,我认为你的工具无论如何都已经过时了。看看这些很酷的工具:regex101.comrefiddle.comregexr.com
0赞 TerryE 4/2/2015
@hexereisoftware,这篇文章已经有 3 年的历史了,因此根据现在使用的 PHP 版本和 Apache 版本,可能会存在一些微妙的问题。但是,正则表达式有许多变体,每个变体都有细微的差异。正如我所说,Apache代码使用的PCRE引擎与PHP引擎非常相似。我不确定与 .Net 等其他变体的区别是什么,所以虽然您使用在线资源的建议是一个很好的建议,但我会坚持使用明确支持 apache 或 PHP 语法的建议。:-)
0赞 hexerei software 4/2/2015
Perl 会最接近,但 php 使用相同的语法
3赞 Lambart 7/31/2012 #3

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

但是,由于Apache使用Perl兼容的正则表达式(PCRE),因此任何有助于编写PCRE的工具都应该有所帮助。我过去曾将 RegexPlanet 的工具用于 Java 和 Javascript RE,很高兴发现它们也支持 Perl。

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

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

我只是简单地在现有答案中添加评论,但我的声誉还没有达到那个水平。希望这对某人有所帮助。

评论

0赞 hexerei software 4/1/2015
不错的工具,但形式很糟糕......看看这些很酷的工具:regex101.comrefiddle.comregexr.com
8赞 Simon 1/29/2013 #4

确保在变量前面使用百分号,而不是美元符号。

它是 ,不是 。error_log中不会有任何内容,不会有内部服务器错误,您的正则表达式仍然正确,规则将不匹配。如果你经常使用 django / genshi 模板并在肌肉记忆中进行变量替换,这真的很可怕。%{HTTP_HOST}${HTTP_HOST}${}

评论

1赞 TerryE 9/4/2015
是的,$ 替换变量与最后一个 RewriteRule 模式相关,% 变量与最后一个 RewriteCond 模式和特殊变量(如 %{env:XXX})相关
9赞 Ruben 2/4/2013 #5

我浪费了几个小时中的一个:

如果您已经应用了所有这些提示,并且由于您无权访问服务器错误日志而只出现 500 个错误,那么问题可能不在于 .htaccess,而在于它重定向到的文件。

在我修复了我的 .htaccess 问题后,我又花了两个小时试图再修复它,即使我只是忘记了一些权限。

评论

0赞 TerryE 9/4/2015
我为我的个人网站使用共享访问托管网络服务,但我所做的是设置一个测试虚拟机,该虚拟机在 PHP / Apache 配置、主目录等方面大致反映了这一点。但是,由于此 VM 在我的管理员下,我可以启用重写日志记录来诊断任何困难的问题。.htaccess
5赞 Doin 3/15/2013 #6

关于4.,在完成所有重写后,您仍然需要确保您的“虚拟脚本存根”实际上是目标URL,否则您将看不到任何内容!

一个类似/相关的技巧(请参阅此问题)是插入一个临时规则,例如:

RewriteRule (.*) /show.php?url=$1 [END]

其中有一些非常简单的脚本,只显示其参数(如果需要,您也可以显示环境变量)。show.php$_GET

这将在将重写插入规则集时停止重写,就像调试器中的断点一样。

如果您使用的是 Apache <2.3.9,则需要使用 而不是 ,然后可能需要添加:[L][END]

RewriteRule ^show.php$ - [L]

在规则集的最顶部,如果 URL 本身正在被重写。/show.php

18赞 Krist van Besien 6/21/2013 #7

不要忘记,在 .htaccess 文件中,它是匹配的相对 URL。

在 .htaccess 文件中,以下 RewriteRule 永远不会匹配:

RewriteRule ^/(.*)     /something/$s

评论

4赞 TerryE 9/4/2015
是的,馈入重写规则的字符串是相对的,因此在任何前导上都会被剥离,但对于在重写Cond 命令中组装的匹配字符串,不会发生这种剥离。/
0赞 unloco 10/14/2013 #8

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

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

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

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

评论

1赞 TerryE 10/16/2013
正如我在 O/P 的第 4 点中提到的,只需使用 phpinfo() 存根就可以做基本相同的事情。查找QUERY_STRING
94赞 JCastell 2/6/2014 #9

在线.htaccess重写测试

我发现这个谷歌搜索正则表达式帮助,它为我节省了大量时间,让我不必在每次进行小修改时上传新文件。.htaccess

从网站:

HTSaccess测试仪

要测试您的htaccess重写规则,只需填写您应用规则的URL,将htaccess的内容放在较大的输入区域,然后按“立即检查”按钮。

评论

7赞 BobHy 4/3/2017
感谢您指向此工具的指针,我找到了调试问题的最直接方法。
0赞 sjas 8/31/2017
如果您对您的网站空间有 ssh 访问权限,另一种选择是直接通过服务器上的编辑器更改 .htaccess。
0赞 toddmo 4/27/2018
您需要忽略站点证书有问题的 ssl 警告 b/c。但该网站仍然存在。这是最好和最简单的解决方案。它提供了对问题所在令人难以置信的洞察力,并导致快速解决问题。
0赞 Benyamin Limanto 2/4/2019
感谢您指向此工具。这很有帮助,有时调试 apache htaccess 本身太难了。谢谢。非常感谢
2赞 Honsa Stunna 7/6/2020
首先,它看起来不错。但它错过了很多功能。不幸的是,这不是一个可靠的工具。
12赞 Flimm 7/22/2015 #10

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

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

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

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

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

该值接受格式说明符,包括环境变量的说明符(不要忘记小写 e)。有时,您需要添加前缀,但我还没有弄清楚何时添加前缀以及何时不添加前缀。%{NAME}eREDIRECT_

评论

0赞 SherylHohman 7/8/2019
您是否对何时使用或不使用前缀有了进一步的了解?此外,我也在其他 (htaccess) 上下文中看到了有关前缀的术语,但一直不清楚其确切含义。这是否意味着在使用某些命令(而不是其他命令)时,必须使用前缀命名变量,或将前缀添加到命名变量中?您的示例是第一个同时显示 var 定义和 var 用法的示例,因此我倾向于认为后者!这些文档几乎没有帮助 - 他们认为我们知道的太多了,并且提供的参考/链接太少。REDIRECT_
1赞 Gruber 9/4/2015 #11

我会把这个留在这里,也许是显而易见的细节,但让我头疼了几个小时: 请谨慎使用,因为 @Krist van Besien 在他的回答中所说的是完全正确的,但不适用于REQUEST_URI字符串,因为此 TestString 的输出以 .所以要小心:%{REQUEST_URI}/

RewriteCond %{REQUEST_URI} ^/assets/$  
                            ^
                            | check this pesky fella right here if missing
2赞 papo 1/28/2017 #12

如果您打算在 .htacesss 中编写不止一行规则,
甚至不要考虑尝试其中一种热修复方法来调试它。

我浪费了几天时间来制定多个规则,却没有得到 LOG 的反馈,但最终还是放弃了。
我把Apache放在我的PC上,把整个网站复制到它的HDD上,然后用日志把整个规则集整理出来,非常快。
然后我回顾了我的旧规则,这些规则一直有效。我看到他们并没有真正做想要做的事情。一颗定时炸弹,地址略有不同。

重写规则中有很多坑,这根本不是一个直接的逻辑问题。
您可以在十分钟内启动并运行Apache,它是10MB,良好的许可证,*NIX/WIN/MAC,即使没有安装。
此外,检查服务器的标题行,并从其存档中获取相同版本的 Apache(如果它是旧的)。我的 OP 还在 2.0 上;许多事情都不受支持。

评论

1赞 TerryE 1/29/2017
papo,我已经在我的开发结构中运行了专用服务器、ISP 托管的 VPS 和私有虚拟机,但我仍然为我的公共域和电子邮件使用共享托管服务,仅仅是因为使用完全托管的服务更方便、更经济高效。本指南真正针对的是共享服务用户。配置专用 VM 以完全镜像共享服务很困难。是的,如果可以的话,使用测试虚拟机会有所帮助,但我仍然不时在我的共享服务上使用这些“技巧”。
2赞 TerryE 1/29/2017
如果你的 A 被框定为调试规则的替代建议,我会同意这一点,但开头的“甚至不要考虑它”对于基本的共享服务用户来说简直是糟糕的建议,他们正在努力理解为什么他们的文件没有按照他们应该的方式工作。mod_rewritehtaccess
0赞 papo 1/30/2017
我很抱歉,如果听起来你整理一系列很好的建议的工作毫无价值。我不想那样。相信我,我很高兴阅读并遵循此线程提供的许多建议。但是我的规则慢慢变得复杂,最后,我浪费了很多时间,只是不想经历安装Apache服务器和进行调试的麻烦。不仅如此,我什么也没学到,因为我在日志中没有看到真正发生的事情。还有很多事情正在发生。我相信分享这段经历也很有价值。
0赞 papo 1/30/2017
对于第二部分,有一个 IF。我现在看到的文字从来没有以“甚至不要考虑”开头,这个措辞似乎有点苛刻,但都是真的。特别是对于那些不熟悉这个并且难以理解的人。这里的建议可能会误导他们,就像我一样,我需要的只是一个可靠的正则表达式,它不是那么简单,就像你的观点 6) PATH_INFO花费了我很多麻烦,而且它不是你说的错误,而是一个功能。如果您不希望重新添加它,请使用 [DPI]。但只有当您查看日志时,您才会看到它正在被添加到那里。这就是为什么,不止一行,你最好使用日志
2赞 TerryE 1/31/2017
对不起@papo,但我投 -1 票的原因是我认为这个“甚至不考虑”是坏建议,IMO。如果你的观点是“超过一定的复杂性,那么你可能会发现安装本地Apache服务来调试你的文件更容易”,那么这就更平衡了。是的,设置本地 Apache 服务相当容易,但让它反映服务提供商的共享托管服务可能很复杂,并且超出了许多用户的技能水平,他们可能刚刚使用过 Wordpress 的一键式设置,比如说,他们的文件有问题。.htaccess.htaccess
6赞 flm 3/14/2017 #13

如果要创建重定向,请使用 curl 进行测试以避免浏览器缓存问题。 使用 -I 仅获取 http 标头。 使用 -L 跟踪所有重定向。

4赞 Abhishek Gurjar 3/27/2017 #14

我观察到的一些错误发生在写作时.htaccess

在多个规则中重复使用 ,使用会导致其他规则在大多数情况下无能为力,因为它在单次点击中匹配所有 URL。^(.*)$^(.*)$

因此,如果我们对此 url 使用规则,它也会消耗此 url 。sapmle/urlsapmle/url/string


应使用 [L] 标志来确保我们的规则已完成处理。


应该知道:

%n 和 $n 的差异

%n在零件期间匹配,在零件上匹配。%{RewriteCond}$n%{RewriteRule}

RewriteBase 的工作原理

RewriteBase 指令指定要用于的 URL 前缀 per-directory (htaccess) RewriteRule 指令,用于替换 相对路径。

当您在 在每个目录 (HTSaccess) 上下文中替换,除非任何 满足以下条件:

原始请求和替换位于 DocumentRoot(而不是通过其他方式(如别名)访问)。 包含 RewriteRule 的目录的文件系统路径, 以相对替换为后缀的 URL 路径也可作为 服务器(这种情况很少见)。在 Apache HTTP Server 2.4.16 及更高版本中, 当通过 Alias 或 mod_userdir。

0赞 Aurovrata 1/15/2020 #15

正如 @JCastell 所指出的,在线测试器在针对 .htaccess 文件测试单个重定向方面做得很好。然而,更有趣的是公开的 api,它可用于使用 json 对象批量测试 url 列表。但是,为了使其更有用,我编写了一个小型 bash 脚本文件,它利用 curl 和 jq 提交 url 列表并将 json 响应解析为 CSV 格式的输出,其中行号和规则在 htaccess 文件中匹配以及重定向的 url,这使得比较电子表格中的 url 列表并快速确定哪些规则不起作用非常方便。

-2赞 Aransiola Oluwaseun 2/7/2020 #16

如果您正在使用 url,您可能需要检查是否“启用 Mod 重写”

3赞 FrankPl 3/10/2021 #17

如果您不是在标准共享托管环境中工作,而是在您具有管理访问权限的环境(可能是您的本地测试环境)中工作,请确保使用 和 已启用。它们在默认的 Apache 安装中被禁用。在这种情况下,即使正则表达式完全有效,文件中配置的任何操作也不起作用。.htaccessmod_rewrite.htaccess

要启用以下功能,请执行以下操作:.htaccess

查找文件,在 Debian/Ubuntu 上,这在 中,在文件中的部分apache2.conf/etc/apache2

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

并将该行更改为 。AllowOverride NoneAllowOverride All

要启用模块:mod_rewrite

在 Debian/Ubuntu 上,执行

sudo a2enmod rewrite

顺便说一句,要禁用模块,您可以使用 .a2dismodea2enmode

完成上述配置更改后,重启 Apache 以使其生效:

sudo systemctl restart apache2
2赞 Syed Waqas Bukhary 10/10/2021 #18

调试它的最佳方法!

添加到 apache 以记录 的所有通知。如果您在共享主机上并且无权访问,请在本地测试它并上传到实时站点。一旦启用,它会在很短的时间内生成一个非常大的日志,这意味着它无论如何都无法在实时服务器上进行测试。LogLevel notice rewrite:trace8httpd.confmod_rewritehttpd.conf

评论

0赞 David Spector 11/16/2022
好。如果我只想在重写规则之外查看表达式的值,该怎么办?
0赞 David Spector 11/24/2022 #19

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

要立即将控制权从 .htaccess 转移到 router.php,用于文件系统中找不到的任何 URL,只需在 .htaccess 中输入以下行:

FallbackResource router.php

是的,真的就是这么简单。是的,它确实有效。试一试。

注意:您可能需要在 .htacess 文件中使用 ErrorDocument 指令,以便将某些 URL 的控制权显式转移到 HTTP 状态为 404 的路由器.php文件,尤其是在您从处理状态 404 的父 htaccess 文件继承时。这样一来,总共有两行将控制权转移到路由器文件。

评论

0赞 TerryE 11/26/2022
这将涉及通过 PHP 引擎(或您使用的任何脚本引擎)传递所有 URL 请求。当然,大多数 PHP 服务器端应用程序都使用 Apache2 或 nginx + fpm-php 之类的东西,其中可能 70% 的请求是裸 css、js、html 等。如果您使用繁重的客户端 React(等)框架,这可能会更多。您当然可以减轻对 URL 重写的需求,但很难完全避免它。
0赞 David Spector 11/27/2022
从htaccess文件到PHP文件的控制权转移只发生在文件系统中找不到的文件,所以这就是你说的70%。它们跳过了PHP处理,因此根本不需要重写规则。
1赞 TerryE 11/28/2022
在某些用例中,仍然需要访问文件。例如,我主要运行特定于服务的 VM 或容器,但我仍然有一个用于个人 Web 服务和电子邮件域的共享服务帐户。它每年$s,所以不值得改变,但是使用托管服务,即使是静态内容,您也需要进行主机>子目录重写。如果您已经嵌入了操作 dom 的 JS,那么您可能希望通过重写添加的 URL 参数传递上下文。...不要将你的思维局限于纯PHP应用程序。