An interesting oddity with mod_rewrite is that it is very difficult[impossible?] to set environmental variables.

Because of the multiple passes apache makes through the entire rewrite ruleset, env variables tend to end up with the prefix 'redirect_' added to them.

At first it seemed like the issue was the difference between the Last and the END flag for rewrite_rules:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule

However, there does not seem to be any set of variables which can ensure apache will skip reprocessing htaccess rules.

The problem appears to be that the environmental variables are renamed before checking for the end flag:

After a pass through hook_fixup is complete, the new request information will be sent back to a special internal rewriter:
https://github.com/apache/httpd/blob/trunk/modules/mappers/mod_rewrite.c#L5080

This in turn starts the whole rule checking process over again in http_request and the request record is copied into a new record in internal_internal_redirect - at which time the environemental variables are renamed.
https://github.com/apache/httpd/blob/trunk/modules/http/http_request.c#L473

This then kicks back another pass through hook_fixup in mod_rewrite - at which point mod_rewrite will detect that the END flag had been set and so all htaccess rules are skiped:
https://github.com/apache/httpd/blob/trunk/modules/mappers/mod_rewrite.c#L4843

The problem is that this is too late in the process, by this point in time the env vars have been renamed.

I've tried hacking around with mod_rewrite and http_request to add another check for the END flag so as to abort processing. The most promising was to copy lines 4842 through 4847 so that they also appeared right before the internal redirect in the same function at line 5079
https://github.com/apache/httpd/blob/trunk/modules/mappers/mod_rewrite.c#L5079

Placing it at that spot would correctly stop the rewrite processing, but it would also stop some additional filename cleanup/directory prefix cleanup - so where I had rules to internally redirect missing file requests to a specific php file Apache could not find the file[but it could load the file when directly entered]

I also tried adding some checks into http_request but they didn't seem to be called at all.


The easiest solution would be to simply replace line 473 in http_request.c
new->subprocess_env=rename_original_env(r->pool,r->subprocess_env);
with

new->subprocess_env=r->subprocess_env;

As near as I can tell, the internal redirect logic is explictly only for internal redirects, so there is no need to rename environemntal variables at all.

Rather then continue fiddling with it, I am using that small change for my own server and I wanted to find out of there was some reason for this behaviour today? [I realise that this function may well have been called from many places in the past and so used to need to rename the variables- I just can't see any reason for it today]

-Gary

Reply via email to