Keith Devens .com |
Tuesday, October 14, 2008 | ![]() |
| Of course, that's just my opinion. I could be wrong. – Dennis Miller | ||
|
| ← Dual booting | Structured templating → |

Adam Langley (http://www.imperialviolet.org) wrote:
Phil Ringnalda (http://philringnalda.com) wrote:
Does [L] say "stop right now, and start pushing bits down the wire" or does it say "stop processing this pass through .htaccess, and start over as a new request with the filename you have now"? After all, if instead of dispatcher.php you rewrote it to /foo/bar/dispatcher.php, you would want the request to obey .htaccess in /foo and /foo/bar, right? I haven't had enough coffee yet to come up with a test, but I think you're failing on the second pass through, when it has started a new request for dispatcher.php, which is a regular file, and is thus forbidden. Either way, making the last line RewriteRule !^dispatcher.php$ - [f] seems to work (unless a direct request for dispatcher.php ought to be forbidden as well?).
Ronaldo (http://reflectivesurface.com/weblog/) wrote:
That has to do with the way mod_rewrite works, especially when the rules are in a .htaccess file.
When a request is processed by mod_rewrite and it causes a sub-request to be initiated, the file is parsed again and all rules that apply to the new request are processed. In the case above, that's what causing all files to be marked as forbidden. You can solve the problem making the rule more that forbids requests more specific.
Also, use (.*) instead of . in the regular expression that match the entire filename. Using a single . means you're matching any file containing at least one character and will cause problems if you use the group when replacing parts of the URL.
You can debug mod_rewriting adding those two directives in httpd.conf:
RewriteLogLevel 9
RewriteLog "<path-to-log-file"
Keith (http://keithdevens.com/) wrote:
but you need to be careful with the !-f flag. Don't you need to prefix it with /path/to/docroot, or replace !-f with !-U?
REQUEST_FILENAME is "The full local filesystem path to the file or script matching the request." So, that's not the problem. (Although, after looking, the mod_rewrite guide treats it both ways in different cases. It might differ depending on the RewriteBase. In any case, I'm pretty sure it's what I want.)
RewriteEngine is on, and I know that the dispatcher line is being executed because, well, because this page works. All of my pages run through the dispatcher.
Keith (http://keithdevens.com/) wrote:
I think you're failing on the second pass through, when it has started a new request for dispatcher.php, which is a regular file, and is thus forbidden.
When a request is processed by mod_rewrite and it causes a sub-request to be initiated, the file is parsed again and all rules that apply to the new request are processed.
I didn't realize it restarts the request and makes a second pass. That must be what's happening. Any way to stop it from doing that? Maybe I have to replace dispatcher.php with the full path to the file so it's absolute instead of relative.
Using a single . means you're matching any file containing at least one character and will cause problems if you use the group when replacing parts of the URL.
I know, but I'm indescriminately replacing the whole url with dispatcher.php, and I don't need to use any captures.
You can debug mod_rewriting adding those two directives in httpd.conf:
I actually can't because I have to test live on my (shared) server. I've had problems testing mod_rewrite on Windows before (known bugs, it seemed, when I checked, though given my gap in knowledge about mod_rewrite I just discovered, it could have been my fault).
Keith (http://keithdevens.com/) wrote:
Maybe I have to replace dispatcher.php with the full path to the file so it's absolute instead of relative.
Ok, that totally didn't work. Is there any way to stop it from doing a sub-request?
Ronaldo (http://reflectivesurface.com/weblog/) wrote:
I don't think it's possible to prevent Apache from going into a sub-request since that would probably break things. But it's possible to check if you're in a sub-request in at least two ways:
1) using the %{IS_SUBREQ} variable, which is set to true of false according the type of the request.
2) using the NS flag, which prevents a rule from being processed if it's matched inside a sub-request.
Keep in mind that using any of those methods can cause unintended results :-) As someone said once: "Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo."
By the way, check those two URLs. They have lots of useful info on mod_rewrite:
http://httpd.apache.org/docs/mod/mod_rewrite.html
http://httpd.apache.org/docs/misc/rewriteguide.html
Ronaldo (http://reflectivesurface.com/weblog/) wrote:
Ops... After refreshing the page I realized you're aware of the URLs I posted. Sorry about posting them again :-)
Keith (http://keithdevens.com/) wrote:
I was able to log mod_rewrite locally. I remembered that the last time I tried using it locally when I ran into bugs I was using Apache 1, and I currently have Apache 2 installed.
Given these rules:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /dispatcher.php [L]
Here are the log results when visiting the url 'URL':
So, it starts over from the beginning and matches the whole darn thing again. I thought that was what the 'next' flag was supposed to be for.
Keith (http://keithdevens.com/) wrote:
By the way, here's a post I found about the bug I referred to above.
Norb Beaver wrote:
So did you actually find a solution to that problem?
Keith (http://keithdevens.com/) wrote:
Don't remember, this was years ago. Here's what I use now fwiw:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule . %{REQUEST_FILENAME}.php%{PATH_INFO} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /dispatcher.php [L]
Feel free to post a comment below. Please see my comment policy.
Formatting Rules (No HTML):
Generated in about 0.249s.
(Used 8 db queries)

I'm not sure why [L] isn't working, but you need to be careful with the !-f flag. Don't you need to prefix it with /path/to/docroot, or replace !-f with !-U?
You have got "RewriteEngine on" in there?
Otherwise, try:
RewriteCond /path/to/docroot/%{REQUEST_FILENAME} !-f
RewriteRule . dispatcher.php [L]
RewriteCond /path/to/docroot/%{REQUEST_FILENAME} -f
RewriteRule . - [f]
AGL