When Setting Environment Variables in Apache Rewriterule Directives, What Causes the Variable Name to Be Prefixed with "Redirect_"

Apache mod_rewrite [E] Redirect prefix with RewriteCond

I cannot use SetEnvIf since I use mod_rewrite so I must use RewriteRule.

You could use mod_setenvif with <If>.

<If "%{REQUEST_URI} =~ /regextomatchurl/">
# or use <If "%{REQUEST_URI} == 'urlstring'">
SetEnv nokeepalive 1
</If>

You can remove that rewrite rule.

OR:

You can just add this, it might work, not tested:

SetEnv nokeepalive ${REDIRECT_nokeepalive}

Edit:

Remember to add PassEnv REDIRECT_nokeepalive before SetEnv because SetEnv cannot read env variables from mod_rewrite.

Just to point out:

You have two spaces here, it could cause future problems in other RewriteRule(s):

RewriteRule  ^ - [E=nokeepalive]
^^

Htaccess - Skip redirect if env var is not set

I have found the answer to my question. The problem has its roots at the following question:

When setting environment variables in Apache RewriteRule directives, what causes the variable name to be prefixed with "REDIRECT_"?

When now setting the following before all the other rules everything does work as expected:

RewriteCond %{ENV:REDIRECT_INTERNALAREA} (.+)
RewriteRule .* - [E=INTERNALAREA:%1]

Here is how it works. It checks on every run if the prefixed env var is already set and re adds the environment variable without the REDIRECT_ prefix.

Accessing environment variables set using mod_rewrite in PHP

See this post also discusses the same feature. The rewrite engine loops on evaluating .htaccess files at the start of each cycle the engine copies any environment variables into a copy REDIRECT_*. Hence if the parsing of the .htaccess files requires 3 loops then you will also get REDIRECT_REDIRECT_* files, and so on.

Apache 2.3 includes a new [E] flag but you can used this feature to implement the same in earlier versions:

RewriteCond %{ENV:REDIRECT_END} =1
RewriteRule ^ - [L]

# other rules

...

RewriteRule somepattern somesubst [L,E=END:1]

AFAIK, these variables will available the SERVER context, but whether they are available in the ENVIRONMENT depends on how PHP is implemented e.g. Apache+mod_php, Apache+mod_suphp, Apache+mod_fcgi, IIS, ...

How do I install a React app based on react-router's browserHistory into a WordPress page on Apache?

I tried lots of things to make this work without touching WordPress, but finally I gave up and entered a well-commented patch into my WordPress /index.php.

.htaccess:

# BEGIN myapp 
#
# Set the REQUEST_URI to just /myapp for any deeper URI for the myapp React router.
#
# Unfortunately, this winds up setting REDIRECT_REQUEST_URI rather than
# REQUEST_URI. See /index.php for a custom patch that works around this.
#
# Issue documented here: http://stackoverflow.com/a/10128290/1426950
SetEnvIf Request_URI "myapp/.*" REQUEST_URI=/myapp/
# END myapp

/index.php:

/**
*
* CUSTOM PATCH
*
* Work around an Apache issue documented here: http://stackoverflow.com/a/10128290/1426950
* We need it for the React app at /myapp/.
*
* We need the WordPress page at /myapp/ to be served for any URL beginning
* with /myapp/, so that we can control that namespace with React. To
* accomplish this, we set REQUEST_URI in the .htaccess, but a subsequent rewrite
* pushes that setting over to REDIRECT_REQUEST_URI and resets REQUEST_URI.
*
* This PHP code fools WordPress into thinking Apache did what we wanted.
*
*/
if (
$_SERVER['REDIRECT_REQUEST_URI'] !== null
) {
$_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_REQUEST_URI'];
}

Now everything works perfectly and WordPress serves the page at /myapp/ for all URLs of the React app (/myapp/foo, myapp/bar/123, etc.).

Set environment variable in .htaccess when the URL starts with directory

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 the L flag to END (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 and REDIRECT_myvar in your PHP code (ie. $_SERVER['REDIRECT_myvar']). Since not all requests that start dira are rewritten by the above rule, you'll have either myvar or REDIRECT_myvar set at different times. Specifically, /dira and /dira/ will result in REDIRECT_myvar being set and /dira/something will have the expected myvar set (since it's not rewritten).

Rewrite every request to one file with url as parameter

Your are getting into this problem because your rules are executing twice. You can stop it by avoiding all resources (js, image, css etc) to rewrite and also not letting it run second time.

Have your rules like this:

RewriteEngine On
RewriteBase /~ps0ke/

# avoid any rules for resources and 2nd time:
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_URI} \.(?:jpe?g|gif|bmp|png|tiff|css|js)$ [NC,OR]
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# Serve index.html via cms.php when base dir or index.html is requested. Also
# set the language.
RewriteRule ^((en)/)?(index.html)?$ cms.php?lang=$2&path=index.html [NC,L,QSA]

# Serve everything else via cms.php. Also set the language.
# Serving from the page subdirectory is due to a problem with all-wildcard
# RewriteRule. This might be fixed.
RewriteRule ^((en)/)?(.*)$ cmas.php?lang=$2path=$3 [NC,L,QSA]

htaccess RewriteRule Redirect with R,L,E flags (environment variable)

how to set apache environment variable with [R,L] redirection and get it in php file?

You can't set an environment variable, redirect the request and have it still be there when the second request is made. When you use R, it redirects the browser, meaning an entirely new and separate request is made for the new location, which in this case is /somelink.php.

You'll need to handle this differently, maybe with a GET parameter?

RewriteRule ^somelink/$ /somelink.php?HOWTO [L,R,QSA]


Related Topics



Leave a reply



Submit