|Rewriting flags L and N|
just when i thought i'd figured out mod_rewrite....
| 3:52 pm on Feb 24, 2010 (gmt 0)|
from the documentation here's what it sounds like L and N should do
L - if the rule matches do the rewrite and immediately serve the matching file. This would mean that if i put L on every rewrite, an infinite loop would be impossible
N - if the rule matches apply the rewrite and start again at the top with the new REQUEST_URI as the rewritten url so it can be further rewritten.
for me though it seems like L acts like N. So then what is the different between the two?
| 6:35 pm on Feb 24, 2010 (gmt 0)|
Yes, this is true for rules in a server config file context, but unfortunately, two other factors come into play.
Note that it says "serve the matching file," so this statement solely applies to internal rewrites: It's still possible to create an infinite external-redirection loop, because a redirect sends a server response to the client and ends the current HTTP transaction. This response says, "That resource has moved, so please ask for it again at this new (redirect target) URL." Therefore, when the client issues a second request (which Apache will treat as a brand-new HTTP request, having no relationship to any previous request), an infinite loop will result if the first-requested URL is redirected to itself -- either directly (A->A) or through a two-stage (A->B->A) redirect or a multiple-stage chain of redirects.
Problem number two is that in a .htaccess context, mod_rewrite is processed during the "fix-up" phase of the Apache API. As a result, any time a rule matches, the Req_Rec variable is updated with the new URL/filepath, and then mod_rewrite is executed starting at the top again, until a pass is made through all the code without any further rules being matched and applied. This is the primary cause of "mysterious" infinite loops on internal rewrites in .htaccess.
An example of this would be the case where the Webmaster typically states, "I want to rewrite all requests to my index.php file." And the response here is, "ALL requests? -- Do you want to rewrite requests for index.php to itself?" Leaving out that the Webmaster probably also needs to exclude images, css, JS files, robots.txt and several other resources from this rewrite, one can see that rewriting index.php to itself is not a good idea, so that needs to be explicitly prevented in a .htaccess context.
The reason that this restarting is done is ostensibly so that the server can be sure that no other access controls or rewrites need to be applied to this request. Or maybe it was a bug, or maybe avoiding this recursion was simply too difficult... Dunno -- I didn't write the module...
All of the above notwithstanding, every rule should end with an [L] flag for the simple reason that once an internal rewrite rule is matched the processing for the current iteration will be stopped at this rule, and the code-restarted from the top. Telling the rewrite engine to "stop here" saves the time/effort of processing all the following rules before restarting. This restarting does not seem to happen for external redirects, which is one reason I guessed at "access control" checking as a reason in the paragraph above; One can also observe that if the [L] flag is used on a redirect rule, then this does prevent any subsequent internal rewrite rules being applied.
Yeah, it's confusing, and not thoroughly-documented. But as a review of the threads posted here will show, hardly anyone reads the documentation anyway... :( / ;)
Perhaps a member who's intimately-familiar with the source code will stop in and further clarify this point, but my statements above are "empirically true" unless I explicitly qualified them.