automad
automad copied to clipboard
Use `$_SERVER` rather than `getenv()` for server request vars
When I moved from my development machine to my production host, index.php
files started appearing in the URLs.
Using Automad's excellent debugging capabilities, I tracked the problem down to here.
My host doesn't set a SERVER_SOFTWARE
environment variable.
In fact, it turns out that using environment variables for such things is wrong.
I found an interesting 2016 thread here. The long and short of it is that Symfony was using getenv()
for certain kinds of things, and no longer does. (To be clear: it no longer uses getenv()
for server request vars; it does for other things not related to server request vars.) Laraval is the same.
It seems that the vars listed on the $_SERVER
page should only be accessed through $_SERVER
, and never through getenv()
?
In the meantime, my workaround was to add this to index.php
:
putenv('HTTP_HOST='.$_SERVER['HTTP_HOST']);
putenv('HTTP_X_FORWARDED_HOST='.$_SERVER['HTTP_X_FORWARDED_HOST']);
putenv('HTTP_X_FORWARDED_SERVER='.$_SERVER['HTTP_X_FORWARDED_SERVER']);
putenv('HTTPS='.$_SERVER['HTTPS']);
putenv('SERVER_NAME='.$_SERVER['SERVER_NAME']);
putenv('SERVER_SOFTWARE='.$_SERVER['SERVER_SOFTWARE']);
putenv('SCRIPT_NAME='.$_SERVER['SCRIPT_NAME']);
(I'm not suggesting that my workaround is a solution; in fact, as given that approach won't work in some environments. The point was to show you the list of server request vars that might be relevant to the issue.)
There are 23 uses of getenv()
in 6 files. I checked them against the keys listed on the $_SERVER
page; it looks like all of them should be switched to $_SERVER
. (Btw, a couple of keys, like SERVER_NAME
, are currently accessed both ways.)
Let me know if you'd like me to tackle this.
(Btw, just for completeness, my original list missed one key: SERVER_PORT
.)
Hi, thanks for reporting this. The advantage of getenv
is that it doesn't require a check whether a key exists. In that sense one could argue it is even the better solution. But I understand your trouble and will take a look at it.
However, there is an easy way to make the index.php
disappear from the URL. In case the automatic detection fails, you can set the AM_INDEX
constant to an empty string in the config.
In that sense one could argue it is even the better solution. But I understand your trouble and will take a look at it.
Marc, this isn't "my trouble." It's about the wrong approach and the right approach. There's no sense in which one could argue that the wrong approach is the better solution!
I sent you a thread in which the Symfony developers admitted they were wrong, and changed their code. (There's a lot of detail in that thread. It's worth a careful read. I followed links and looked at the source code they were talking about.)
After finding that, I took the time to verify that both Laravel and Symfony exclusively use $_SERVER
for server request vars today.
Here is Grav, another flat-file PHP-based CMS. Same thing.
Here is Kirby, another flat-file PHP-based CMS. Same thing.
If you like the convenience of what getenv()
provides you can create a small wrapper around $_SERVER
that works the same way.
_SERVER is the correct solution. As it currently is, automad cannot be run behind distributed transparent caching proxies. Which is a bit sad, since it's quite nice.
I haven't tested if the putenv solution above will work with ha-proxy / varnish & a cdn, but I'll try to get to it.
I haven't tested if the putenv solution above will work with ha-proxy / varnish & a cdn, but I'll try to get to it.
No, that is not sufficient. I'm not sure what is happening here, but I can varnishlog the POST requests. I checked to make sure that no form / session cookies are being unset (are not), but login does not work. It does with the same setup on a drupal install.
Hi, so it looks that switching to $_SERVER
would be the only working solution, right? I haven't tested it in the environment you described though. But I guess it is not a big deal to replace getenv()
entirely.
It will probably be fixed in the next major release.
One other thing came into my mind. There is the AM_BASE_PROXY
constant that can be defined in the config in order to address issues with URL rewriting for pages behind proxies. Maybe you could give that one a quick try.
One other thing came into my mind. There is the
AM_BASE_PROXY
constant that can be defined in the config in order to address issues with URL rewriting for pages behind proxies. Maybe you could give that one a quick try.
I'll try this later this evening. Thanks!
One other thing came into my mind. There is the
AM_BASE_PROXY
constant that can be defined in the config in order to address issues with URL rewriting for pages behind proxies. Maybe you could give that one a quick try.
Errr, what should it be set to? In my drupal configs I noted 127.0.0.1 ?
127.0.0.1 ? that value does not work ;)
After taking a closer look, it turned out that it needed more than changing from getenv()
to $_SERVER
. That actually has really nothing todo with it at all, as I mentioned before. However, I agree that a streamlined use of $_SERVER
is more consistent here as well.
The actual issue is that the automatic determination of the base URL is not working correctly when running behind a proxy. That basically breaks the app. In the beginning it was not meant to run in such a scenario and also was not really tested therefore.
However, I have just added the ability to run behind a proxy. The feature will be included in the next major release.
However, I have just added the ability to run behind a proxy. The feature will be included in the next major release.
Ah, that's great news. I host a lot of smaller sites on IPv6 only virts and proxy IPv4 with a transparent cache, so that would make those scenarios automadic :) Thanks for all your work!