PHP $_SERVER – Some Things You Didn’t Know

September 17, 2013 — 2 Comments
php $_server... because of ports, duh

photo by Piet Musterd

The PHP $_SERVER superglobal allows you access to some truly useful information about the client browser, the web server environment, and the current page context. We all know the basics of what this array holds, but here I go into a bit more detail to find out what else it can tell us…

What is the PHP $_SERVER superglobal?

PHP’s $_SERVER superglobal is a global variable created by the web server. $_SERVER stores information about the current page request and the environment in which it is being executed. The name of the variable is a bit misleading: some of the elements in the $_SERVER array are actually descriptive of the User Agent (i.e.: the browser), and are provided by the browser.

The presence of any given element in the array is not reliable: not all the elements listed will always be available. This is because the information is provided by the web server, not by PHP. And if you are running PHP via the command line interface (CLI) many of these elements become meaningless or are absent.

Common Uses

These are the most commonly used elements:

  • SERVER_NAME: i.e.: the URL of the current site.
  • HTTP_USER_AGENT: often used to customise the page content, for example when showing downloads specific to the user’s browser and OS on a software downloads page.
  • REMOTE_ADDR: commonly used to get the IP Address of the user for logging or geolocation.
  • SCRIPT_FILENAME: The full path to the current PHP script. There are some gotchas here, read the full description below for details.
  • QUERY_STRING: a text string containing all the parameters in the http request.

More details below.

$_SERVER Elements reference

  • HTTP_HOST: not to be confused with SERVER_NAME, though the two will usually look identical. HTTP_HOST is actually just echoing the host header provided in the http request. So, although it is useful if you are interested in the brower’s intent, it is unreliable. Therefore you should use $_SERVER["SERVER_NAME"] (or the configuration of your application) if you want to know the current server address.
  • HTTP_USER_AGENT: the browser’s professed user agent. This might not be accurate: aside from the many spiders and bots that cloak their identity and claim to be Firefox or IE, there are also tools in many browsers to switch user agents.
  • HTTP_ACCEPT: the browser can indicate to the web server not just the types of content that it accepts, but also which of these it prefers. In the example below, my browser sent "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", indicating that the types "text/html,application/xhtml+xml were most preferred, since they were not marked with a quality indicator parameter. That resulted in their quality being set to the default of 1. The xml type is different, and was specified as: application/xml;q=0.9, indicating a lesser preference for xml (i.e.: 0.9 vs 1.0). Finally, all other types are marked with a quality indicator of 0.8: */*;q=0.8.
  • HTTP_ACCEPT_LANGUAGE: the browser can specify language preference, using the same quality indicator syntax we saw in HTTP_ACCEPT.
  • HTTP_ACCEPT_ENCODING: again, this comes from the headers sent in the request.
  • HTTP_CONNECTION: another variable set from the client request. This one allows the browser to let the server know that it supports keep-alives. This sounds good, but http 1.1 (in widespread use) uses keep alives by default, so sending this in the request is pretty meaningless unless the request is http 1.0. Keep alives are used to enable persistent connections, which can save resources since the TCP connections are reused for multiple files instead of recreated for every request. In any case, it’s fairly common for server administrators to leave persistent conenctions enabled but set the timeout interval very low. This provides a good experience for well-beahiving, fast browsers, but tries to minimize the exposure to denials of service (where bad clients can open many connections without using or closing them, thus denying access to other clients). The increasing popularity of CDNs and other forms of distribution have again changed things, since they move resources away from the server that generates the html. And more recently, the massive increase in mobile traffic means that slower devices on slower (mobile) networks have forced some server admins to increase timeouts again. Upshot: performance is always an issue. For more on PHP performance, see this.
  • PATH: the currently configured php include path.
  • SERVER_SIGNATURE: this will be populated with the web server version information, but only if server signatures are enabled. This should be blank in most cases, but don’t think for a second that means your server is secure!
  • SERVER_NAME: this comes from the resolved server name, or from the ServerName directive if Apache is running the site as a virtual host.
  • SERVER_ADDR: the IP Address of the web server or virtual server. Note that this is the IP Address as resolved, not necessarily the external interface. So in some cases this is likely to be ’127.0.0.1′ as in my example below.
  • SERVER_PORT: commonly 80 for http and 443 for https, but can be anything if you change Apache’s Listen parameter from the default 80.
  • REMOTE_ADDR: the IP Address of the browser, or of the proxy between.
  • DOCUMENT_ROOT: comes from either Apache’s DocumentRoot parameter or from that in the current virtual host.
  • SERVER_ADMIN: comes from Apache’s ServerAdmin directive. Not often populated with anything other than ‘you@example.com’ because it’s such a target for spammers.
  • SCRIPT_FILENAME: the absolute path of the currently running script. In other words, relative to the root of the file system. This is probably most useful when you need to get out of the web root. Bear in mind that in most PHP apps, this will be the path to your bootstrap script file. So the usefulness of this is limited in most modern PHP apps.
  • REMOTE_PORT: the port used by the client browser.
  • GATEWAY_INTERFACE: the version of CGI that the se server supports.
  • SERVER_PROTOCOL: the protocol and version information for the current page request. This could be useful for whether the request is https, though usually any checks around that would happen earlier (for example in a .htaccess rule).
  • REQUEST_METHOD: the method the client used to access the page. Commonly used to determine whether this is a POSTed form or a form display using GET.
  • QUERY_STRING: all the parameters attached to the current page request; i.e. everything after the ?.
  • REQUEST_URI: everything in the URL except the actual server address. So this might contain random invalid data.
  • SCRIPT_NAME: the path to the current script. This might be the same as REQUEST_URI, but it’s more reliable.
  • PHP_SELF: this is meant to be the path of the currently executing script, but it’s drawn from the rquest and might contain utter garbage, so use with caution.
  • REQUEST_TIME_FLOAT: the timestamp of the request with microsecond accuracy.
  • REQUEST_TIME: a slightly less OCD version of REQUEST_TIME_FLOAT that omits the microseconds.
  • argv: if the current script is called via GET this will look very much like QUERY_STRING. If run via CLI, this will be an array of command-line parameters.
  • argc: a count of the parameters. This will always be 1 if the current script is called via the GET method.

PHP $_SERVER Elements – A Real World Example

As a reference, here’s what I based my list on. This is from the MAMP installation on my laptop. Note the query string variables that appear in $_SERVER["QUERY_STRING"] and $_SERVER["REQUEST_URI"]. They’ve also appeared in $_SERVER["argv"][0] and this has set $_SERVER["argc"] to 1. Also note: I’ve wrapped HTTP_USER_AGENT to two lines to help readability.

array(28) {
["HTTP_HOST"]=>
string(11) "tools.local"
["HTTP_USER_AGENT"]=>
string(117) "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1
(KHTML, like Gecko) Version/6.0.5 Safari/536.30.1"
["HTTP_ACCEPT"]=>
string(63) "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
["HTTP_ACCEPT_LANGUAGE"]=>
string(5) "en-us"
["HTTP_ACCEPT_ENCODING"]=>
string(13) "gzip, deflate"
["HTTP_CONNECTION"]=>
string(10) "keep-alive"
["PATH"]=>
string(29) "/usr/bin:/bin:/usr/sbin:/sbin"
["SERVER_SIGNATURE"]=>
string(0) ""
["SERVER_SOFTWARE"]=>
string(66) "Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/0.9.8x DAV/2 PHP/5.4.4"
["SERVER_NAME"]=>
string(11) "tools.local"
["SERVER_ADDR"]=>
string(9) "127.0.0.1"
["SERVER_PORT"]=>
string(2) "80"
["REMOTE_ADDR"]=>
string(9) "127.0.0.1"
["DOCUMENT_ROOT"]=>
string(22) "/Users/jay/Sites/tools"
["SERVER_ADMIN"]=>
string(15) "you@example.com"
["SCRIPT_FILENAME"]=>
string(33) "/Users/jay/Sites/tools/server.php"
["REMOTE_PORT"]=>
string(5) "52630"
["GATEWAY_INTERFACE"]=>
string(7) "CGI/1.1"
["SERVER_PROTOCOL"]=>
string(8) "HTTP/1.1"
["REQUEST_METHOD"]=>
string(3) "GET"
["QUERY_STRING"]=>
string(29) "cheese=gruyere&bread=ciabatta"
["REQUEST_URI"]=>
string(41) "/server.php?cheese=gruyere&bread=ciabatta"
["SCRIPT_NAME"]=>
string(11) "/server.php"
["PHP_SELF"]=>
string(11) "/server.php"
["REQUEST_TIME_FLOAT"]=>
float(1379213291.88)
["REQUEST_TIME"]=>
int(1379213291)
["argv"]=>
array(1) {
[0]=>
string(29) "cheese=gruyere&bread=ciabatta"
}
["argc"]=>
int(1)
}

More Reading

2 responses to PHP $_SERVER – Some Things You Didn’t Know

  1. It may be easier to state that any HTTP_ item in this array actually holds the contents of a HTTP request header, coming from the browser.

Leave a Reply

*

Text formatting is available via select HTML.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>