Home / Get the headers sent from the browser with PHP

Get the headers sent from the browser with PHP

I recently needed to be able to see what headers the browser sent to the web server with PHP for testing purposes. This is possible using the apache_request_headers() function but it only works if PHP is run on Apache as a module. This post shows using apache_request_headers() and also an alternative when PHP is run as a CGI. I believe this second method works for lighttpd but have no idea if it works for IIS.

apache_request_headers()

If PHP is run on Apache as a module then the headers the browser send can be retrieved using the apache_request_headers() function. The following example code uses print_r to output the value from this function call:

print_r( apache_request_headers() );

The output from the above using an example request from Google Chrome would output something similar to the following:

Array
(
  [Host] => www.testing.local
  [Connection] => keep-alive
  [User-Agent] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.206.1 Safari/532.0
  [Cache-Control] => max-age=0
  [Accept] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
  [Accept-Encoding] => gzip,deflate,sdch
  [Accept-Language] => en-US,en;q=0.8
  [Accept-Charset] => ISO-8859-1,utf-8;q=0.7,*;q=0.3
)

An alternative method

If PHP is not being run as a module on Apache, the browser headers should be stored in the $_SERVER array with the key being the request header name converted to upper case, hypens replaced with underscores, and prefixed with HTTP_

The same request above showing the relevent lines from $_SERVER are as follows:

[HTTP_HOST] => www.testing.local
[HTTP_CONNECTION] => keep-alive
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.206.1 Safari/532.0
[HTTP_CACHE_CONTROL] => max-age=0
[HTTP_ACCEPT] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate,sdch
[HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.8
[HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.3

The alternative method is create our own function if the apache_request_headers() function does not exist, which extracts just the values from $_SERVER and converts the key names to the same style as apache_request_headers(). This works like so:

if(!function_exists('apache_request_headers')) {
    function apache_request_headers() {
        $headers = array();
        foreach($_SERVER as $key => $value) {
            if(substr($key, 0, 5) == 'HTTP_') {
                $headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))))] = $value;
            }
        }
        return $headers;
    }
}

The new function is only declare if the function with that name does not already exist. The end result is that whether or not the internal PHP function exists, you will be able to call a function with this name in your code.

A loop is done though the $_SERVER array and any whose key starts with HTTP_ is added to the array, and the key is translated via a series of function calls to be in the same format as returned by apache_request_headers().

Some additional notes

This isn’t foolproof, as I’ve only tested the alternative method on Apache which runs PHP as a module (calling my function a different name to be able to test it). It may not always work as expected.

If you can use apache_request_headers() then great, use it. Otherwise some trial and error will be required with the alternative method, or you could instead use the looping idea to find all HTTP_ prefixed variables and refer to variables from the $_SERVER array.

However, for my own purposes (which was to test some code for another post I’m writing) it works perfectly.