Is $_SERVER['REQUEST_SCHEME'] reliable?

The REQUEST_SCHEME environment variable is documented on the Apache mod_rewrite page. However, it didn't become available until Apache 2.4.

I only have Apache 2.2 so I created an environment variable. I added the following to the top of my .htaccess file.

RewriteEngine on

# Set REQUEST_SCHEME (standard environment variable in Apache 2.4)
RewriteCond %{HTTPS} off
RewriteRule .* - [E=REQUEST_SCHEME:http]

RewriteCond %{HTTPS} on
RewriteRule .* - [E=REQUEST_SCHEME:https]

Now I can use

  • %{ENV:REQUEST_SCHEME} in other rewrite conditions and rules
  • $_SERVER['REQUEST_SCHEME'] in my PHP code

I don't have to do extra messy conditional checks everywhere, and my PHP code is forward compatible. When Apache is upgraded, I can change my .htaccess file.

I don't know how you'd apply this to a Windows environment. This is probably not a good solution for distributed code, but it works well for my needs.


It is hard to prove that it is reliable, but it is easy to prove that it is not reliable (if only I could provide a case which it does not work). And I can prove that it is unreliable because it does not work with IIS 7.0 + PHP 5.3


As this variable is not available in all web server versions, it is not reliable testing only it. Instead, you can change your PHP code to test two more server environment variables, which can also indicate that https is being used, as below:

if ( (! empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') ||
     (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
     (! empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ) {
    $server_request_scheme = 'https';
} else {
    $server_request_scheme = 'http';
}

As remarked by toxalot, REQUEST_SCHEME is a native variable of Apache web server since its version 2.4. Apache 2.2 does not have it (see Apache 2.2 server variables) and Microsoft IIs 8.5 does not have it either (see IIS 8.5 Server Variables). Naturally, if a variable is not set by the server, PHP will not include it in its global array $_SERVER.

Fortunately, for compatibility with codes based exclusively on REQUEST_SCHEME checking, you can create this variable in Apache 2.2 editing all your host configuration files (httpd.conf, ssl.conf, 000-default.conf, vhosts.conf), adding the following lines:

# FOR HOSTS LISTENING AT PORT 80
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=http

# FOR HOSTS LISTENING AT PORT 443
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=https

The code above presume the use of one vhost for every protocol (a best practice in Apache - see this and that).