Forum Moderators: phranque

Message Too Old, No Replies

SetEnv

         

csdude55

7:43 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Do I need to install mod_env in order to use SetEnv?

I'm able to use [E] right now with no problems, but SetEnv would just be easier to read. When I added this to the .conf, though, Apache crashed:

# /etc/apache2/conf.d/userdata/ssl/2_4/[account]/[domain]/config.conf
SetEnv SetTester foo

Key_Master

8:47 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Do I need to install mod_env in order to use SetEnv?


Yes.

phranque

10:15 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Do I need to install mod_env in order to use SetEnv?

SetEnv is a mod_env directive:
https://httpd.apache.org/docs/current/mod/mod_env.html#setenv

I'm able to use [E] right now with no problems

the [E] flag appears to set the environment variable within the mod_rewrite module, as opposed to the [P] flag for example, which let's mod_proxy handle things.
https://httpd.apache.org/docs/current/rewrite/flags.html#flag_e

btw if you are wondering which are Apache core directives [httpd.apache.org] ...

csdude55

10:35 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Man, I looked EVERYWHERE for that, @phranque!

I guess now the next question will be, is there a performance hit on every page load by installing a module that essentially just makes a file easier to read... a file that I might not even look at for years? A quick Google didn't find any results on "mod_env performance", so maybe I'll bench test it later myself.

phranque

10:56 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



i would guess the only performance hit for loading an extra module is only on server startup and it would be practically irrelevant to your application.
i would also guess that the cost of invoking the SetEnv directive is negligible.

csdude55

11:32 pm on Jan 22, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You would think! But I remember when I uninstalled mod_security and... something else that I don't remember, it had a pretty significant impact on my load time. Somewhere around 500ms, I think? I can't find the discussion on it now.

But after that little discovery, I'm a tad gun shy about installing unnecessary modules.

lucy24

3:04 am on Jan 23, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



But I remember when I uninstalled mod_security and... something else that I don't remember, it had a pretty significant impact on my load time.
mod_security may be a special case, because it performs a number of actions on every request; that’s its job. If someone has a spare domain sitting around, I guess they could test-and-compare whether the mere existence of mod_security has an effect, or if it only starts being noticeable once you’ve given it a longish list of patterns to work on.

phranque

4:24 am on Jan 23, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



But I remember when I uninstalled mod_security and... something else that I don't remember, it had a pretty significant impact on my load time.

that's like comparing apples and orangutans.

w3dk

11:44 pm on Jan 23, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



I'm able to use [E] right now with no problems, but SetEnv would just be easier to read.


Note that using SetEnv isn't necessarily a direct replacement for using mod_rewrite (E flag) (or SetEnvIf). If all you are doing is passing an env var to your backend script then SetEnv is "better" than mod_rewrite. However, if you are setting an env var to be processed by other Apache modules then SetEnv is probably processed too late to be useful.

Man, I looked EVERYWHERE for that


Generally, if you search for "Apache <directive>" in Google, the Apache docs appear in the #1 spot.

phranque

12:16 am on Jan 24, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



If all you are doing is passing an env var to your backend script then SetEnv is "better" than mod_rewrite.

upon what basis are you making this assertion?
However, if you are setting an env var to be processed by other Apache modules then SetEnv is probably processed too late to be useful.

mod_setenvif (SetEnvIf) will run before mod_rewrite which will run before mod_env (SetEnv).

w3dk

11:23 am on Jan 24, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



If all you are doing is passing an env var to your backend script then SetEnv is "better" than mod_rewrite.


upon what basis are you making this assertion?


SetEnv is simpler and more permanent than invoking mod_rewrite just to set a "simple" environment variable.

lucy24

5:43 pm on Jan 24, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



SetEnv is simpler and more permanent
Does “more permanent” mean that some environmental variables disappear if an internal request is looped back through the server, so it hits mod_rewrite more than once? Or only that, since mod_env runs after mod_rewrite, some variables might be changed or re-set?

:: side trip to apache dot org ::

This technique is offered as an example, not as a recommendation.
Dunno about the rest of you, but I find some parts of the Apache docs more helpful than others.

w3dk

6:34 pm on Jan 24, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



SetEnv is simpler and more permanent


Sorry, that's a typo! It should have read: "more performant"!

some environmental variables disappear if an internal request is looped back through the server


Although, yes, you do have a point there. However, if the env var is set unconditionally with mod_rewrite then you'll probably (depending on context, order of directives and number of rewrite "loops") just end up with multiple env vars with the same value... MYVAR and REDIRECT_MYVAR and REDIRECT_REDIRECT_MYVAR, etc.

lucy24

7:58 pm on Jan 24, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



MYVAR and REDIRECT_MYVAR and REDIRECT_REDIRECT_MYVAR
Matter of fact, I did notice that when adding environmental variables to the logheaders routine. (Set with SetEnvIf, not Rewrite.) Happily the leading element REDIRECT is in ALL CAPS, so I didn't have to take an extra step to ignore it.

I suppose there are times when it would be useful to know that something has been set more than once, as illustrated by a cascade of REDIRECT_blahblah.

csdude55

5:12 am on Feb 3, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm finally experimenting with mod_env... it's hard to make a side by side comparison, but as far as I can tell there was no discernable speed difference after installing the module, or with changing a handful of my [E] rewrites to SetEnv.

Some advantages and disadvantages that I've seen so far:

1. With [E], I had to escape whitespaces, and commas didn't work at all, so I had to do an alternative; eg,

[E=example:Lorem\ ipsum\ dolor\ sit\ amet\%2C\ consectetur]


Then in PHP I would use str_replace() to convert %2C back to a comma.

SetEnv lets me do it prettier:

SetEnv example "Lorem ipsum dolor sit amet, consectetur"


2. [E] let me chain as many together as I wanted using a comma as a delimiter; eg,

[E=foo:bar,E=lorem:ipsum]


SetEnv doesn't have a delimiter, so I have to do a separate line for each; eg,

SetEnv foo bar
SetEnv lorem ipsum


3. Order of operations, like @phranque mentioned, can throw things off. For example, this returns "bar" instead of the desired "notbar":

// assuming the page is index.php
SetEnv foo bar
SetEnvIf REQUEST_URI "index\.php" foo=notbar


So it appears that it goes through the entire .conf to run all of the SetEnvIf, then it starts over and runs the SetEnv which would overwrite anything set by SetEnvIf (then it starts over again and runs the RewriteRules). I guess I'd have to do it like this instead? Typed but not tested:

// assuming the page is index.php
SetEnvIf REQUEST_URI "index\.php" foo=notbar
SetEnvIf REQUEST_URI "!index\.php" foo=bar


I was pleased to see that SetInvIf allows me to chain them together, though :-) Eg,

SetEnvIf REQUEST_URI "index\.php" foo=bar lorem=ipsum


4. With SetEnvIfExpr I had no idea what "ap_expr" was supposed to mean, but I figured it out by example:

SetEnvIfExpr "%{QUERY_STRING} =~ /foo/" foo=bar


So I guess "ap_expr" means PCRE? Either way, I guess that's a way to get around SetEnvIf not recognizing the query string... complex and confusing, sure, but it works.


Some things I haven't figured out yet:

1. Using PHP's print_r($_SERVER), I see a variable of [HOME] that's set to /home/example. But when I do this:

SetEnv foo ${HOME}

I see that foo is set to /root. Why? I don't remember where I found the ${whatever} format, but it's the only thing I could find that worked at all. Am I strictly limited to accessing Remote_host, Remote_addr, Request_method, Request_protocol, and Request_URI?

2. What's the purpose of PassEnv? The docs explanation makes no sense.

In the end, though, if it's not faster and really not easier to read, then the only real advantage I see at all is that I can use whitespace and commas in the value without escaping or encoding them. And for me, at least, that's not enough of an advantage to have to modify every one of them.

Or is there some other advantage that I'm not seeing?

lucy24

6:02 am on Feb 3, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



So it appears that it goes through the entire .conf to run all of the SetEnvIf, then it starts over and runs the SetEnv which would overwrite anything set by SetEnvIf (then it starts over again and runs the RewriteRules).
That's your reverse alphabetical order (unless you've expressly told your server to load them in a different order):
mod_setenvif
mod_setenv
mod_rewrite
...
with everything in auth conveniently at the end (but, I guess, before alias?) so you can use all your environmental variables, from all those sources, for access control.

csdude55

5:37 am on Feb 4, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I mean, it makes SENSE, but using RewriteRule this worked the other way around:

# typed up for this, so please forgive any typos
RewriteRule ^ - [E=foo:bar]

RewriteCond %{REQUEST_URI} index\.php
RewriteRule ^ - [E=foo:notbar]


More accurately, I set a series of variables, then if the query string contains a specific param then I overwrite the variables to false (or, [E=foo:], so whatever that sets). So by using mod_rewrite for everything, the order of operations appears to be more top-down, which seems to be easier to understand.

lucy24

5:20 pm on Feb 4, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



by using mod_rewrite for everything, the order of operations appears to be more top-down, which seems to be easier to understand

Apples and oranges.
#1 each module executes separately, in reverse alphabetical order, regardless of where its directives are placed in config and/or htaccess. You could even garble together the directives for different modules; the server will pick out the one it's currently working on, and ignore the others.
#2 within each module, directives execute in sequential order (with rare exceptions such as the pre-2.4 "Allow/Deny" construction in mod_auth_thingy).

w3dk

7:18 pm on Feb 4, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



1. With [E], I had to escape whitespaces, and commas didn't work at all, so I had to do an alternative; eg,


[E=example:Lorem\ ipsum\ dolor\ sit\ amet\%2C\ consectetur]



Instead of backslash escaping spaces, you can surround the entire flags argument with double quotes:


"[E=example:Lorem ipsum dolor sit amet consectetur]"


However, commas are still a problem. Although you could employ a RewriteCond directive to help here and avoid all escaping (at the expense of some brevity). For example:


RewriteCond "Lorem ipsum dolor sit amet, consectetur" (.*)
RewriteRule ^ - [E=example:%1]



...run all of the SetEnvIf, then it starts over and runs the SetEnv which would overwrite anything set by SetEnvIf (then it starts over again and runs the RewriteRules).


That's your reverse alphabetical order (unless you've expressly told your server to load them in a different order):
mod_setenvif
mod_setenv
mod_rewrite



This isn't quite right... it's mod_env, not mod_setenv. mod_env is processed last (the "reverse alphabetical order"), after mod_rewrite (you can't access a variable in mod_rewrite that has been set with SetEnv). The "normal" order would be:

1. mod_setenvif
2. mod_rewrite
3. mod_env

So I guess "ap_expr" means PCRE?


No, it doesn't. "ap_expr" is an "Apache Expression" (new with Apache 2.4). PCRE is the flavor of regex that Apache uses. Apache Expressions don't necessarily use regex at all.


1. Using PHP's print_r($_SERVER), I see a variable of [HOME] that's set to /home/example. But when I do this:

SetEnv foo ${HOME}

I see that foo is set to /root. Why? I don't remember where I found the ${whatever} format, but it's the only thing I could find that worked at all. Am I strictly limited to accessing Remote_host, Remote_addr, Request_method, Request_protocol, and Request_URI?


I covered some of this in your other thread: [webmasterworld.com...]

${HOME} is accessing a shell environment variable OR value of an Apache "Define" directive. If $_SERVER['HOME'] is different then you would seem to be setting an environment variable of the same name (or something)? "HOME" is non-standard in both cases.

Note that Remote_Host etc. are related to SetEnvIf, not SetEnv. No you are not limited to just those variables, you can also access HTTP request headers and other environment variables.

2. What's the purpose of PassEnv? The docs explanation makes no sense.


PassEnv passes in system environment variables from the OS that are not ordinarily available to Apache/PHP and makes them available.

For example, you might have a TEMP var defined by the OS and by calling "PassEnv TEMP" this will then become available to Apache and your PHP script.

lucy24

10:25 pm on Feb 4, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This isn't quite right...
Whoops! I should have double-checked the module name before posting. (I don't use SetEnv and related directives--though I see they are permitted in htaccess--so the module name isn't internalized like mod_rewrite and similar names*.)


* Longtime readers of this forum know that I have an ineradicable mental block against the name of any module beginning in auth...