46

Is it possible to get the http headers of the current request with PHP? I am not using Apache as the web-server, but using nginx.

I tried using getallheaders() but I am getting Call to undefined function getallheaders().

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Justin
  • 42,716
  • 77
  • 201
  • 296

6 Answers6

50

Taken from the documentation someone wrote a comment...

if (!function_exists('getallheaders')) 
{ 
    function getallheaders() 
    { 
       $headers = array (); 
       foreach ($_SERVER as $name => $value) 
       { 
           if (substr($name, 0, 5) == 'HTTP_') 
           { 
               $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; 
           } 
       } 
       return $headers; 
    } 
} 
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
Layke
  • 51,422
  • 11
  • 85
  • 111
  • 1
    Thanks it works. But could you explain what is the purpose of `ucwords` and `strtolower` in that function ? Is it necessary ? – Michal S. Nov 20 '16 at 15:33
  • 2
    A bug in this function is that uppercase headers such as "DNT" (Do Not Track) will become "Dnt" - which is NOT the case of native getallheaders() – Bell Mar 11 '17 at 22:44
  • 3
    The "Authorization" didn't appear with this function... Any idea ? – Toto NaBendo Apr 26 '19 at 07:36
27

Improved @Layke his function, making it a bit more secure to use it:

if (!function_exists('getallheaders'))  {
    function getallheaders()
    {
        if (!is_array($_SERVER)) {
            return array();
        }

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

(wished I could just add this as a comment to his answer but still building on that reputation thingy -- one of my first replies)

JanDesch
  • 546
  • 6
  • 5
4

This issue was finally addressed in PHP 7.3.0, check release notes.

Fixed bug #62596 (getallheaders() missing with PHP-FPM).

Geo Salameh
  • 323
  • 2
  • 8
  • Can you elaborate what this means? (Answers should be self contained, see for example "Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link" https://stackoverflow.com/help/how-to-answer) – Sybille Peters Nov 24 '22 at 12:53
  • Also, links are often broken after some time ... – Sybille Peters Nov 24 '22 at 12:54
3

You can upgrade your server to PHP 5.4 thereby giving you access to getallheaders() via fastcgi or simply parse what you need out of $_SERVER with a foreach loop and a little regex.

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
Chris Wiegman
  • 382
  • 1
  • 2
  • 10
  • 1
    Does `nginx` always run on FastCGI? Is that why `getallheaders()` doesn't work under PHP 5.3? – Ben Harold May 31 '13 at 18:17
  • 1
    @BenHarold See changelog of [getallheaders](http://www.php.net/manual/en/function.getallheaders.php): _5.4: This function became available under FastCGI. Previously, it was supported only when PHP was installed as an Apache module._ – Fred Wuerges May 31 '13 at 19:00
  • @FredWuerges I did read the changelog. That's why I asked the questions. To word it a little better: Does nginx always use FastCGI, and is that why `getallheaders()` doesn't work when using PHP 5.3 or older with nginx? Does this mean that both `getallheaders()` and `apache_request_headers()` work when using PHP 5.4 and nginx? – Ben Harold May 31 '13 at 21:17
  • @BenHarold Now it's clear. If we follow the premise of the changelog, we conclude that the wheel always nginx with FastCGI, if PHP is in 5.4 or higher, will work. Thus, if PHP is in 5.3 will not run on nginx. – Fred Wuerges May 31 '13 at 21:31
  • This should be marked as correct. On 5.4, just do $headers = getallheaders(); if ($token = $headers['Authorization']) {/*check token*/} else {/*Not authed*/}. Very simple. – Stephen Smith Jul 06 '14 at 15:31
  • 4
    This does not work on nginx still, getallheaders is filed under apache functions in the PHP doc since it is Apache only as confirmed on php 5.5 and nginx – Sammaye Sep 11 '14 at 22:28
  • 7
    Currently on PHP7 getallheaders does not work on nginx under FastCGI – Jesse Greathouse Oct 25 '15 at 19:55
3

Combined getallheaders() + apache_request_headers() for nginx

    function get_nginx_headers($function_name='getallheaders'){

        $all_headers=array();

        if(function_exists($function_name)){ 

            $all_headers=$function_name();
        }
        else{

            foreach($_SERVER as $name => $value){

                if(substr($name,0,5)=='HTTP_'){

                    $name=substr($name,5);
                    $name=str_replace('_',' ',$name);
                    $name=strtolower($name);
                    $name=ucwords($name);
                    $name=str_replace(' ', '-', $name);

                    $all_headers[$name] = $value; 
                }
                elseif($function_name=='apache_request_headers'){

                    $all_headers[$name] = $value; 
                }
            }
        }


        return $all_headers;
}
RafaSashi
  • 16,483
  • 8
  • 84
  • 94
0

This should work:

<?php 

print_r(
  array_intersect_key(
    $_SERVER,
    array_flip(
      preg_grep(
        '/^HTTP_/', 
        array_keys($_SERVER),
        0
      )
    )
  )
);
Volomike
  • 23,743
  • 21
  • 113
  • 209