I'm trying to set an environment variable in my .htaccess based on the 1st subdirectory of a URL. As long as the URL contains dira as the 1st subdirectory, it should set my variable (myvar) to a value of 123. For example, these URLs should work:
test.com/dira
test.com/dira/
test.com/dira/b
test.com/dira/b/
test.com/dira/b/random.html
test.com/dira/b/2
test.com/dira/b/2/
test.com/dira/b/2/and-so-in-into-infinity
Any other URL should be ignored, like these:
test.com
test.com/
test.com/dirb
test.com/dirc/123/456/789/blah
test.com/123/dira/
test.com/dirz/
I've tried all these rules in my .htaccess without success:
RewriteRule ^dira(.*)$ [E=myvar:123]
RewriteRule ^dira/(.*)$ [E=myvar:123]
RewriteRule ^dira/? [E=myvar:123]
RewriteRule ^dira/?$ [E=myvar:123]
In every case, myvar isn't set. So my question is, what's the syntax to wildcard everything after the first sub-directory? Thanks.
CodePudding user response:
RewriteRule ^dira(.*)$ [E=myvar:123] RewriteRule ^dira/(.*)$ [E=myvar:123] RewriteRule ^dira/? [E=myvar:123] RewriteRule ^dira/?$ [E=myvar:123]
You are missing the substitution string (2nd argument) so none of these directives are actually setting an environment variable. [E=myvar:123]
is seen as the substitution string (2nd argument), so would result in a rather malformed internal rewrite.
It should read something like this:
RewriteRule ^dira($|/) - [E=myvar:123]
Note the single hyphen (-
) as the substitution string (2nd argument) indicating "no substitution".
The regex ^dira($|/)
matches any URL-path that contains dira
as the first complete path segment. eg. It matches dira
, dira/
and dira/anything
, but not dirasomething
.
However, there are additional "problems" resulting from other directives in your .htaccess
file...
RewriteRule ^([^/\.] )/?$ index.php?acid={ENV:myvar} [L]
(Aside: That should be %{ENV:myvar}
- you are missing the %
prefix.)
If that is the only other rule you have in your .htaccess
file then the myvar
env var should now be successfully set when requesting /dira/something
, but not /dira
or /dira/
. (Because both /dira
and /dira/
are internally rewritten by the above rule.)
The reason being, when matched, the above RewriteRule
triggers a second pass of the rewrite engine (when used in .htaccess
). This second pass causes any environment variables that are already set to be renamed with a REDIRECT_
prefix. ie. myvar
becomes REDIRECT_myvar
. myvar
is not (re)set on the second pass because index.php
does not match your rule.
You can either:
Modify the above
RewriteRule
directive (that internally rewrites the request) to prevent a second pass of the rewrite engine. This can be done by changing theL
flag toEND
(requires Apache 2.4). For example:RewriteRule ^([^/.] )/?$ index.php?acid=%{ENV:myvar} [END]
Note that I corrected the env var reference by including the
%
prefix. And there is no need to backslash-escape literal dots when used inside a regex character class.However, you will need to be mindful of future rules you add in order to prevent loops by the rewrite engine. And sometimes the looping nature of the rewrite engine can be desirable.
OR
- Check for both
myvar
andREDIRECT_myvar
in your PHP code (ie.$_SERVER['REDIRECT_myvar']
). Since not all requests that startdira
are rewritten by the above rule, you'll have eithermyvar
orREDIRECT_myvar
set at different times. Specifically,/dira
and/dira/
will result inREDIRECT_myvar
being set and/dira/something
will have the expectedmyvar
set (since it's not rewritten).