Using $_SERVER['REQUEST_SCHEME'] === 'https' is not always trustworthy. First of all, it's only available in Apache >=2.4. It doesn't even exist in nginx, IIS, lighttpd and other web servers.
Proposed resolution
Create a protected method Request::getRequestScheme() that can properly calculate whether http or https was used. Use this function to set Request->scheme and Request->secure member variables.
protected static function getRequestScheme() : bool
{
// Modern servers will have the HTTPS header set to 'on' or '1'.
if (
isset($_SERVER['HTTPS'])
&& (
strtolower($_SERVER['HTTPS']) == 'on'
|| $_SERVER['HTTPS'] == 1
)
) {
return 'https';
}
// Some reverse proxies and load balencers will have the
// HTTP_X_FORWARDED_PROTO header set to 'https'.
else if (
isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https'
) {
return 'https';
}
// Other reverse proxies and load balencers will have the
// HTTP_FRONT_END_HTTPS headers set to 'on' or '1'.
else if (
isset($_SERVER['HTTP_FRONT_END_HTTPS'])
&& (
strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) == 'on'
|| $_SERVER['HTTP_FRONT_END_HTTPS'] == 1
)
) {
return 'https';
}
// Apache server may have the REQUEST_SCHEME header available.
else if (
isset($_SERVER['REQUEST_SCHEME'])
&& strtolower($_SERVER['REQUEST_SCHEME']) == 'https'
) {
return 'https';
}
// If all else fails, try the standard SSL server port '443'.
else if (
isset($_SERVER['SERVER_PORT'])
&& intval($_SERVER['SERVER_PORT']) === 443
) {
return 'https';
}
return 'http';
}
Problem statement
Using
$_SERVER['REQUEST_SCHEME'] === 'https'
is not always trustworthy. First of all, it's only available in Apache >=2.4. It doesn't even exist in nginx, IIS, lighttpd and other web servers.Proposed resolution
Create a protected method
Request::getRequestScheme()
that can properly calculate whether http or https was used. Use this function to setRequest->scheme
andRequest->secure
member variables.