Forum Moderators: phranque

Message Too Old, No Replies

Automagically setting variable to /home/example

         

csdude55

3:45 pm on Feb 4, 2021 (gmt 0)

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



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

RewriteRule ^ - [E=foo:${HOME}]


it sets foo to /root. Using %{HOME} returns nothing. I'm guessing that this variable is set by PHP instead of Apache, so it's not accessible pre-PHP?

I know that I could hack it out, like:

RewriteCond %{DOCUMENT_ROOT} (/home/\w+)/public_html
RewriteRule ^ - [E=foo:%1]


but I'm not in love with the idea of using a condition without a fallback.

Before I resort to that, is there any other way of accessing /home/example via Apache?

I have always used a variable in PHP and Perl of $basepath = '/home/example';, and if I could set it one time in Apache then I could eliminate that in all of my accounts (which would be marginally faster, and cut down on the probability of typos in future scripts). I could obviously still use $basepath = $_SERVER['HOME']; in PHP, but since I'm setting a ton of other variables in Apache then I'd like to do this one the same way if I can.

w3dk

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

10+ Year Member Top Contributors Of The Month



RewriteRule ^ - [E=foo:${HOME}]


If you are accessing the variable using the syntax ${VAR} then VAR is either a "shell environment variable" (defined outside of Apache) or has been defined using the "Define" directive elsewhere in your server config. If it wasn't defined at all then you would get the literal text "${HOME}" (ie. it's not expanded).

%{HOME} would return the value of an "Apache server variable". (There are no standard Apache server variables by this name.) Whereas %{ENV:HOME} would return the value of an "environment variable" by that name (again, there are no standard environment variables by that name).

${HOME}, %{HOME} and %{ENV:HOME} reference 3 different variables all called "HOME".

"HOME" is not a standard Apache or PHP server/environment variable.

I could obviously still use $basepath = $_SERVER['HOME']; in PHP


If this is working in your environment then this may be the preferred way to do it anyway? If you set another env var in Apache then you'd only have to reference that in a similar way in PHP?

However, if your code needs to be portable, then relying on $_SERVER['HOME'] would not be recommended, since it's unlikely to work on other servers.

There is no standard variable as far as I'm aware (in Apache or PHP) that holds the value of the directory-above-the-document-root, this would always need to be calculated. Personally, I would do this in PHP. For example:


$basepath = dirname($_SERVER['DOCUMENT_ROOT']);

lucy24

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

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



Edit: I overlapped w3dk, so I hope there are no wild contradictions.

I'm guessing that this variable is set by PHP instead of Apache, so it's not accessible pre-PHP?
afaik, nothing ever happens in php until the server itself has done all its stuff and the request arrives at the page containing the php. (Or the invisible script, in the case of something like auto-indexing.)

but I'm not in love with the idea of using a condition without a fallback
:: detour to horse's mouth [httpd.apache.org] because I'm so used to thinking of DOCUMENT_ROOT as an URL element, not a filepath ::

What does “fallback” mean in this context? If the Condition isn't met--say, you changed some part of your root directory's filepath and forgot to update the RewriteRule--then the variable simply isn't set. Seems like that's what you would want in that case.

csdude55

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

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



I gotcha, thanks for the input! I only saw [HOME] after moving to the new VPS so I figured it was something with their configuration, but at the same time I updated Apache and PHP so I wasn't positive and couldn't find anything about it.

Short term I'm looking at speed, and long term I'm looking at portability. I discovered a few months ago that setting variables in my Apache configuration processed considerably faster than setting them in PHP, so I've moved everything that I can to Apache and then using this to define them in PHP (which you and I discussed earlier, @lucy24):

foreach ($_SERVER as $key => $val)
if (lcfirst($key) === $key)
$$key = (!empty($val)) ?
str_replace('%2C', ',', $val) :
false;


I forget the bench test, but I think it shaved about 300ms off of every page load :-O Plus, it makes it easier if I need to change something en masse in the future.

(Note, it was marginally faster to just set all of the server variables and leave off the if (lcfirst($key) === $key) condition, but I didn't like having that many unused variables floating around. I'm also not sure that using "false" as a fallback is necessary, but it didn't really affect the speed so I left it.)

What does “fallback” mean in this context? If the Condition isn't met--say, you changed some part of your root directory's filepath and forgot to update the RewriteRule--then the variable simply isn't set. Seems like that's what you would want in that case.

Thinking long term... back in the day, the directory path was something like /var/example instead if /home/example. I think I was using Solaris at the time? I dunno, it's been awhile. So if an overnight update to Apache or cPanel or something suddenly changes the path then the whole thing breaks.

This variable is primarily used to define a location for log files, text-based cache files, and specialized Perl modules, so if it comes back as empty then those scripts all break.

Which, of course, it's pretty unlikely for a major shift like that unless I change to a whole new VPS; in which case I'd almost definitely see it long before going live! So it's an OK solution, but I wanted to make sure there wasn't a predefined variable that would always be the proper path.

w3dk

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

10+ Year Member Top Contributors Of The Month



I discovered a few months ago that setting variables in my Apache configuration processed considerably faster than setting them in PHP


Are you talking about just setting ordinary variables in PHP (which is what you seem to be)? OR are you specifically setting "environment variables" in PHP, eg. with putenv()?

If you are doing the former (ie. these variables are only used by PHP), then setting env vars in Apache cannot be faster; since you are essentially doing twice the work?

(Note, it was marginally faster to just set all of the server variables and leave off the if (lcfirst($key) === $key) condition, but I didn't like having that many unused variables floating around....


That would also be a security vulnerability. (Remember "register_globals"?)

If you wanted this to be "portable" then you can't use "HOME" at all. It's not a case of checking to see if it's set, and if it's not then calculate it. Since on another server "HOME" could be set, but means something entirely different.

csdude55

11:44 pm on Feb 8, 2021 (gmt 0)

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



Are you talking about just setting ordinary variables in PHP (which is what you seem to be)? OR are you specifically setting "environment variables" in PHP, eg. with putenv()?
If you are doing the former (ie. these variables are only used by PHP), then setting env vars in Apache cannot be faster; since you are essentially doing twice the work?

I thought the same thing, but it turned out to be considerably faster! There's a thread on here about it from early last year, I think, but I couldn't find it :-(

In my case, moving the variables to Apache .conf cut the size of variables.php (that's including on every PHP script) by 11kb, and removed one MySQL SELECT query, so those were probably what affected the time as opposed to the actual setting of the variables. My preliminary tests were on my old VPS using PHP 5.6 and HTTP/1.1, too, so it could be different now that I'm using PHP 7.x and HTTP/2.