Fix GRAV_CONFIG env override gate to also check $_SERVER/$_ENV - #4286
Fix GRAV_CONFIG env override gate to also check $_SERVER/$_ENV#4286wakqasahmed wants to merge 2 commits into
Conversation
…etenv() Some SAPIs (Apache SetEnv, nginx fastcgi_param) only populate $_SERVER, never the process environment getenv() reads. The gate at InitializeProcessor::initializeConfig() checked getenv() alone even though the body one line below already reads $_ENV + $_SERVER, so the whole GRAV_CONFIG__* override feature silently did nothing under those setups. Setup.php had the same getenv()-only pattern for GRAV_ENVIRONMENT, GRAV_SETUP_PATH, GRAV_ENVIRONMENT_PATH and GRAV_ENVIRONMENTS_PATH. Applies the same $_SERVER ?? $_ENV ?? getenv() fallback Env.php already uses (and already has test coverage for) at all five call sites. Added a regression test that fails on the old code and passes on the fix. Fixes getgrav#4279
|
Thanks for picking this one up, and for taking the trouble to redo it cleanly after the author mix-up on #4285. That's appreciated. The diagnosis is right, and the test is the best part of the PR. I checked it the way I check these: I reverted just the one line in There's one thing I need changed before this can go in, and it's a subtle one that bit the last PR in this same family too.
For The fix is to fall through on empty as well as missing, which is the same correction I made to the One small private helper in /**
* Read a bootstrap variable from wherever the SAPI put it.
*
* $_SERVER is the only source PHP guarantees for server-set variables, but
* a present-but-empty entry (an unset nginx variable used in a
* `fastcgi_param`, an empty `SetEnv`) must not shadow a working getenv(),
* or the fix breaks the hosts where the old code worked. Mirrors Env.php
* and Uri::ip(). (#4279)
*
* @param string $name
* @return string|null
*/
private static function envVar(string $name): ?string
{
foreach ([$_SERVER[$name] ?? null, $_ENV[$name] ?? null, getenv($name)] as $value) {
if (is_string($value) && $value !== '') {
return $value;
}
}
return null;
}with the four call sites becoming: (defined('GRAV_ENVIRONMENT') ? GRAV_ENVIRONMENT : static::envVar('GRAV_ENVIRONMENT'));
$setupFile = defined('GRAV_SETUP_PATH') ? GRAV_SETUP_PATH : static::envVar('GRAV_SETUP_PATH');
$envPath = defined('GRAV_ENVIRONMENT_PATH') ? GRAV_ENVIRONMENT_PATH : static::envVar('GRAV_ENVIRONMENT_PATH');
$envPath = defined('GRAV_ENVIRONMENTS_PATH') ? GRAV_ENVIRONMENTS_PATH : static::envVar('GRAV_ENVIRONMENTS_PATH');And for the // Override configuration using the environment. The gate has to read
// exactly what the loop below reads: a SAPI that populates only
// $_SERVER (Apache SetEnv, nginx fastcgi_param) would otherwise skip
// the whole feature with nothing logged, and an empty value must fall
// through rather than shadow a working getenv(). (#4279)
$prefix = 'GRAV_CONFIG';
$vars = $_ENV + $_SERVER;
if (!empty($vars[$prefix]) || getenv($prefix)) {Two smaller things while you're in there. Could the test save and restore any pre-existing No changelog needed from you, I'll write that on merge. Nice work. Get those in and I'll take it. |
An env var read via \$_SERVER['X'] ?? \$_ENV['X'] ?? getenv('X') falls through
on missing, not on empty. A SAPI that sets the variable but sets it to
nothing (an unset nginx fastcgi_param, an empty Apache SetEnv) satisfies
the ?? chain with '' and the getenv() fallback never runs - which breaks
GRAV_CONFIG overrides, GRAV_ENVIRONMENT, GRAV_ENVIRONMENT_PATH,
GRAV_SETUP_PATH and GRAV_ENVIRONMENTS_PATH on exactly the hosts the
previous fix for getgrav#4279 was supposed to help, and for GRAV_SETUP_PATH it's
worse than quiet: an unresolvable value makes Setup.php exit(1).
Added a private Setup::envVar() helper that tries \$_SERVER, then \$_ENV,
then getenv(), skipping any that come back empty, and switched all five
call sites to it. The GRAV_CONFIG gate in InitializeProcessor now checks
the same \$_ENV + \$_SERVER array its body already reads instead of a
separate getenv()-first check, so the gate and the body can't disagree.
Test changes: the existing getgrav#4279 test now saves and restores whatever
was already in \$_SERVER instead of unconditionally unsetting it, and a
new test pins the empty-\$_SERVER-falls-back-to-getenv case with
putenv().
|
Good catch, and thanks for the exact pointer - pushed a commit with your |
The
GRAV_CONFIGoverride gate inInitializeProcessor::initializeConfig()checksgetenv($prefix), but the body one line below already reads$_ENV + $_SERVER. On Apache withSetEnvor nginx withfastcgi_param, the variable lands in$_SERVERbut never in the process environmentgetenv()reads, so the gate is false and the wholeGRAV_CONFIG__*override feature does nothing — same failure mode as #4260/#4275.Setup.phphas the identical pattern forGRAV_ENVIRONMENT,GRAV_SETUP_PATH,GRAV_ENVIRONMENT_PATHandGRAV_ENVIRONMENTS_PATH.Env.phpalready solves this correctly ($_SERVER[$key] ?? $_ENV[$key] ?? (getenv($key) ?: null)) and has its own test coverage proving the precedence. This PR applies the same fallback at all five call sites instead of inventing a new pattern.Added a test that sets the override only in
$_SERVERand drives the realinitializeConfig()— confirmed it fails against the old code and passes against the fix. Ran the fullInitializeProcessorTestandEnvTestsuites after, both green (59 tests).(Replaces #4285, which had the wrong commit author — closing that one.)
Fixes #4279