Can htaccess read a server environment variable set in Apache?

25,797

Solution 1

Yes it is.

You will probably want to use mod_setenvif functionality, so that module will need to be turned on.

Then you simply do something like:

SetEnvIf Request_URI "\.gif$" image_type=gif

Which would set the environmental variable image_type with a value of gif if the requested file name ends with .gif.

You could then access this (like in RewriteCond) like this:

RewriteCond %{ENV:image_type} gif
RewriteRule ^(.*) $.gif

You can read the full documentation here: http://httpd.apache.org/docs/2.2/env.html

Solution 2

As I had a lot of problems setting up a similar thing to recognise my home localhost as distinct to my work set up, here's what I ended up doing.

First and foremost, The <IF ..> directive does not recognise SetEnv. From http://httpd.apache.org/docs/current/env.html : "The SetEnv directive runs late during request processing meaning that directives such as SetEnvIf and RewriteCond will not see the variables set with it."

So, try to use SetEnvIf if you can. I was lazy and just put this in my httpd.conf file. It checks that it's running on localhost - which is obviously is - then sets the variable:

SetEnvIf Server_Addr ^127\.0\.0\.1$ home_variable

Then, elsewhere, in my htaccess file I had this:

# IfVersion needs mod_version - you could do an ifmodule before all this i guess
# we use ifversion because If was introduced in apache 2.4
<IfVersion >= 2.4>
  # check if the home variable exists/isn't: empty, "0", "off", "false", or "no"
  <If "-T reqenv('home_variable')">
    ... do home-y stuff
  </If>

  <Else>
    ... do work-y stuff
  </Else>
</IfVersion>

# fallback
<IfVersion < 2.4>
  .. fallback?
</IfVersion>

Alternatively, you could just have one variable for each environment and give it a specific value:

SetEnvIf Server_Addr ^127\.0\.0\.1$ check_location=home

Then the rest would be the same, except that first<If ..> statement:

<If "%{ENV:check_location} == 'home'">....</If>

I've tested both of those between a home environment with 2.4 and a work environment with 2.2, both of which had mod_version enabled (hence not bothering with the ifmod).

(I also haven't tested for more than two environments but Apache 2.4 does give an <ElseIf> so that's also an option).

Doop di do.

(More about the -T operator et al: http://httpd.apache.org/docs/current/expr.html)

Solution 3

Apache 2.4 introduced <If>, <Else>,<ElseIf> blocks in conjunction with a new expression syntax for more powerful programmatic control in .htaccess files, etc.

This is untested but ostensibly works:

<If "%{MY_VAR} == 'my result'">
    …
</If>

Source: https://blogs.apache.org/httpd/entry/new_in_httpd_2_4

Solution 4

I gave description and .htaccess and PHP examples here: Set an environment variable in .htaccess and retrieve it in PHP

For just some examples in .htaccess, taken from my modifying the Perishable Press 5G Blacklist/Firewall http://perishablepress.com/5g-blacklist-2013/ to use environment variable reporting:

SetEnv myServerName %{SERVER_NAME}

RewriteCond %{QUERY_STRING} (base64_encode|localhost|mosconfig|open_basedir) [NC,OR]
RewriteCond %{QUERY_STRING} (boot\.ini|echo.*kae|etc/passwd) [NC,OR]
RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC]
RewriteRule .* - [E=badQueryString:%0--%1--%2,F,L]

SetEnvIfNoCase User-Agent ^$ noUserAgent
SetEnvIfNoCase User-Agent (binlar|casper|cmsworldmap|comodo|diavol|dotbot|feedfinder|flicky|ia_archiver|jakarta|kmccrew|nutch|planetwork|purebot|pycurl|skygrid|sucker|turnit|vikspider|zmeu) badUserAgent=$1

<limit GET POST PUT>
  Order Allow,Deny
  Allow from all
  Deny from env=badUserAgent
</limit>

Notice the use of paramters. %0 gives the full string, %1 gives the match from the 1st parenthesized statement, %2 the 2nd. The hyphens are literal display characters, to visually separate (don't think is any way to put spaces in there).

Share:
25,797
Tim Jahn
Author by

Tim Jahn

Updated on August 03, 2020

Comments

  • Tim Jahn
    Tim Jahn almost 4 years

    When you set a server environment variable in your Apache settings, it's possible to read that variable from PHP using built in functions.

    But can you read the variable from an htaccess file?

    What I'm trying to accomplish in my htaccess is something along the lines of:

    <If var=="stuff">
    do things here
    </if>
    
    <if var=="different stuff">
    do different things here
    </if>
    
  • Tim Jahn
    Tim Jahn over 11 years
    Does the %{ENV:variable} part just check to see if "variable" exists? Is there a way to check what the value of variable is?
  • Mike Brant
    Mike Brant over 11 years
    @TimJahn NO that actually gives the value of the variable. I have edited may answer to hopefully give better usage example. Though in my case the example is pretty useless.
  • Tim Jahn
    Tim Jahn over 11 years
    Hm, doesn't seem to be working for me. Here's my code for context: RewriteEngine on RewriteCond %{ENV:ENVIRONMENT} production RewriteCond %{REQUEST_URI} !/index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php/$1 [L]
  • Mike Brant
    Mike Brant over 11 years
    @TimJahn Where are you actually setting your environmental variable?
  • Tim Jahn
    Tim Jahn over 11 years
    I'm setting the environment variable in httpd.conf
  • Mike Brant
    Mike Brant over 11 years
    Ahh... The problem with that is that regular environmental variable are set very late in the request process and would not be available to .htaccess. You would need to set value using SetEnvIf in the .htaccess. See the "caveats" section in this link to the documentataion. httpd.apache.org/docs/2.2/env.html
  • Tim Jahn
    Tim Jahn over 11 years
    Ah, crap. Thanks for all your help anyway!
  • Mike Brant
    Mike Brant over 11 years
    @TimJahn You can use the SetEnvIf and then the RewriteCond referencing within .htaccess.
  • David
    David over 7 years
    It should be mentioned that <If> is available as of Apache 2.4.