用于调试.htaccess重写规则的提示。

时间:2022-03-13 06:10:28

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.

许多海报在调试他们的.htaccess文件中的RewriteRule和RewriteCond语句时遇到了问题。它们中的大多数都使用共享主机服务,因此无法访问根服务器配置。他们无法避免使用.htaccess文件进行重写,而且无法启用RewriteLogLevel。也有许多。htaccessc特定的陷阱和约束没有被很好地覆盖。设置一个本地测试LAMP堆栈包含了太多的学习曲线。

So my Q here is how would we recommend that they debug their rules themselves. I provide a few suggestions below. Other suggestions would be appreciated.

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

  1. Understand that the mod_rewrite engine cycles through .htaccess files. The engine runs this loop:

    理解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
    

    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.

    因此,您的规则将被反复执行,如果您更改了URI路径,那么它可能最终会执行其他的.htaccessfile(如果它们存在的话)。因此,请确保您终止了这个循环,如果需要的话,可以添加额外的RewriteCond来停止规则的触发。还可以删除任何低级的.htaccess重写规则集,除非明确意图使用多级规则集。

  2. 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.

    要确保每个Regexp的语法都是正确的,通过测试一组测试模式来确保这是一个有效的语法,并按照您想要的完全范围的测试uri来做。参见下面的答案了解更多细节。

  3. 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.

    在测试目录中增量地构建您的规则。您可以使用“在路径特性上执行最深入的.htaccess文件”来设置一个单独的测试目录(树),并在这里调试规则集,而不会破坏您的主要规则并停止您的站点工作。您必须一次添加一个,因为这是将失败本地化为单个规则的唯一方法。

  4. 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.

    使用一个虚拟脚本存根转储服务器和环境变量。(参见清单2)如果你的应用程序使用了博客/索引。然后你可以将它复制到测试/博客/索引中。使用php在测试子目录中测试您的博客规则。您还可以使用环境变量来确保重写引擎在解释替换字符串时是正确的。

    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..

    在phpinfo转储中查找这些REDIRECT_*变量。顺便说一下,我在我的网站上发现,我必须使用%{ENV:DOCUMENT_ROOT_REAL}。在redirector的情况下,循环REDIRECT_REDIRECT_*变量列出了以前的通过。等。

  5. 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.

    确保你没有被浏览器缓存错误的301重定向。请参阅下面的回答。我感谢Ulrich Palha。

  6. 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.

    重写引擎似乎在一个. htaccess上下文敏感的级联规则,(这就是RewriteRule导致替换这瀑布虽然进一步规则),当我发现缺陷与内部子请求,(1),和不正确的PATH_INFO处理通常可以防止利用(NS),[L]和[葡文]旗帜。

Any more comment or suggestions?

还有什么意见或建议吗?

Listing 1 -- phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);

14 个解决方案

#1


117  

Here are a few additional tips on testing rules that may ease the debugging for users on shared hosting

下面是一些测试规则的附加提示,它们可以简化共享主机上用户的调试。

1. Use a Fake-user agent

When testing a new rule, add a condition to only execute it with a fake user-agent that you will use for your requests. This way it will not affect anyone else on your site.

当测试一个新规则时,添加一个条件,只使用您将用于请求的冒牌用户代理来执行它。这样它就不会影响你网站上的任何人。

e.g

#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] 

If you are using Firefox, you can use the User Agent Switcher to create the fake user agent string and test.

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

2. Do not use 301 until you are done testing

I have seen so many posts where people are still testing their rules and they are using 301's. DON'T.

我看到过很多帖子,人们仍然在测试他们的规则,他们使用的是301。不喜欢。

If you are not using suggestion 1 on your site, not only you, but anyone visiting your site at the time will be affected by the 301.

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

Remember that they are permanent, and aggressively cached by your browser. Use a 302 instead till you are sure, then change it to a 301.

记住它们是永久的,并被浏览器积极地缓存。使用302,直到你确定,然后把它改成301。

3. Remember that 301's are aggressively cached in your browser

If your rule does not work and it looks right to you, and you were not using suggestions 1 and 2, then re-test after clearing your browser cache or while in private browsing.

如果您的规则不起作用,而且它看起来很适合您,并且您没有使用建议1和2,那么在清除您的浏览器缓存或在私人浏览时重新测试。

4. Use a HTTP Capture tool

Use a HTTP capture tool like Fiddler to see the actual HTTP traffic between your browser and the server.

使用像Fiddler这样的HTTP捕获工具来查看浏览器和服务器之间的实际HTTP流量。

While others might say that your site does not look right, you could instead see and report that all of the images, css and js are returning 404 errors, quickly narrowing down the problem.

虽然其他人可能会说你的网站看起来不太好,但是你可以看到并报告所有的图片、css和js正在返回404错误,迅速缩小问题。

While others will report that you started at URL A and ended at URL C, you will be able to see that they started at URL A, were 302 redirected to URL B and 301 redirected to URL C. Even if URL C was the ultimate goal, you will know that this is bad for SEO and needs to be fixed.

在URL,而有些则报告,你开始和结束在URL C,你就能看到,他们开始在URL,302 B和C . 301重定向URL重定向到URL即使URL C是终极目标,你就会知道这是不利于搜索引擎优化,需要固定的。

You will be able to see cache headers that were set on the server side, replay requests, modify request headers to test ....

你将能够看到缓存头设置在服务器端,重播请求,修改请求头测试....


#2


60  

Online .htaccess rewrite testing

I found this Googling for RegEx help, it saved me a lot of time from having to upload new .htaccess files every time I make a small modification.

我在google上找到了RegEx的帮助,这节省了我很多时间,因为每次我做一个小小的修改,就必须上传新的.htaccess文件。

from the site:

从这个网站:

htaccess tester

htaccess测试仪

To test your htaccess rewrite rules, simply fill in the url that you're applying the rules to, place the contents of your htaccess on the larger input area and press "Check Now" button.

要测试htaccess重写规则,只需填入应用规则的url,将htaccess的内容放置在较大的输入区域上,然后按下“Check Now”按钮。

#3


11  

Don't forget that in .htaccess files it is a relative URL that is matched.

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

In a .htaccess file the following RewriteRule will never match:

在.htaccess文件中,下面的RewriteRule将永远无法匹配:

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

#4


8  

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.

通过对一组测试模式进行测试,以确保这是一个有效的语法,并执行您想要的完全范围的测试uri。

See regexpCheck.php below for a simple script that you can add to a private/test directory in your site to help you do this. I've kept this brief rather than pretty. Just past this into a file regexpCheck.php in a test directory to use it on your website. This will help you build up any regexp and test it against a list of test cases as you do so. I am using the PHP PCRE engine here, but having had a look at the Apache source, this is basically identical to the one used in Apache. There are many HowTos and tutorials which provide templates and can help you build your regexp skills.

看到regexpCheck。下面是一个简单的脚本,您可以在您的站点中添加一个私有/测试目录来帮助您这样做。我保持了这个简短而不是漂亮。把它放到文件regexpCheck中。php在一个测试目录中使用它在您的网站上。这将帮助您构建任何regexp,并在测试用例列表中测试它。我在这里使用的是PHP PCRE引擎,但是查看了Apache源代码,这与Apache中使用的基本相同。有许多HowTos和教程提供模板,可以帮助您构建regexp技能。

Listing 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>

#5


6  

Set environment variables and use headers to receive them:

You can create new environment variables with RewriteRule lines, as mentioned by OP:

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

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

But if you can't get a server-side script to work, how can you then read this environment variable? One solution is to set a header:

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

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

The value accepts format specifiers, including the %{NAME}e specifier for environment variables (don't forget the lowercase e). Sometimes, you'll need to add the REDIRECT_ prefix, but I haven't worked out when the prefix gets added and when it doesn't.

值接受格式说明符,包括环境变量(不要忘记小写的e)的%{NAME}。有时,您需要添加REDIRECT_前缀,但当添加前缀时,我还没有计算出它。

#6


5  

One from a couple of hours that I wasted:

我浪费了几个小时

If you've applied all these tips and are only going on 500 errors because you don't have access to the server error log, maybe the problem isn't in the .htaccess but in the files it redirects to.

如果您已经应用了所有这些技巧,并且只会出现500个错误,因为您无法访问服务器错误日志,那么可能问题不在.htaccess中,而是在它重定向到的文件中。

After I had fixed my .htaccess-problem I spent two more hours trying to fix it some more, even though I simply had forgotten about some permissions.

在我解决了这个问题之后,我花了两个多小时来修复它,尽管我只是忘记了一些权限。

#7


4  

Make sure you use the percent sign in front of variables, not the dollar sign.

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

It's %{HTTP_HOST}, not ${HTTP_HOST}. There will be nothing in the error_log, there will be no Internal Server Errors, your regexp is still correct, the rule will just not match. This is really hideous if you work with django / genshi templates a lot and have ${} for variable substitution in muscle memory.

% { HTTP_HOST },不是$ { HTTP_HOST }。在error_log中将没有任何内容,没有内部服务器错误,您的regexp仍然正确,规则将不匹配。如果您使用django / genshi模板,并且在肌肉内存中使用变量替换,那么这是非常可怕的。

#8


4  

If you're creating redirections, test with curl to avoid browser caching issues. Use -I to fetch http headers only. Use -L to follow all redirections.

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

#9


3  

I found this question while trying to debug my mod_rewrite issues, and it definitely has some helpful advice. But in the end the most important thing is to make sure you have your regex syntax correct. Due to problems with my own RE syntax, installing the regexpCheck.php script was not a viable option.

在调试mod_rewrite问题时,我发现了这个问题,而且它确实提供了一些有用的建议。但是最后最重要的是确保你的正则表达式语法正确。由于我自己的语法问题,安装了regexpCheck。php脚本不是一个可行的选项。

But since Apache uses Perl-Compatible Regular Expressions (PCRE)s, any tool which helps writing PCREs should help. I've used RegexPlanet's tool with Java and Javascript REs in the past, and was happy to find that they support Perl as well.

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

Just type in your regular expression and one or more example URLs, and it will tell you if the regex matches (a "1" in the "~=" column) and if applicable, any matching groups (the numbers in the "split" column will correspond to the numbers Apache expects, e.g. $1, $2 etc.) for each URL. They claim PCRE support is "in beta", but it was just what I needed to solve my syntax problems.

只要输入你的正则表达式和一个或多个URL示例,它会告诉你如果正则表达式匹配(“1”“~ =”专栏)如果适用,任何匹配的组织(“分裂”列中的数字对应于数字Apache预计,例如$ 1,$ 2等)为每个URL。他们声称PCRE支持是“beta版”,但这正是我需要解决的语法问题。

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

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

I'd have simply added a comment to an existing answer but my reputation isn't yet at that level. Hope this helps someone.

我只是给现有的答案添加了一个注释,但我的名声还没有达到那个水平。希望这可以帮助别人。

#10


3  

Regarding 4., you still need to ensure that your "dummy script stub" is actually the target URL after all the rewriting is done, or you won't see anything!

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

A similar/related trick (see this question) is to insert a temporary rule such as:

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

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

Where show.php is some very simple script that just displays its $_GET parameters (you can display environment variables too, if you want).

显示的地方。php是一个非常简单的脚本,它只显示$_GET参数(如果需要,也可以显示环境变量)。

This will stop the rewriting at the point you insert it into the ruleset, rather like a breakpoint in a debugger.

这将在您将其插入到规则集(而不是调试器中的断点)时停止重写。

If you're using Apache <2.3.9, you'll need to use [L] rather than [END], and you may then need to add:

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

RewriteRule ^show.php$ - [L]

At the very top of your ruleset, if the URL /show.php is itself being rewritten.

在您的规则集的顶部,如果URL /显示。php本身也在重写。

#11


2  

Some mistakes I observed happens when writing .htaccess

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

Using of ^(.*)$ repetitively in multiple rules, using ^(.*)$ causes other rules to be impotent in most cases, because it matches all of the url in single hit.

使用^(. *)美元在多个规则,重复使用^(. *)美元会导致阳痿在大多数情况下,其他规则,因为它匹配的所有url单。

So, if we are using rule for this url sapmle/url it will also consume this url sapmle/url/string.

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


[L] flag should be used to ensure our rule has done processing.

[L] flag应该用来确保我们的规则已经完成了处理。


Should know about:

应该知道:

Difference in %n and $n

%n is matched during %{RewriteCond} part and $n is matches on %{RewriteRule} part.

%n在%{RewriteCond}部分匹配,$n在%{RewriteRule}部分匹配。

Working of RewriteBase

The RewriteBase directive specifies the URL prefix to be used for per-directory (htaccess) RewriteRule directives that substitute a relative path.

RewriteBase指令指定每个目录(htaccess) RewriteRule指令的URL前缀,以替代相对路径。

This directive is required when you use a relative path in a substitution in per-directory (htaccess) context unless any of the following conditions are true:

当您在每个目录(htaccess)上下文中的替换中使用相对路径时,该指令是必需的,除非以下条件为真:

The original request, and the substitution, are underneath the DocumentRoot (as opposed to reachable by other means, such as Alias). The filesystem path to the directory containing the RewriteRule, suffixed by the relative substitution is also valid as a URL path on the server (this is rare). In Apache HTTP Server 2.4.16 and later, this directive may be omitted when the request is mapped via Alias or mod_userdir.

最初的请求和替换是在DocumentRoot下面(而不是通过其他方法,比如别名)。对于包含RewriteRule的目录的文件系统路径,相对替换的后缀也可以作为服务器上的URL路径(这是很少见的)。在Apache HTTP Server 2.4.16和后面,当请求通过别名或mod_userdir映射时,可以省略该指令。

#12


1  

If you planning on writing more than just one line of rules in .htacesss,
don't even think about trying one of those hot-fix methods to debug it.

如果您打算在.htacesss中编写不止一行的规则,那么就不要尝试使用那些热修复方法来调试它。

I have wasted days on setting multiple rules without feedback from LOGs, only to finally giving up on one.
I got Apache on my PC, copied the whole site to HDD, and had the whole rule-set sorted out using logs real fast.
Then I reviewed my old rules which been working, I saw they are not really doing what was desired. A time bomb for a little different address.

我浪费了好几天时间,在没有日志反馈的情况下设置多个规则,最终放弃了一个。我在PC上找到了Apache,将整个站点复制到HDD中,并将整个规则集以非常快的速度进行了分类。然后,我回顾了我以前的工作规则,我发现他们并没有真正地做自己想做的事情。一枚定时炸弹,有一个不同的地址。

There are so many pit falls in rewrite rules, it's not a straight logic thing at all.
You can get Apache up and running in ten minutes, it's 10MB, good license, *NIX/WIN/MAC ready, even without install.
Also, check the header lines of your server and get the same version of Apache from archive if it's old. My OP is still on 2.0, many things are not supported.

重写规则中有太多的陷阱,这根本不是一个逻辑问题。您可以在10分钟内启动Apache并运行,它是10MB,良好的许可证,*NIX/WIN/MAC准备好了,即使没有安装。此外,检查服务器的标题行,如果它是旧的,则从存档获取相同版本的Apache。我的OP仍然是2.0,很多东西都不支持。

#13


0  

(Similar to Doin idea) To show what is being matched, I use this code

(类似于Doin的想法)显示正在匹配的内容,我使用此代码。

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

Save it to r.php on the server root and then do some tests in .htaccess
For example, i want to match urls that do not start with a language prefix

将其保存到r。php在服务器根上,然后在.htaccess中做一些测试,例如,我想要匹配不以语言前缀开头的url。

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

#14


0  

I'll leave this here, maybe obvious detail, but got me banging my head for hours: be careful using %{REQUEST_URI} because what @Krist van Besien say in his answer is totally right, but not for the REQUEST_URI string, because the out put of this TestString starts with a /. So take care:

我将在这里留下这个,可能是很明显的细节,但是让我用了几个小时的头:小心使用%{REQUEST_URI},因为@Krist van Besien在他的回答中说的是完全正确的,但不是对于REQUEST_URI字符串,因为这个TestString的输出是从一个/开始的。所以照顾:

RewriteCond %{REQUEST_URI} ^/assets/$  
                            ^
                            | check this pesky fella right here if missing

#1


117  

Here are a few additional tips on testing rules that may ease the debugging for users on shared hosting

下面是一些测试规则的附加提示,它们可以简化共享主机上用户的调试。

1. Use a Fake-user agent

When testing a new rule, add a condition to only execute it with a fake user-agent that you will use for your requests. This way it will not affect anyone else on your site.

当测试一个新规则时,添加一个条件,只使用您将用于请求的冒牌用户代理来执行它。这样它就不会影响你网站上的任何人。

e.g

#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] 

If you are using Firefox, you can use the User Agent Switcher to create the fake user agent string and test.

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

2. Do not use 301 until you are done testing

I have seen so many posts where people are still testing their rules and they are using 301's. DON'T.

我看到过很多帖子,人们仍然在测试他们的规则,他们使用的是301。不喜欢。

If you are not using suggestion 1 on your site, not only you, but anyone visiting your site at the time will be affected by the 301.

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

Remember that they are permanent, and aggressively cached by your browser. Use a 302 instead till you are sure, then change it to a 301.

记住它们是永久的,并被浏览器积极地缓存。使用302,直到你确定,然后把它改成301。

3. Remember that 301's are aggressively cached in your browser

If your rule does not work and it looks right to you, and you were not using suggestions 1 and 2, then re-test after clearing your browser cache or while in private browsing.

如果您的规则不起作用,而且它看起来很适合您,并且您没有使用建议1和2,那么在清除您的浏览器缓存或在私人浏览时重新测试。

4. Use a HTTP Capture tool

Use a HTTP capture tool like Fiddler to see the actual HTTP traffic between your browser and the server.

使用像Fiddler这样的HTTP捕获工具来查看浏览器和服务器之间的实际HTTP流量。

While others might say that your site does not look right, you could instead see and report that all of the images, css and js are returning 404 errors, quickly narrowing down the problem.

虽然其他人可能会说你的网站看起来不太好,但是你可以看到并报告所有的图片、css和js正在返回404错误,迅速缩小问题。

While others will report that you started at URL A and ended at URL C, you will be able to see that they started at URL A, were 302 redirected to URL B and 301 redirected to URL C. Even if URL C was the ultimate goal, you will know that this is bad for SEO and needs to be fixed.

在URL,而有些则报告,你开始和结束在URL C,你就能看到,他们开始在URL,302 B和C . 301重定向URL重定向到URL即使URL C是终极目标,你就会知道这是不利于搜索引擎优化,需要固定的。

You will be able to see cache headers that were set on the server side, replay requests, modify request headers to test ....

你将能够看到缓存头设置在服务器端,重播请求,修改请求头测试....


#2


60  

Online .htaccess rewrite testing

I found this Googling for RegEx help, it saved me a lot of time from having to upload new .htaccess files every time I make a small modification.

我在google上找到了RegEx的帮助,这节省了我很多时间,因为每次我做一个小小的修改,就必须上传新的.htaccess文件。

from the site:

从这个网站:

htaccess tester

htaccess测试仪

To test your htaccess rewrite rules, simply fill in the url that you're applying the rules to, place the contents of your htaccess on the larger input area and press "Check Now" button.

要测试htaccess重写规则,只需填入应用规则的url,将htaccess的内容放置在较大的输入区域上,然后按下“Check Now”按钮。

#3


11  

Don't forget that in .htaccess files it is a relative URL that is matched.

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

In a .htaccess file the following RewriteRule will never match:

在.htaccess文件中,下面的RewriteRule将永远无法匹配:

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

#4


8  

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.

通过对一组测试模式进行测试,以确保这是一个有效的语法,并执行您想要的完全范围的测试uri。

See regexpCheck.php below for a simple script that you can add to a private/test directory in your site to help you do this. I've kept this brief rather than pretty. Just past this into a file regexpCheck.php in a test directory to use it on your website. This will help you build up any regexp and test it against a list of test cases as you do so. I am using the PHP PCRE engine here, but having had a look at the Apache source, this is basically identical to the one used in Apache. There are many HowTos and tutorials which provide templates and can help you build your regexp skills.

看到regexpCheck。下面是一个简单的脚本,您可以在您的站点中添加一个私有/测试目录来帮助您这样做。我保持了这个简短而不是漂亮。把它放到文件regexpCheck中。php在一个测试目录中使用它在您的网站上。这将帮助您构建任何regexp,并在测试用例列表中测试它。我在这里使用的是PHP PCRE引擎,但是查看了Apache源代码,这与Apache中使用的基本相同。有许多HowTos和教程提供模板,可以帮助您构建regexp技能。

Listing 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>

#5


6  

Set environment variables and use headers to receive them:

You can create new environment variables with RewriteRule lines, as mentioned by OP:

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

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

But if you can't get a server-side script to work, how can you then read this environment variable? One solution is to set a header:

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

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

The value accepts format specifiers, including the %{NAME}e specifier for environment variables (don't forget the lowercase e). Sometimes, you'll need to add the REDIRECT_ prefix, but I haven't worked out when the prefix gets added and when it doesn't.

值接受格式说明符,包括环境变量(不要忘记小写的e)的%{NAME}。有时,您需要添加REDIRECT_前缀,但当添加前缀时,我还没有计算出它。

#6


5  

One from a couple of hours that I wasted:

我浪费了几个小时

If you've applied all these tips and are only going on 500 errors because you don't have access to the server error log, maybe the problem isn't in the .htaccess but in the files it redirects to.

如果您已经应用了所有这些技巧,并且只会出现500个错误,因为您无法访问服务器错误日志,那么可能问题不在.htaccess中,而是在它重定向到的文件中。

After I had fixed my .htaccess-problem I spent two more hours trying to fix it some more, even though I simply had forgotten about some permissions.

在我解决了这个问题之后,我花了两个多小时来修复它,尽管我只是忘记了一些权限。

#7


4  

Make sure you use the percent sign in front of variables, not the dollar sign.

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

It's %{HTTP_HOST}, not ${HTTP_HOST}. There will be nothing in the error_log, there will be no Internal Server Errors, your regexp is still correct, the rule will just not match. This is really hideous if you work with django / genshi templates a lot and have ${} for variable substitution in muscle memory.

% { HTTP_HOST },不是$ { HTTP_HOST }。在error_log中将没有任何内容,没有内部服务器错误,您的regexp仍然正确,规则将不匹配。如果您使用django / genshi模板,并且在肌肉内存中使用变量替换,那么这是非常可怕的。

#8


4  

If you're creating redirections, test with curl to avoid browser caching issues. Use -I to fetch http headers only. Use -L to follow all redirections.

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

#9


3  

I found this question while trying to debug my mod_rewrite issues, and it definitely has some helpful advice. But in the end the most important thing is to make sure you have your regex syntax correct. Due to problems with my own RE syntax, installing the regexpCheck.php script was not a viable option.

在调试mod_rewrite问题时,我发现了这个问题,而且它确实提供了一些有用的建议。但是最后最重要的是确保你的正则表达式语法正确。由于我自己的语法问题,安装了regexpCheck。php脚本不是一个可行的选项。

But since Apache uses Perl-Compatible Regular Expressions (PCRE)s, any tool which helps writing PCREs should help. I've used RegexPlanet's tool with Java and Javascript REs in the past, and was happy to find that they support Perl as well.

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

Just type in your regular expression and one or more example URLs, and it will tell you if the regex matches (a "1" in the "~=" column) and if applicable, any matching groups (the numbers in the "split" column will correspond to the numbers Apache expects, e.g. $1, $2 etc.) for each URL. They claim PCRE support is "in beta", but it was just what I needed to solve my syntax problems.

只要输入你的正则表达式和一个或多个URL示例,它会告诉你如果正则表达式匹配(“1”“~ =”专栏)如果适用,任何匹配的组织(“分裂”列中的数字对应于数字Apache预计,例如$ 1,$ 2等)为每个URL。他们声称PCRE支持是“beta版”,但这正是我需要解决的语法问题。

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

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

I'd have simply added a comment to an existing answer but my reputation isn't yet at that level. Hope this helps someone.

我只是给现有的答案添加了一个注释,但我的名声还没有达到那个水平。希望这可以帮助别人。

#10


3  

Regarding 4., you still need to ensure that your "dummy script stub" is actually the target URL after all the rewriting is done, or you won't see anything!

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

A similar/related trick (see this question) is to insert a temporary rule such as:

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

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

Where show.php is some very simple script that just displays its $_GET parameters (you can display environment variables too, if you want).

显示的地方。php是一个非常简单的脚本,它只显示$_GET参数(如果需要,也可以显示环境变量)。

This will stop the rewriting at the point you insert it into the ruleset, rather like a breakpoint in a debugger.

这将在您将其插入到规则集(而不是调试器中的断点)时停止重写。

If you're using Apache <2.3.9, you'll need to use [L] rather than [END], and you may then need to add:

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

RewriteRule ^show.php$ - [L]

At the very top of your ruleset, if the URL /show.php is itself being rewritten.

在您的规则集的顶部,如果URL /显示。php本身也在重写。

#11


2  

Some mistakes I observed happens when writing .htaccess

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

Using of ^(.*)$ repetitively in multiple rules, using ^(.*)$ causes other rules to be impotent in most cases, because it matches all of the url in single hit.

使用^(. *)美元在多个规则,重复使用^(. *)美元会导致阳痿在大多数情况下,其他规则,因为它匹配的所有url单。

So, if we are using rule for this url sapmle/url it will also consume this url sapmle/url/string.

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


[L] flag should be used to ensure our rule has done processing.

[L] flag应该用来确保我们的规则已经完成了处理。


Should know about:

应该知道:

Difference in %n and $n

%n is matched during %{RewriteCond} part and $n is matches on %{RewriteRule} part.

%n在%{RewriteCond}部分匹配,$n在%{RewriteRule}部分匹配。

Working of RewriteBase

The RewriteBase directive specifies the URL prefix to be used for per-directory (htaccess) RewriteRule directives that substitute a relative path.

RewriteBase指令指定每个目录(htaccess) RewriteRule指令的URL前缀,以替代相对路径。

This directive is required when you use a relative path in a substitution in per-directory (htaccess) context unless any of the following conditions are true:

当您在每个目录(htaccess)上下文中的替换中使用相对路径时,该指令是必需的,除非以下条件为真:

The original request, and the substitution, are underneath the DocumentRoot (as opposed to reachable by other means, such as Alias). The filesystem path to the directory containing the RewriteRule, suffixed by the relative substitution is also valid as a URL path on the server (this is rare). In Apache HTTP Server 2.4.16 and later, this directive may be omitted when the request is mapped via Alias or mod_userdir.

最初的请求和替换是在DocumentRoot下面(而不是通过其他方法,比如别名)。对于包含RewriteRule的目录的文件系统路径,相对替换的后缀也可以作为服务器上的URL路径(这是很少见的)。在Apache HTTP Server 2.4.16和后面,当请求通过别名或mod_userdir映射时,可以省略该指令。

#12


1  

If you planning on writing more than just one line of rules in .htacesss,
don't even think about trying one of those hot-fix methods to debug it.

如果您打算在.htacesss中编写不止一行的规则,那么就不要尝试使用那些热修复方法来调试它。

I have wasted days on setting multiple rules without feedback from LOGs, only to finally giving up on one.
I got Apache on my PC, copied the whole site to HDD, and had the whole rule-set sorted out using logs real fast.
Then I reviewed my old rules which been working, I saw they are not really doing what was desired. A time bomb for a little different address.

我浪费了好几天时间,在没有日志反馈的情况下设置多个规则,最终放弃了一个。我在PC上找到了Apache,将整个站点复制到HDD中,并将整个规则集以非常快的速度进行了分类。然后,我回顾了我以前的工作规则,我发现他们并没有真正地做自己想做的事情。一枚定时炸弹,有一个不同的地址。

There are so many pit falls in rewrite rules, it's not a straight logic thing at all.
You can get Apache up and running in ten minutes, it's 10MB, good license, *NIX/WIN/MAC ready, even without install.
Also, check the header lines of your server and get the same version of Apache from archive if it's old. My OP is still on 2.0, many things are not supported.

重写规则中有太多的陷阱,这根本不是一个逻辑问题。您可以在10分钟内启动Apache并运行,它是10MB,良好的许可证,*NIX/WIN/MAC准备好了,即使没有安装。此外,检查服务器的标题行,如果它是旧的,则从存档获取相同版本的Apache。我的OP仍然是2.0,很多东西都不支持。

#13


0  

(Similar to Doin idea) To show what is being matched, I use this code

(类似于Doin的想法)显示正在匹配的内容,我使用此代码。

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

Save it to r.php on the server root and then do some tests in .htaccess
For example, i want to match urls that do not start with a language prefix

将其保存到r。php在服务器根上,然后在.htaccess中做一些测试,例如,我想要匹配不以语言前缀开头的url。

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

#14


0  

I'll leave this here, maybe obvious detail, but got me banging my head for hours: be careful using %{REQUEST_URI} because what @Krist van Besien say in his answer is totally right, but not for the REQUEST_URI string, because the out put of this TestString starts with a /. So take care:

我将在这里留下这个,可能是很明显的细节,但是让我用了几个小时的头:小心使用%{REQUEST_URI},因为@Krist van Besien在他的回答中说的是完全正确的,但不是对于REQUEST_URI字符串,因为这个TestString的输出是从一个/开始的。所以照顾:

RewriteCond %{REQUEST_URI} ^/assets/$  
                            ^
                            | check this pesky fella right here if missing