Comment lire n'importe quel en-tête de demande en PHP


271

Comment lire un en-tête en PHP?

Par exemple en- tête la coutume: X-Requested-With.

Réponses:


345

SI : vous n'avez besoin que d'un seul en-tête, au lieu de tous les en- têtes, la méthode la plus rapide est:

<?php
// Replace XXXXXX_XXXX with the name of the header you need in UPPERCASE (and with '-' replaced by '_')
$headerStringValue = $_SERVER['HTTP_XXXXXX_XXXX'];


ELSE IF : vous exécutez PHP en tant que module Apache ou, à partir de PHP 5.4, en utilisant FastCGI (méthode simple):

apache_request_headers ()

<?php
$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}


ELSE: Dans tous les autres cas, vous pouvez utiliser (implémentation de l'espace utilisateur):

<?php
function getRequestHeaders() {
    $headers = array();
    foreach($_SERVER as $key => $value) {
        if (substr($key, 0, 5) <> 'HTTP_') {
            continue;
        }
        $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
        $headers[$header] = $value;
    }
    return $headers;
}

$headers = getRequestHeaders();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}


Voir aussi :
getallheaders () - (PHP> = 5.4) édition multiplateforme Alias ​​de apache_request_headers() apache_response_headers () - Récupère tous les en-têtes de réponse HTTP.
headers_list () - Récupère une liste des en-têtes à envoyer.


3
Je suppose que ce n'est que lors de l'utilisation du serveur Apache ... peut-être besoin de faire savoir à l'OP que :)
alex

12
Je me fiche de 82% des amateurs. Je me soucie des installations professionnelles. Personne dans un bon état d'esprit n'essaierait d'exécuter un site à fort trafic sur mod_php.
vartec

11
@Jacco Oui, et je pense que c'est une raison parfaite pour voter en aval. À tout moment, la meilleure réponse doit être votée positivement et les mauvaises réponses doivent être rétrogradées. Ce n'est pas un site de solutions historiques :-)
Thomas Jensen

3
@ThomasJensen Considérez cependant que certains pourraient être intéressants dans d'autres ou tous les en-têtes et pas spécialement dans 'HTTP_X_REQUESTED_WITH'; La réponse est absolument correcte et Jacco a déclaré explicitement que cela ne fonctionne que pour apache; Le fait que, dans certains scénarios, ce ne soit pas la solution la meilleure / la plus performante n'est pas une raison pour un IMO de downvote.
Sebastian Hoffmann

1
@Paranaix A: Je ne sais pas ce que vous voulez dire, je n'ai pas critiqué l'étendue de la réponse et votre raisonnement est exactement la raison pour laquelle j'ai commencé ma réponse en répondant à la question spécifique, puis élaboré avec des connaissances plus générales et des liens pour plus d'informations. . B: Je ne pense toujours pas que vous devriez encourager l'utilisation de apache_request_headers (). Les débutants qui trouvent cette question commenceront à l'utiliser, ce qui est dommage à l'OMI quand de meilleures fonctions existent.
Thomas Jensen

371
$_SERVER['HTTP_X_REQUESTED_WITH']

RFC3875 , 4.1.18:

Les méta-variables dont les noms commencent par HTTP_contiennent des valeurs lues dans les champs d'en-tête de demande client, si le protocole utilisé est HTTP. Le nom du champ d'en-tête HTTP est converti en majuscules, a toutes les occurrences de- remplacé par _et a été HTTP_ajouté au début pour donner le nom de la méta-variable.


6
Puis-je m'attendre de manière fiable à ce que n'importe quel serveur mette chaque en-tête dans la $_SERVERvariable? La documentation PHP à php.net/manual/en/reserved.variables.server.php est évasive sur ce que nous pouvons être sûrs qu'il y aura.
Mark Amery

4
Cela ne fonctionnera pas (toujours), surtout en PHP-fpm (ou cgi). Cet en-tête n'est pas toujours disponible depuis PHP.
Glenn Plas

En utilisant cette solution, je ne vois que certains en-têtes de demande, et dans ce cas, je ne vois pas celui que je veux. Chrome envoie un en- cache-controltête, mais je ne le vois nulle part $_SERVER. Je vois plusieurs en-têtes préfixés HTTP_, y compris "HTTP_ACCEPT" et "HTTP_UPGRADE_INSECURE_REQUESTS" et "HTTP_USER_AGENT" (parmi plusieurs autres). Mais rien pour "cache-control" rien pour "pragma". Ceci indépendamment de la casse ou du HTTP_préfixe. Suis-je en train de manquer quelque chose?
Evan de la Cruz

@EvandelaCruz: leserged.online.fr/phpinfo.php Je le vois ici:_SERVER["HTTP_CACHE_CONTROL"] max-age=0
Quassnoi

hmmm, merci ... C'est sur mon serveur de développement Wamp et je pense que PHP fonctionne comme un module Apache mais je ne suis pas sûr. Laissez-moi vérifier ma boîte de prod avec FPM et voir si je peux comprendre pourquoi je ne le vois pas ici sur wamp ...
Evan de la Cruz

48

Vous devriez trouver tous les en-têtes HTTP dans la $_SERVERvariable globale préfixée avec HTTP_majuscule et avec tirets (-) remplacés par des traits de soulignement (_).

Par exemple, vous X-Requested-Withpouvez le trouver dans:

$_SERVER['HTTP_X_REQUESTED_WITH']

Il peut être pratique de créer un tableau associatif à partir de la $_SERVERvariable. Cela peut être fait dans plusieurs styles, mais voici une fonction qui génère des clés en forme de chameau:

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

Maintenant, utilisez simplement $headers['XRequestedWith'] pour récupérer l'en-tête souhaité.

Manuel PHP sur $_SERVER: http://php.net/manual/en/reserved.variables.server.php


3
La meilleure réponse, à mon avis, est l'explication de Thomas avec le résultat final de Quassnoi. Un tableau associatif n'est généralement pas nécessaire, et il n'est pas très facile de trouver la solution simple en lisant la parseRequestHeaders()fonction. Si un tel tableau associatif est nécessaire, alors IMO, la fonction apache est la meilleure option, car elle retourne exactement les en-têtes reçus au lieu d'une version CamelCase déformée. (Notez également qu'à partir de PHP 5.4, il n'est plus uniquement Apache.)
Brilliand

Auriez-vous répondu plus rapidement 2 ans et 11 mois, cette réponse aurait plus de 200 votes positifs.
DividedByZero

apache_request_headers()ou getallheaders()ne semble pas mettre en majuscule les noms d'en-tête lorsque j'ai testé. Ils reviennent exactement comme je passe du côté client. Alors pourquoi capitalisez-vous les noms d'en-tête dans une telle fonction de remplacement?
rineez

22

Depuis PHP 5.4.0, vous pouvez utiliser une getallheadersfonction qui retourne tous les en-têtes de demande sous forme de tableau associatif:

var_dump(getallheaders());

// array(8) {
//   ["Accept"]=>
//   string(63) "text/html[...]"
//   ["Accept-Charset"]=>
//   string(31) "ISSO-8859-1[...]"
//   ["Accept-Encoding"]=>
//   string(17) "gzip,deflate,sdch"
//   ["Accept-Language"]=>
//   string(14) "en-US,en;q=0.8"
//   ["Cache-Control"]=>
//   string(9) "max-age=0"
//   ["Connection"]=>
//   string(10) "keep-alive"
//   ["Host"]=>
//   string(9) "localhost"
//   ["User-Agent"]=>
//   string(108) "Mozilla/5.0 (Windows NT 6.1; WOW64) [...]"
// }

Auparavant, cette fonction ne fonctionnait que lorsque PHP s'exécutait en tant que module Apache / NSAPI.


20
Je l'utilise sur PHP-FPM 5.5 et NGINX. getallheaders () n'existe pas.
CMCDragonkai

@CMCDragonkai dans FPM comment avez-vous obtenu les informations d'en-tête?
Ajit Singh

5

strtolowerfait défaut dans plusieurs des solutions proposées, la RFC2616 (HTTP / 1.1) définit les champs d'en-tête comme des entités insensibles à la casse. Le tout, pas seulement la partie valeur .

Par conséquent, des suggestions telles que l'analyse syntaxique des entrées HTTP_ sont fausses.

Mieux serait comme ça:

if (!function_exists('getallheaders')) {
    foreach ($_SERVER as $name => $value) {
        /* RFC2616 (HTTP/1.1) defines header fields as case-insensitive entities. */
        if (strtolower(substr($name, 0, 5)) == 'http_') {
            $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
        }
    }
    $this->request_headers = $headers;
} else {
    $this->request_headers = getallheaders();
}

Notez les différences subtiles avec les suggestions précédentes. La fonction ici fonctionne également sur php-fpm (+ nginx).


1
Où la RFC 2616 indique-t-elle exactement que les valeurs de champ ne respectent pas la casse? Il déclare explicitement que "la date HTTP est sensible à la casse" - et cela va dans l'en- Datetête - et que "les valeurs des paramètres [texte dans Content-Type après le point-virgule] peuvent ou non être sensibles à la casse". Donc, étant donné qu'il existe au moins deux en-têtes avec des valeurs sensibles à la casse, il semble que vous vous trompiez.
Joker_vD

HTTP header fields, which include general-header (section 4.5), request-header (section 5.3), response-header (section 6.2), and entity-header (section 7.1) fields, follow the same generic format as that given in Section 3.1 of RFC 822 [9]. Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive. Je suppose donc que vous vous trompez.
Glenn Plas

4
Les noms de champ ne respectent pas la casse. Il n'y a rien sur les valeurs de champ dans ce paragraphe, tandis que d'autres parties du document parlent explicitement des valeurs de champ sensibles à la casse.
Joker_vD

1
Pourquoi remplacez-vous tous le soulignement par l'espace puis l'espace par le tiret? cela ne fonctionnerait-il pas simplement: $ headers [ucwords (strtolower (substr ($ name, 5)))]] = $ value; ?
temirbek le

5

Passez un nom d'en-tête à cette fonction pour obtenir sa valeur sans utiliser de forboucle. Renvoie null si l'en-tête n'est pas trouvé.

/**
 * @var string $headerName case insensitive header name
 *
 * @return string|null header value or null if not found
 */
function get_header($headerName)
{
    $headers = getallheaders();
    return isset($headerName) ? $headers[$headerName] : null;
}

Remarque: cela ne fonctionne qu'avec le serveur Apache, voir: http://php.net/manual/en/function.getallheaders.php

Remarque: cette fonction traitera et chargera tous les en-têtes dans la mémoire et elle est moins performante qu'une forboucle.


la fonction a une erreur, remplacez $ pHeaderKey par $ headerKey
Tegos

4

Pour simplifier les choses, voici comment obtenir celle que vous souhaitez:

Facile:

$headerValue = $_SERVER['HTTP_X_REQUESTED_WITH'];

ou lorsque vous devez en obtenir un à la fois:

<?php
/**
 * @param $pHeaderKey
 * @return mixed
 */
function get_header( $pHeaderKey )
{
    // Expanded for clarity.
    $headerKey = str_replace('-', '_', $pHeaderKey);
    $headerKey = strtoupper($headerKey);
    $headerValue = NULL;
    // Uncomment the if when you do not want to throw an undefined index error.
    // I leave it out because I like my app to tell me when it can't find something I expect.
    //if ( array_key_exists($headerKey, $_SERVER) ) {
    $headerValue = $_SERVER[ $headerKey ];
    //}
    return $headerValue;
}
// X-Requested-With mainly used to identify Ajax requests. Most JavaScript frameworks
// send this header with value of XMLHttpRequest, so this will not always be present.
$header_x_requested_with = get_header( 'X-Requested-With' );

Les autres en-têtes sont également dans le tableau super global $ _SERVER, vous pouvez lire comment les obtenir ici: http://php.net/manual/en/reserved.variables.server.php


Par rapport à d'autres réponses, il semble que votre fonction ne fonctionnera pas car elle ne précède HTTP_pas le$headerKey
EECOLOR

3

J'utilisais CodeIgniter et j'ai utilisé le code ci-dessous pour l'obtenir. Peut être utile pour quelqu'un à l'avenir.

$this->input->get_request_header('X-Requested-With');

C'était. Je connaissais la méthode get_request_header (), mais je n'étais pas sûr de pouvoir utiliser le nom de l'en-tête tel quel, c'est-à-dire sans avoir à changer les tirets en traits de soulignement.
Valkay

Heureux que cela ait aidé. À votre santé.
Rajesh

1

Voici comment je le fais. Vous devez obtenir tous les en-têtes si $ header_name n'est pas transmis:

<?php
function getHeaders($header_name=null)
{
    $keys=array_keys($_SERVER);

    if(is_null($header_name)) {
            $headers=preg_grep("/^HTTP_(.*)/si", $keys);
    } else {
            $header_name_safe=str_replace("-", "_", strtoupper(preg_quote($header_name)));
            $headers=preg_grep("/^HTTP_${header_name_safe}$/si", $keys);
    }

    foreach($headers as $header) {
            if(is_null($header_name)){
                    $headervals[substr($header, 5)]=$_SERVER[$header];
            } else {
                    return $_SERVER[$header];
            }
    }

    return $headervals;
}
print_r(getHeaders());
echo "\n\n".getHeaders("Accept-Language");
?>

Cela me semble beaucoup plus simple que la plupart des exemples donnés dans d'autres réponses. Cela obtient également la méthode (GET / POST / etc.) Et l'URI demandés lors de l'obtention de tous les en-têtes, ce qui peut être utile si vous essayez de l'utiliser dans la journalisation.

Voici la sortie:

Array ( [HOST] => 127.0.0.1 [USER_AGENT] => Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0 [ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 [ACCEPT_LANGUAGE] => en-US,en;q=0.5 [ACCEPT_ENCODING] => gzip, deflate [COOKIE] => PHPSESSID=MySessionCookieHere [CONNECTION] => keep-alive )

en-US,en;q=0.5

0

Voici un moyen simple de le faire.

// echo get_header('X-Requested-With');
function get_header($field) {
    $headers = headers_list();
    foreach ($headers as $header) {
        list($key, $value) = preg_split('/:\s*/', $header);
        if ($key == $field)
            return $value;
    }
}

N'est-ce pas des en-têtes qui sont envoyés?
CMCDragonkai,

@CMCDragonkai No. "headers_list () renverra une liste des en-têtes à envoyer au navigateur / client" - php.net/manual/en/function.headers-list.php
kehers

2
Oui. C'est ce que je voulais dire.
CMCDragonkai

1
La question demande des en-têtes envoyés au serveur. Ce sont les en-têtes de demande.
CMCDragonkai

1
La source et la destination, lors de l'utilisation de termes tels que "envoyé", "sortant", "vers", "de", sont relatives au contexte dans lequel ces termes sont utilisés. Dans cette réponse, l'exemple montre PHP en cours d'exécution sur le serveur . Et, la question de l'OP faisait également référence à PHP côté serveur. Par conséquent, @CMCDragonkai et MichaelLeany sont corrects. Ceci est une mauvaise réponse. "envoyé", dans ce contexte, signifie "en-têtes de réponse HTTP envoyés depuis le serveur". Kehers commente du point de vue du client, mais sa réponse et la question du PO sont du point de vue du serveur.
Evan de la Cruz

0

Ce petit extrait PHP peut vous être utile:

<?php
foreach($_SERVER as $key => $value){
echo '$_SERVER["'.$key.'"] = '.$value."<br />";
}
?>

0
function getCustomHeaders()
{
    $headers = array();
    foreach($_SERVER as $key => $value)
    {
        if(preg_match("/^HTTP_X_/", $key))
            $headers[$key] = $value;
    }
    return $headers;
}

J'utilise cette fonction pour obtenir les en-têtes personnalisés, si l'en-tête commence à partir de "HTTP_X_" nous poussons dans le tableau :)


0

si une seule clé est requise pour être récupérée, par exemple une "Host"adresse est requise, alors nous pouvons utiliser

apache_request_headers()['Host']

Afin que nous puissions éviter les boucles et les mettre en ligne sur les sorties d'écho


À partir de PHP 5.4. Dans 5.3, cette syntaxe provoquera une erreur.
Robin K

ceci est testé avec PHP 7.1
Dickens AS

0

PHP 7: Opérateur Null Coalesce

//$http = 'SCRIPT_NAME';
$http = 'X_REQUESTED_WITH';
$http = strtoupper($http);
$header = $_SERVER['HTTP_'.$http] ?? $_SERVER[$http] ?? NULL;

if(is_null($header)){
    die($http. ' Not Found');
}
echo $header;

-1

Cela fonctionne si vous avez un serveur Apache

Code PHP:

$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}

Résultat:

Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: www.example.com
Connection: Keep-Alive
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.