Reputation: 154494
Why can't I use mod_rewrite
rules similar to this:
RewriteEngine On RewriteCond %{ENV:did_rewrite} !=true RewriteCond %{REQUEST_URI} ^(.*)/ RewriteRule (.*) %1/foo.php?original=$1 [E=did_rewrite:true]
To prevent recursion?
When I turn up the RewriteLogLevel
, I see:
[.../initial] (3) [perdir /.../test/] strip per-dir prefix: /.../test/stuff -> stuff [.../initial] (3) [perdir /.../test/] applying pattern '(.*)' to uri 'stuff' [.../initial] (4) [perdir /.../test/] RewriteCond: input='' pattern='!=true' => matched [.../initial] (4) [perdir /.../test/] RewriteCond: input='/test/stuff' pattern='(.*)/' => matched [.../initial] (2) [perdir /.../test/] rewrite 'stuff' -> '/test/foo.php?original=stuff' [.../initial] (5) setting env variable 'did_rewrite' to 'true' [.../initial] (3) split uri=/test/foo.php?original=stuff -> uri=/test/foo.php, args=original=stuff [.../initial] (1) [perdir /.../test/] internal redirect with /test/foo.php [INTERNAL REDIRECT] [.../initial/redir#1] (3) [perdir /.../test/] strip per-dir prefix: /.../test/foo.php -> foo.php [.../initial/redir#1] (3) [perdir /.../test/] applying pattern '(.*)' to uri 'foo.php' [.../initial/redir#1] (4) [perdir /.../test/] RewriteCond: input='' pattern='!=true' => matched [.../initial/redir#1] (4) [perdir /.../test/] RewriteCond: input='/test/foo.php' pattern='(.*)/' => matched [.../initial/redir#1] (2) [perdir /.../test/] rewrite 'foo.php' -> '/test/foo.php?original=foo.php' ...
It seems like, on the "recursive" call, the environment variable somehow becomes un-set… But I can't figure out why that would happen.
To be clear: I know there are a bunch of ways to prevent this kind of recursion. I'd like to understand why this particular way doesn't work.
Upvotes: 3
Views: 830
Reputation: 4142
I think this blog entry may have your answer. In summary, when Apache performs an internal redirect, it renames all of the environment variables:
static apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)
{
const apr_array_header_t *env_arr = apr_table_elts(t);
const apr_table_entry_t *elts = (const apr_table_entry_t *) env_arr->elts;
apr_table_t *new = apr_table_make(p, env_arr->nalloc);
int i;
for (i = 0; i < env_arr->nelts; ++i) {
if (!elts[i].key)
continue;
apr_table_setn(new, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
elts[i].val);
}
return new;
}
Unfortunately, this doesn't seem to be documented anywhere.
Upvotes: 8