How can I debug mod_rewrite rules?

2020-02-26 10:41发布

This is a case of "ask a question and answer it myself", which I'm posting for the benefit of anyone who has the same problem.

I had some problems debugging a mod_rewrite ruleset in a .htaccess file on a shared server, where I couldn't even access the Apache error logs. I found a neat way to debug them, which is this:

  1. Write a short script that simply prints out it's querystring variables. e.g. in PHP:

    <?='<pre>',htmlentities(print_r($_GET,true)),'</pre>'?>
    

    is all you need.

  2. Let's say you name this script "show.php" and put it in /public_html. Then in your .htaccess file, identify the point in your ruleset that you think might be causing the problem, and insert this rule:

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

The effect is the same as inserting a PRINT statement in a regular program. It'll let you know that (a) You reached that point in the ruleset, and (b) what the current rewritten URL is.

It's not as flash as a real debugging tool, but it gets the job done.

If you're using Apache <2.3.9, you'll have to use [L] instead of [END]. In that case, something to look out for is that your ruleset should not attempt to rewrite "/show.php" to anything else. If that's a problem, you can fix it by adding this rule at the very top:

RewriteRule ^show.php$ - [L]

...Just remember to remove it when you're done debugging!

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-02-26 11:09

Other possibility:

use this online htaccess tester:

http://htaccess.madewithlove.be/

查看更多
做自己的国王
3楼-- · 2020-02-26 11:21

Very helpful insight. For years I've been trying to figure out how to debug mod_rewrite rules without needing to have root access and having to put the rules in httpd.conf. This does it!

You have one minor mistake in your PHP:

<?='<pre>',htmlentities(print_r($_GET),true),'</pre>'?>

In this code, print_r() outputs everything in $_GET to stdout and then returns the value true, which htmlentities() picks up as its first argument. htmlentities() also receives the literal true as its second argument, which is an optional argument that tells htmlentities() whether or not to mess with single- and/or double-quotes.

I think what you intended was:

<?='<pre>',htmlentities(print_r($_GET, true)),'</pre>'?>

This tells print_r() to format everything in $_GET. Passing true as the second argument to print_r() tells it not to output the result to stdout, but instead to put the result in a string and return that string as print_r()'s return value. htmlentities() then receives that string as its one input parameter, and does appropriate substitutions to force the browser to display the string as is rather than allowing the browser to interpret the string. E.G. -

<i>text</i>

would get translated to:

&lt;i&gt;text&lt;/i&gt;

which will cause the browser to display:

<i>text</i>

instead of displaying the word "text" in italics:

text

查看更多
登录 后发表回答