Forum Moderators: phranque

Message Too Old, No Replies

SetEnv vs SetEnvIf vs RewriteRule, why use SetEnv if it runs last?

         

csdude55

6:59 pm on Jan 26, 2023 (gmt 0)

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



We've touched on this in other threads, but I wanted to clarify without taking them off topic.

It's my understanding that mod_rewrite (eg, RewriteRule) runs in the order it's presented. mod_setenv (eg, SetEnvIf) runs before everything else, and mod_env (eg, SetEnv) runs after everything else. So if I have this:

SetEnv this that
ReWriteRule ^ - [E=foo:bar]
SetEnvIf ^ ^ lorem=ipsum

then lorem is set first, foo is set second, and this is set last. Right?

Assuming so:

1. I recognize that SetEnv is subjectively easier to read than RewriteRule, but is there any other advantage to it? I guess if you have a reason to write it higher in the script but intentionally want it to run last, but I can't think of any example of this where it couldn't just be written at the end.

2. SetEnvIf is shorter than a series of RewriteCond => RewriteRule, but it seems like using it just once means that I need to use it exclusively in order to prevent confusion. Is there a DISadvantage to using SetEnvIf ^ ^ foo=bar (which should match in all cases, making it seem identical to SetEnv or RewriteRule other than the order of operation)?

I'm sure that Apache had some reason for creating the modules to run in this order, but I honestly don't understand it. It feels highly inefficient if Apache has to scan the entire config for any SetEnvIf, then scan again for any RewriteRule, then scan a third time for any SetEnv.

phranque

12:03 am on Jan 27, 2023 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



this is the best description i've seen for how apache selects the processing order of modules and directives:
On Apache 2.x, module execution order is controlled by an internal priority scheme, and can't be changed unless you modify the Apache source and re-compile it.

To be very clear about all of the above: Each Apache module parses your .htaccess file(s) in turn, looking for directives that it understands and handles. So directives handled by any one specific module are executed in the order they appear in your .htaccess file. But you cannot control the order in which different module's directives execute by specifying their order in .htaccess -- The module execution order determines that.

https://www.webmasterworld.com/apache/3403983.htm#msg3404382

it would also be useful to read this as well:
https://httpd.apache.org/docs/2.4/sections.html#merging
be sure to read the "How the sections are merged" and "Relationship between modules and configuration sections" sections of the document.

the apache mod_env documentation states (regarding the SetEnv directive):
The internal environment variables set by this directive are set after most early request processing directives are run, such as access control and URI-to-filename mapping. If the environment variable you're setting is meant as input into this early phase of processing such as the RewriteRule directive, you should instead set the environment variable with SetEnvIf.

https://httpd.apache.org/docs/2.4/mod/mod_env.html#setenv

the apache mod_setenvif documentation states:
The SetEnvIf directive defines environment variables based on attributes of the request.

(my emphasis)
https://httpd.apache.org/docs/2.4/mod/mod_setenvif.html#setenvif

taking all this into account, i would suggest using each module's directives as intended in the documentation.
i would fall back to using mod_rewrite for setting environment variables only when you can't do it using mod_env or mod_setenvif directives.

lucy24

2:20 am on Jan 27, 2023 (gmt 0)

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



mod_rewrite (eg, RewriteRule) runs in the order it's presented. mod_setenv (eg, SetEnvIf) runs before everything else, and mod_env (eg, SetEnv) runs after everything else
This is a little misleading, but I can’t tell if it is an artifact of posting, or a bona fide misunderstanding.

#1 With rare exceptions, modules are executed in reverse alphabetical order. All mod_setenvif directives run before all mod_rewrite directives which run before all mod_env directives and so on. While any given module is doing its thing, directives for all other modules are simply ignored. (Think of being in a room filled with conversations, but only one of them happens to be in a language you understand. All the others are just white noise.)

#2 Within each module, directives run in sequential order, top to bottom. (As usual, mod_rewrite has more than its share of exceptions: “RewriteEngine on” and RewriteOptions can be placed anywhere and will still be treated as if they came first--and, as we all know, RewriteCond is evaluated after the RewriteRule it belongs to.)

csdude55

4:44 am on Jan 27, 2023 (gmt 0)

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



I recently learned about a concept called "The Curse of Knowledge". Basically, it refers to a concept that once you understand something, you can't understand how someone else doesn't understand it. Here's a better explanation:

[effectiviology.com...]

I think that the Apache docs are a perfect example of this concept. I know that you're thinking the docs explain the answer perfectly well, but that's because you understand it. To me, a guy that has VERY little understanding of Apache config, the whole thing is dangerously close to gibberish! LOL

module execution order is controlled by an internal priority scheme, and can't be changed unless you modify the Apache source and re-compile it.

Might as well be in Latin :-O LOL

This is a little misleading, but I can’t tell if it is an artifact of posting, or a bona fide misunderstanding.

Probably a bona fide misunderstanding.

If I'm understanding correctly, the only reason that they run in that specific order is because of the name of the module? Meaning, had mod_env been named mod_zenv then SetEnv would always run first?

And based on that, it seems to me that the usage of SetEnvIf anywhere would mean that it's most logical to use it everywhere. Yes?

I'd asked before if there is a disadvantage to using SetEnvIf ^ ^ foo=bar or SetEnvIfExpr "%{foo} =~ /bar/" foo=bar. I'm looking at replacing about 700 RewriteRules, so I'm very concerned with a performance hit! It'll take me a week to rebuild all of it, and I'd hate to spend all that time just to find out that there's an unexpected problem from it :-/

lucy24

6:11 am on Jan 27, 2023 (gmt 0)

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



I know that you're thinking the docs explain the answer perfectly well
Nuh-uh, not me, you must be thinking of someone else ;)

Meaning, had mod_env been named mod_zenv then SetEnv would always run first?
It's probably more accurate to say that, if Apache's developers had wanted mod_env directives to run before all other mods, they would have named it mod_zenv. Similarly, if words like Access and Authentication had not happened to start with the letter A, the relevant modules might have been named something less intuitive.

I'm looking at replacing about 700 RewriteRules
Criminy, that's a lot of RewriteRules. I think this is the point where we pull out the boilerplate answer, deployed quite often in the Apache subforum: Start by laying out, in English (which is a different language from Apache) exactly what it is you want to do. From there, we proceed to working out how best to accomplish it.

csdude55

5:21 pm on Jan 27, 2023 (gmt 0)

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



I think this is the point where we pull out the boilerplate answer, deployed quite often in the Apache subforum: Start by laying out, in English (which is a different language from Apache) exactly what it is you want to do. From there, we proceed to working out how best to accomplish it.

Oops, I see where you asked this now :-) For some reason I'm not getting an email on every reply anymore, I don't know what happened to change that. But it's led to me missing replies a few times.

I have about 60 domains parked on top of a main domain. I look at the domain name and pull out a unique keyword, which I set as an ENV named "default". But! If they're at the main domain, I look at the first section of the REQUEST_URI to get that keyword if the directory doesn't exist.

For example, if they go to www.example.com or www.main.com/example then I set "default" to "example".

From there, I used to set a lot of variables in PHP along the lines of:

if ($default == 'example') {
$foo = "bar";
$this = "that";
}

(I actually did that using MySQL, that was just typed up to explain the process)

This would run on every page, but I learned that if I move them to Apache config instead of MySQL then each page loaded a LOT faster.

Which is where I am now. I extrapolate "default", then have a list of:

RewriteCond %{ENV:default} ^example$
RewriteRule ^ - [E=foo:bar,E=this:that]


Extrapolating "default" has gotten a little more complicated than I originally intended, though, and the best solution seems to have been to use SetEnvIfExpr. But in doing that I have to change all of the subsequent rules to use SetEnvIf, too.

lucy24

7:06 pm on Jan 27, 2023 (gmt 0)

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



Yeah, that kind of thing can definitely be done in SetEnvIf
SetEnvIf default ^example$ foo=bar this=that
and so on. But depending on circumstances it may be possible to set them all at once:
SetEnvIf attribute RegEx default=example foo=bar this=that
and, again, so on.

Incidentally, there are often two different reasons for using the ^ opening anchor: if the string-to-match has to come first (meaning it might also occur later but you don't want those), and/or if it always de facto does come first, in which case the server can get out of there right away if it doesn't get an instant match. The closing anchor is only needed if the string-to-match has to come at the very end.

phranque

11:51 pm on Jan 27, 2023 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



module execution order is controlled by an internal priority scheme, and can't be changed unless you modify the Apache source and re-compile it.

Might as well be in Latin :-O LOL

this is a strong signal that changing the order of module execution is not an option for you.
in fact, i understood that statement clearly and wouldn't bother trying the suggested solution.

i haven't yet found a definitive way to list the order of execution of modules in your apache configuration, but you can usually dump a list of loaded static and shared modules using one of the following commands (or using a similar alias to the httpd binary):
httpd -M
apachectl -M


i'm pretty sure my linux desktop has the vanilla ubuntu apache installation and returns this result:
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
unixd_module (static)
access_compat_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_core_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
cgi_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
filter_module (shared)
mime_module (shared)
mpm_event_module (shared)
negotiation_module (shared)
reqtimeout_module (shared)
rewrite_module (shared)
setenvif_module (shared)
status_module (shared)

i would guess the static modules run in the order listed and then the shared modules run in the reverse order listed.
i may study each module to see if that actually makes sense...

csdude55

12:38 am on Jan 28, 2023 (gmt 0)

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



module execution order is controlled by an internal priority scheme, and can't be changed unless you modify the Apache source and re-compile it.

Maybe it's the North Carolina in me? LOL But this seems like a super pretentious way of saying:

The order in which modules execute is chosen internally by Apache, and there's nothing you can really do about it. While it's "technically" possible that you could change that order by modifying the Apache source code and re-compiling it, you really should not do that. If you do it and Apache breaks, good luck and we'll be praying for you.

(OK, that last sentence was meant to be a joke, hope you chuckled)

lucy24

2:45 am on Jan 28, 2023 (gmt 0)

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



a super pretentious way of saying

Yup, that looks like a very good translation from Apache into English. Your final sentence is typically expressed in Apache docs as something involving “unintended consequences”, meaning that they can’t absolutely guarantee that the world as we know it will not come to an end.

csdude55

10:45 pm on Jan 29, 2023 (gmt 0)

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



On the topic of the order of operations, do ya'll know where <Files> and <If> fall in the list?

Best I can tell is that when there's an <If>, <Files> and RewriteRules set outside of the <If> are ignored.

If there's no <If> but there's a <Files> then RewriteRules set outside of <Files> are ignored.

<Files> and <If> both run before SetEnvIf.

Is that right?

phranque

11:53 pm on Jan 29, 2023 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



<Files> and <If> are both core directives.

mod_rewrite directives are not required to be within an <If> envelope or a <Files> envelope.

lucy24

1:17 am on Jan 30, 2023 (gmt 0)

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



When using a <Files> envelope, make sure there's a fresh "RewriteEngine on" inside the envelope, along with the one outside it. (Source: Direct personal experience.) I don't know how this works with <If>, but it can't hurt to repeat yourself.

csdude55

5:08 am on Jan 30, 2023 (gmt 0)

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



I might have said that wrong.

Here's what I've tested in my htaccess test directory, trying to determine the order of everything:

# "foo" and "second" do not exist
# I get "first" first, then "this"
SetEnvIf ^ ^ this=that

<If "-n %{QUERY_STRING}">
RewriteRule ^ - [E=first:1]
</If>

<Files "test.php">
RewriteRule ^ - [E=second:2]
</Files>

RewriteRule ^ - [E=foo:bar]


# "foo" and "second" do not exist
# I get "first" first, then "this"
RewriteRule ^ - [E=foo:bar]

<If "-n %{QUERY_STRING}">
RewriteRule ^ - [E=first:1]
</If>

SetEnvIf ^ ^ this=that


# "foo" does not exist
# I get "second", then "this"
RewriteRule ^ - [E=foo:bar]

SetEnvIf ^ ^ this=that

<Files "test.php">
RewriteRule ^ - [E=second:2]
</Files>


# "foo" does not exist
# "first" then "this"
RewriteRule ^ - [E=foo:bar]

<Files "test.php">
RewriteRule ^ - [E=first:1]
</Files>

SetEnvIf ^ ^ this=that


# "foo" then "this"
RewriteRule ^ - [E=foo:bar]
SetEnvIf ^ ^ this=that


# "foo" then "this"
SetEnvIf ^ ^ this=that
RewriteRule ^ - [E=foo:bar]


# "foo" does not exist
# "second" then "this"
SetEnvIf ^ ^ this=that

<Files "test.php">
RewriteRule ^ - [E=second:2]
</Files>

RewriteRule ^ - [E=foo:bar]

I'm confused on why the RewriteRules simply don't run at all when there's an <If> or <Files> present.

And it looks like if I have an <If> and a <Files> in the same config (not nested, just in the same script) then the <If> runs and <Files> doesn't.

csdude55

5:18 am on Jan 30, 2023 (gmt 0)

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



When using a <Files> envelope, make sure there's a fresh "RewriteEngine on" inside the envelope, along with the one outside it.

@lucy24, you mentioned that before, too. I've given up on my previous work and now I'm basically trying to undo 3 weeks worth of work, so of course I immediately forgot your advice! LOL

I've tested with and without it in the <Files> section and it didn't seem to have any impact. What were you seeing before that made you add it? Was it an actual error, or something just not working right? I ask so that I'll (try to) remember this if I have the same problem at some point.

lucy24

6:46 am on Jan 30, 2023 (gmt 0)

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



What were you seeing before that made you add it? Was it an actual error, or something just not working right?
Years ago when I had some of my RewriteRules inside a <Files> envelope, I saw that they simply didn't execute if I didn't repeat the instruction. fwiw, I dug through my HD and found an old htaccess from 2016 which used the <Files>. There are separate "RewriteEngine on" declarations, but nothing about inheritance.

I used <Files> for a slew of rules involving images, so the rules themselves could be a little cleaner. But there were added complications so in the end I went back to doing the (jpg|gif|png)$ in each pattern. This was in Apache 2.2, but I've no reason to think it would be different in 2.4...

... except that there are more inheritance options, which is a further complication. (Did we ever figure out what the default setting is for 2.4? I think Inherit is still off by default, but am not prepared to bet money on it.) I was going to say that if all you're doing is setting environmental variables, it really shouldn't matter--but actually it might still matter, because inheritance or lack thereof doesn't just apply to redirects, it applies to all actions taken by mod_rewrite.

Strong reminder: Since each module is an island, and anything inside a <FIles> executes later, it makes no difference what order the directives are in. That is,
SetEnvIf blahblah
RewriteRule blahblah
will come out with identical results to
RewriteRule blahblah
SetEnvIf blahblah

I hope this kind of thing is just for experimental purposes, because
<Files "test.php">
RewriteRule ^ - [E=second:2]
</Files>
is, again, identical to
RewriteRule test\.php - [E=second:2]
or, for that matter,
SetEnvIf Request_URI test\.php second=2

csdude55

6:51 pm on Jan 30, 2023 (gmt 0)

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



Since each module is an island, and anything inside a <FIles> executes later, it makes no difference what order the directives are in.

I was thinking more along the lines of how to set ENV variables outside of <Files> or <If>, and whether they would then be accessible within <Files> or <If>.

I hope this kind of thing is just for experimental purposes

Haha, yeah, don't worry :-) I was just putting things together in an attempt to figure out the order, but then came across the issue where RewriteRules outside of <Files> or <If> were just completely being ignored!

I assumed that core directives (eg, <Files> and <If>) would run first, process everything inside of them (rewrite > setenvif > setenv), then go back and process RewriteRules that were outside of them (meaning, those outside RewriteRules would overwrite whatever was written inside). But instead I'm just getting nothing, so now I'm confused again.

lucy24

8:14 pm on Jan 30, 2023 (gmt 0)

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



Core doesn't mean it runs first. It simply means a given functionality is available to, or independent of, all modules. In the specific case of <Files>--also <Directory> and <Location> which of course can't be tested in htaccess--things inside the envelope happen after non-enveloped things, because the envelope can't be evaluated until after various business involving filepaths and physical filenames has been evaluated. That's why, for example, RewriteRules inside <Files> can't have ^ at the beginning of a pattern: at this point, the rule is no longer basedon the present directory.

:: detour to test site ::

Yes, I remembered correctly. Given a rule inside a <Files> or <FilesMatch> then for example
RewriteRule (.*) /detour.html?$1 [R=302,L]
takes you to
https://example.com/detour.html?/full/physical/filepath/originally-requested-file.html

instead of the expected
https://example.com/detour.html?originally-requested-file.html

csdude55

9:35 pm on Jan 30, 2023 (gmt 0)

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



I see. So the order, then, would be RewriteRules, then SetEnvIf, then SetEnv, THEN Files>RewriteRules, then Files>SetEnvIf, then Files>SetEnv.

How about <If>?

RewriteRule ^ - [E=zero:1]
SetEnvIf ^ ^ this=that

<Files "test.php">
RewriteCond %{ENV:this} .+
RewriteRule ^ - [E=first:1]

SetEnvIfExpr "-n %{ENV:this}" second=2
</Files>

<If "-n %{ENV:this}">
RewriteRule ^ - [E=third:3]
</If>

This does not write "zero" at all, but it does write "this". Then I get "first" and "second", confirming that the SetEnvIf from outside of the envelope runs first.

But I don't get "third", so maybe <If> runs before SetEnvIf? If I change it to "-z %{ENV:this}" then I do get "third", so the <If> runs but it just doesn't match.

Any thoughts on why RewriteRules are ignored entirely when <If> or <Files> is in the config?

csdude55

10:03 pm on Jan 30, 2023 (gmt 0)

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



Addendum to that.

This sets "first", "second", and "this", but not "third":

SetEnvIf ^ ^ this=that

<Files "test.php">
RewriteCond %{ENV:this} .+
RewriteRule ^ - [E=first:1]

SetEnvIfExpr "-n %{ENV:this}" second=2

<If "-n %{ENV:this}">
RewriteRule ^ - [E=third:3]
</If>
</Files>


And then this modification sets "third", "second", and "this", but NOT "first":

SetEnvIf ^ ^ this=that

<Files "test.php">
RewriteCond %{ENV:this} .+
RewriteRule ^ - [E=first:1]

SetEnvIfExpr "-n %{ENV:this}" second=2

<If "-n %{HTTP_HOST}">
RewriteRule ^ - [E=third:3]
</If>
</Files>

So maybe the issue with <If> is in matching against ENV at all?

And it still looks like using <If> will force it to ignore all RewriteRules that are outside of the <If>.

lucy24

10:28 pm on Jan 30, 2023 (gmt 0)

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



I realize you've been simplifying for posting purposes, but in the real file do you have a
RewriteOptions Inherit
(or InheritBefore, or whatever works for you?)
inside each separate envelope that uses mod_rewrite?

As a simpler alternative, RewriteOptions InheritDown (or InheritDownBefore) is supposed to, er, be heritable straight down the line, but I don't know whether this is fully truthful.
If this option is enabled, all child configurations will inherit the configuration of the current configuration. It is equivalent to specifying RewriteOptions Inherit in all child configurations.
Only in 2.4.8 and later, if that matters.

When I remember, I will experiment on the test site, but right now I have to run out and buy cat food.

Edit: As always, I don't see the necessity for the <Files> with all its hideous complications, when both mod_rewrite and mod_setenvif can act according to the Request_URI.

phranque

11:30 pm on Jan 30, 2023 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I assumed that core directives (eg, <Files> and <If>) would run first, process everything inside of them (rewrite > setenvif > setenv), then go back and process RewriteRules that were outside of them (meaning, those outside RewriteRules would overwrite whatever was written inside).

i would refer you to this from my previous post in this thread:
it would also be useful to read this as well:
https://httpd.apache.org/docs/2.4/sections.html#merging
be sure to read the "How the sections are merged" and "Relationship between modules and configuration sections" sections of the document.

especially important is this section:
At runtime, the core of httpd iterates over the defined configuration sections in the order described above to determine which ones apply to the current request. When the first section matches, it is considered the current configuration for this request. If a subsequent section matches too, then each module with a directive in either of the sections is given a chance to merge its configuration between the two sections. The result is a third configuration, and the process goes on until all the configuration sections are evaluated.

After the above step, the "real" processing of the HTTP request begins: each module has a chance to run and perform whatever tasks they like. They can retrieve their own final merged configuration from the core of the httpd to determine how they should act.

in simpler terms, the actual mod_rewrite/mod_env/mod_setenvif directives aren't processed until all configuration (<If>/<Files>/etc) containers/sections are evaluated and merged into a final set of configuration directives.
i.e., configuration directives are merged first, then processed.

csdude55

7:44 pm on Jan 31, 2023 (gmt 0)

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



I realize you've been simplifying for posting purposes, but in the real file do you have a
RewriteOptions Inherit
(or InheritBefore, or whatever works for you?)
inside each separate envelope that uses mod_rewrite?

Actually, for THIS test run I set up a new account on the server and gave it an .htaccess. So the code I've been posting is verbatim from the .htaccess.

Looking at /etc/apache2/conf/httpd.conf (which is built by WHM, not manually configured), I do see this for the account:

<IfModule rewrite_module>
RewriteOptions Inherit
</IfModule>

Is that what you mean?

As always, I don't see the necessity for the <Files> with all its hideous complications, when both mod_rewrite and mod_setenvif can act according to the Request_URI.

I'm really too deep to turn back :-/ I have 10 .conf files that are a cumulative 82kb, so I'm trying to ensure that things run in the order in which I intended.

What "hideous complications" do you mean, other than the issue with rewriting paths? I'm exclusively using it to set ENV variables. I read these variables in variables.php and variables.lib to be used throughout the site, so I use <FilesMatch "variables\.(php|lib)%">. I thought this would be better than setting them for every image, JS, and CSS file unnecessarily?

in simpler terms, the actual mod_rewrite/mod_env/mod_setenvif directives aren't processed until all configuration (<If>/<Files>/etc) containers/sections are evaluated and merged into a final set of configuration directives.

I say this in a joke manner, @phranque, but I'm really serious. When I try to read the docs, my eyes cross and I have to go back and re-read the same sentence several times. And then it still doesn't make sense!

I'm not a dumb guy. I read the KJV, front to back, when I was 13. I read at least an hour a day for leisure, often very deep and complex books. The book I'm reading now is The Book of Abraham:
[amazon.com...]

I don't know what it is, but there's just something about the way that the docs are written that makes it just impossible to sink in. I'd like to blame it on my age, but it wasn't any easier when I configured Apache the first time some 20 years ago. I know that I'm not dumb, but I swear, reading the docs makes me really question that :-/

This is of particular note, though:

When <If> is used in .htaccess, the enclosed directives in a parent directory will be merged after non-enclosed directives in a subdirectory.

Since I'm testing in .htaccess and plan to move the final version to .conf, I think this means that my entire test is going to be flawed.

Blerg.

My head hurts.

lucy24

9:11 pm on Jan 31, 2023 (gmt 0)

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



<IfModule rewrite_module>
RewriteOptions Inherit
</IfModule>
Oh, them and their IfModule. Anyway, “Inherit” by itself is pretty pointless if it's in the config file and there's nothing further upstream to inherit. For things to be universally inherited, rather than repeating the directive in each <Directory> and <Files> and .htaccess, you have so say InheritDown somewhere along the line. (This is the part I intend to explore on the test site when I get the energy.)
I use <FilesMatch "variables\.(php|lib)%">. I thought this would be better than setting them for every image, JS, and CSS file unnecessarily?
Again, making this envelope and putting a bunch of RewriteRules inside it is identical in effect to saying
RewriteRule variables\.(php|lib)% blahblah
and then you don't have the execution-order complication. (But what's the % for? Did you mean to say $ I hope?)

But I have to say I don't perfectly understand the connection between “every image, JS, and CSS file” and "variables\.(php|lib)". You didn't get <FilesMatch> mixed up with <If> somewhere along the line, did you?
I don't know what it is, but there's just something about the way that the docs are written that makes it just impossible to sink in.
It's not just you. The docs definitely do have their issues--I particularly dislike many of their Regular Expressions--which is why we need phranque with his particular ability to Find Stuff.

csdude55

5:32 am on Feb 1, 2023 (gmt 0)

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



Again, making this envelope and putting a bunch of RewriteRules inside it is identical in effect to saying

In this particular case, though, I have 200+ lines inside of the <FilesMatch>. It wouldn't make sense to have the same condition before each of them, would it?

But what's the % for? Did you mean to say $ I hope?

Sorry, yeah, just a type :-)

But I have to say I don't perfectly understand the connection between “every image, JS, and CSS file” and "variables\.(php|lib)". You didn't get <FilesMatch> mixed up with <If> somewhere along the line, did you?

Well, there's a very good chance that I'm misunderstanding something.

It's my understanding that these rules will run on every HTTP request, including images, JS, and CSS as well as HTML and CGI. Right? In this case, where I'm setting a series of environment variables that would only ever need to be read in variables.php or variables.lib, it doesn't make sense to set those variables for each of those other things. So I thought that using <FilesMatch> would prevent that. Am I wrong?

lucy24

6:22 am on Feb 1, 2023 (gmt 0)

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



It wouldn't make sense to have the same condition before each of them, would it?
There's no need for any Condition. If you're matching files of a particular type--whether that be URLpath, filename or extension--that goes in the body of the rule.
RewriteRule ^dirname/ blahblah
RewriteRule \bexactfilename\b blahblah
RewriteRule \.xtn$ blahblah

Am I wrong?
I think you may not fully appreciate the role of the pattern in a RewriteRule. I've said elsewhere that, as a general rule, don't put anything in a RewriteCond that can be put in the body of the RewriteRule. (There exist exceptions, but they don't apply here.)

Now, you may find it appropriate to use the [S] flag with the rarely-used negative pattern:
RewriteRule !variables\.(php|lib)$ - [S=some-number]
meaning “if the requested file is NOT variables.php or variables.lib then skip the next so-and-so-many rules. (Counting only the rules themselves, not Conditions or blank lines or comments.) This does require some attention to ensure you have an accurate count of rules-to-skip.

:: shuddering mightily at the RegEx examples in this section of the docs ::

w/r/t the [E] flag, the docs say
Note that this same effect can be obtained using SetEnvIf. This technique is offered as an example, not as a recommendation.
and this time I have to agree.

But it's an awful shame you can't achieve your desired goal by something straightforward like
SetEnvIf Request_URI (\w+)\.(php|lib) jigsaw=$1
or
SetEnvIf Host (\w+)\.com foobar=$1
and then use those jigsaw and foobar values for whatever murky and nefarious purpose you need them for.

csdude55

7:02 pm on Feb 1, 2023 (gmt 0)

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



If you're matching files of a particular type--whether that be URLpath, filename or extension--that goes in the body of the rule.

Well duh! LOL That makes sense :-)

Now, you may find it appropriate to use the [S] flag with the rarely-used negative pattern:

That was actually about to be my next question! LOL I modified a long series of RewriteCond/RewriteRule to SetEnvIf that looks like:

SetEnvIf foo a lorem=1
SetEnvIf foo b lorem=2
SetEnvIf foo c lorem=3

When one matches the remainder will always fail, so it would be REALLY nice if I IF-ELSEIF-ELSE would work here! But since they apparently can't read ENV variables then I guess not :-/

Since I'm exclusive writing ENV variables inside of the <FilesMatch>, do you think it's wiser to use a negative pattern to skip ahead like you suggested? My concern there is that I might add a rule in the future and forget to change the line number.

lucy24

7:30 pm on Feb 1, 2023 (gmt 0)

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



The [S] flag should definitely be used with caution, simply because the number has to be right. But if you're already inside a <Files> envelope, anything based on the filename would be superfluous.

SetEnvIf foo a lorem=1
SetEnvIf foo b lorem=2
SetEnvIf foo c lorem=3
Yup, that's what I meant about captures. It would be a lot simpler if the rule could instead say
SetEnvIf foo (a|b|c) lorem=$1
and then when you get to the code that uses “lorem” it works on a, b or c rather than 1, 2 or 3. But then we're back to the question of why it can’t simply use “foo” in the first place--dunno about perl, but pretty much all aspects of the request are available to php--though this may not be answerable without disclosing too much about the sites involved.

csdude55

8:20 pm on Feb 14, 2023 (gmt 0)

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



I have another question related to the order of operations.

I have several .CONF files, primarily split up into multiple files for my own organization. They're named in BASIC format so that they run in the expected order:

10_environmentvariables.conf
20_configuration.conf

and so on.

If I use mod_rewrite in 10 and mod_setenvif in 20, am I correct that the mod_rewrite in 10 would execute first?

phranque

8:44 pm on Feb 14, 2023 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



configuration directives are merged first, then processed.
This 32 message thread spans 2 pages: 32