Come faccio a leggere qualsiasi intestazione di richiesta in PHP


271

Come devo leggere qualsiasi intestazione in PHP?

Per esempio intestazione la consuetudine: X-Requested-With.

Risposte:


345

IF : è necessaria un'unica intestazione, anziché tutte le intestazioni, il metodo più rapido è:

<?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 : esegui PHP come modulo Apache o, a partire da PHP 5.4, usando FastCGI (metodo semplice):

apache_request_headers ()

<?php
$headers = apache_request_headers();

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


ELSE: in qualsiasi altro caso, è possibile utilizzare (implementazione userland):

<?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";
}


Vedi anche :
getallheaders () - (PHP> = 5.4) cross platform edition Alias ​​di apache_request_headers() apache_response_headers () - Scarica tutte le intestazioni di risposta HTTP.
headers_list () - Recupera un elenco di intestazioni da inviare.


3
Suppongo che ciò avvenga solo quando si utilizza il server Apache ... potrebbe essere necessario che l'OP lo sappia :)
alex

12
Non mi interessa circa l'82% dei dilettanti. Mi occupo delle installazioni professionali. Nessuno nel giusto stato d'animo cercherebbe di eseguire il sito ad alto traffico su mod_php.
Vartec,

11
@Jacco Sì, e penso che sia un motivo perfetto per il downvoting. In qualsiasi momento la migliore risposta dovrebbe essere votata e le cattive risposte ridotte. Questo non è un sito di soluzioni storiche :-)
Thomas Jensen,

3
@ThomasJensen Considera però che alcuni potrebbero essere interessati ad altre o tutte le intestazioni e non soprattutto a "HTTP_X_REQUESTED_WITH"; La risposta è assolutamente corretta e Jacco ha dichiarato esplicitamente che funziona solo per Apache; Che in alcuni scenari non sia la soluzione migliore / più performante non è un motivo per un IMO downvote.
Sebastian Hoffmann,

1
@Paranaix A: Non so cosa intendi, non ho criticato l'entità della risposta e il tuo ragionamento è esattamente il motivo per cui ho iniziato la mia risposta rispondendo alla domanda specifica e quindi elaborato con conoscenze e collegamenti più generali per ulteriori informazioni . B: Continuo a non pensare che dovresti incoraggiare l'uso di apache_request_headers (). I principianti che trovano questa domanda inizieranno a usarla, il che è un peccato IMO quando esistono funzioni migliori.
Thomas Jensen,

371
$_SERVER['HTTP_X_REQUESTED_WITH']

RFC3875 , 4.1.18:

Le meta-variabili con nomi che iniziano con HTTP_contengono valori letti dai campi di intestazione della richiesta client, se il protocollo utilizzato è HTTP. Il nome del campo dell'intestazione HTTP viene convertito in lettere maiuscole, tutte le occorrenze sono state -sostituite con _e ha HTTP_anteposto a dare il nome della meta-variabile.


6
Posso aspettarmi in modo affidabile che qualsiasi server inserisca tutte le intestazioni nella $_SERVERvariabile? La documentazione di PHP su php.net/manual/en/reserved.variables.server.php è evasiva su ciò di cui possiamo essere certi che ci sarà.
Mark Amery,

4
Questo non funzionerà (sempre), specialmente in PHP-fpm (o cgi). Questa intestazione non è sempre disponibile da PHP.
Glenn Plas,

Utilizzando questa soluzione vedo solo alcune delle intestazioni delle richieste e, in questo caso, non vedo quello che voglio. Chrome sta inviando cache-controlun'intestazione, ma non la vedo da nessuna parte $_SERVER. Vedo il prefisso di diverse intestazioni HTTP_, tra cui "HTTP_ACCEPT" e "HTTP_UPGRADE_INSECURE_REQUESTS" e "HTTP_USER_AGENT" (tra molti altri). Ma niente per "controllo della cache" e niente per "pragma". Questo indipendentemente dal caso o dal HTTP_prefisso. Mi sto perdendo qualcosa?
Evan de la Cruz,

@EvandelaCruz: leserged.online.fr/phpinfo.php Lo vedo qui:_SERVER["HTTP_CACHE_CONTROL"] max-age=0
Quassnoi

hmmm, grazie ... Questo è sul mio server Wamp Dev e penso che PHP sia in esecuzione come modulo Apache ma non ne sono sicuro. Fammi controllare sulla mia cassetta dei prodotti con FPM e vedere se riesco a capire perché non lo vedo qui su Wamp ...
Evan de la Cruz

48

Dovresti trovare tutte le intestazioni HTTP nella $_SERVERvariabile globale con prefisso HTTP_maiuscolo e trattini (-) sostituiti da caratteri di sottolineatura (_).

Ad esempio, X-Requested-Withpuoi trovarlo in:

$_SERVER['HTTP_X_REQUESTED_WITH']

Potrebbe essere conveniente creare un array associativo dalla $_SERVERvariabile. Questo può essere fatto in diversi stili, ma ecco una funzione che emette i tasti camelcased:

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

Ora basta usare $headers['XRequestedWith']per recuperare l'intestazione desiderata.

Manuale di PHP su $_SERVER: http://php.net/manual/en/reserved.variables.server.php


3
La migliore risposta, secondo me, è la spiegazione di Thomas con il risultato finale di Quassnoi. Un array associativo di solito non è ciò che è necessario e non è molto semplice elaborare la soluzione semplice leggendo la parseRequestHeaders()funzione. Se è necessario un tale array associativo, allora IMO la funzione apache è l'opzione migliore, poiché restituisce esattamente le intestazioni ricevute anziché una versione CamelCase alterata. (Si noti inoltre che a partire da PHP 5.4, non è più solo Apache.)
Brilliand,

Avresti risposto più velocemente di 2 anni e 11 mesi, con una risposta di oltre 200 voti.
DividedByZero

apache_request_headers()o getallheaders()non sembra scrivere in maiuscolo i nomi delle intestazioni quando ho provato. Stanno tornando esattamente mentre passo dal lato client. Allora perché stai capitalizzando i nomi delle intestazioni in una tale funzione di sostituzione?
rineez,

22

Da PHP 5.4.0 è possibile utilizzare la getallheadersfunzione che restituisce tutte le intestazioni di richiesta come un array associativo:

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) [...]"
// }

In precedenza questa funzione funzionava solo quando PHP era in esecuzione come modulo Apache / NSAPI.


20
Lo sto usando su PHP-FPM 5.5 e NGINX. getallheaders () non esiste.
CMCDragonkai,

@CMCDragonkai in FPM come hai ottenuto le informazioni di intestazione?
Ajit Singh,

5

strtolowermanca in molte delle soluzioni proposte, RFC2616 (HTTP / 1.1) definisce i campi di intestazione come entità senza distinzione tra maiuscole e minuscole. Il tutto, non solo la parte di valore .

Quindi suggerimenti come solo l'analisi delle voci HTTP_ sono errati.

Meglio sarebbe così:

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();
}

Notare le sottili differenze con i suggerimenti precedenti. La funzione qui funziona anche su php-fpm (+ nginx).


1
Dove esattamente RFC 2616 afferma che i valori di campo non fanno distinzione tra maiuscole e minuscole? Spiega esplicitamente che "La data HTTP fa distinzione tra maiuscole e minuscole" - e questo va Datenell'intestazione - e che "I valori dei parametri [testo in Content-Type dopo il punto e virgola] potrebbero o no essere sensibili alla distinzione tra maiuscole e minuscole". Quindi, dato che ci sono almeno due intestazioni con valori sensibili al maiuscolo / minuscolo, sembra che ti sbagli.
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. Quindi immagino tu abbia torto.
Glenn Plas,

4
I nomi dei campi non fanno distinzione tra maiuscole e minuscole. Non vi è nulla sui valori dei campi in questo paragrafo, mentre altre parti del documento parlano esplicitamente dei valori dei campi sensibili al maiuscolo / minuscolo.
Joker_vD,

1
Perché tutti sostituite la sottolineatura con lo spazio e poi lo spazio con il trattino? questo non funzionerebbe: $ headers [ucwords (strtolower (substr ($ name, 5)))] = $ value; ?
temirbek

5

Passa un nome di intestazione a questa funzione per ottenere il suo valore senza usare il forciclo. Restituisce null se l'intestazione non è stata trovata.

/**
 * @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;
}

Nota: funziona solo con il server Apache, consultare: http://php.net/manual/en/function.getallheaders.php

Nota: questa funzione elaborerà e caricherà tutte le intestazioni in memoria ed è meno performante di un forloop.


la funzione ha un errore, sostituire $ pHeaderKey a $ headerKey
Tegos

4

Per semplificare le cose, ecco come puoi ottenere solo quello che desideri:

Semplice:

$headerValue = $_SERVER['HTTP_X_REQUESTED_WITH'];

o quando è necessario ottenerne uno alla volta:

<?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' );

Le altre intestazioni sono anche nell'array super globale $ _SERVER, puoi leggere come ottenerle qui: http://php.net/manual/en/reserved.variables.server.php


Rispetto ad altre risposte sembra che la tua funzione non funzioni in quanto non HTTP_$headerKey
anteposta

3

Stavo usando CodeIgniter e ho usato il codice qui sotto per ottenerlo. Potrebbe essere utile per qualcuno in futuro.

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

Era. Conoscevo il metodo get_request_header (), ma non ero sicuro di poter usare il nome dell'intestazione così com'è, cioè senza dover cambiare trattini in caratteri di sottolineatura.
Valkay,

Sono contento che abbia aiutato. Saluti.
Rajesh,

1

Ecco come lo sto facendo. Devi ottenere tutte le intestazioni se $ header_name non viene passato:

<?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");
?>

Mi sembra molto più semplice della maggior parte degli esempi forniti in altre risposte. Questo ottiene anche il metodo (GET / POST / ecc.) E l'URI richiesto quando si ottengono tutte le intestazioni che possono essere utili se si sta tentando di usarlo nella registrazione.

Ecco l'output:

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

Ecco un modo semplice per farlo.

// 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;
    }
}

Quelle intestazioni non vengono spedite?
CMCDragonkai

@CMCDragonkai No. "headers_list () restituirà un elenco di intestazioni da inviare al browser / cliente" - php.net/manual/en/function.headers-list.php
kehers

2
Sì. Ecco cosa intendevo.
CMCDragonkai,

1
La domanda è chiedere intestazioni inviate al server. Sono le intestazioni della richiesta.
CMCDragonkai,

1
La fonte e la destinazione, quando si usano termini come "inviato", "fuori", "a", "da", sono relativi al contesto in cui vengono usati quei termini. In questa risposta, l'esempio mostra PHP in esecuzione sul server . Inoltre, la domanda dell'OP faceva riferimento anche a PHP lato server. Pertanto, @CMCDragonkai e MichaelLeany sono corretti. Questa è una cattiva risposta "inviato", in questo contesto, significa "intestazioni di risposta HTTP inviate dal server". kehers sta commentando dal punto di vista del client, ma sia la sua risposta che la domanda del PO sono dal punto di vista del server.
Evan de la Cruz,

0

Questo piccolo frammento di PHP può esserti 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;
}

Uso questa funzione per ottenere le intestazioni personalizzate, se l'intestazione inizia da "HTTP_X_" inseriamo l'array :)


0

se è necessario recuperare una sola chiave, ad esempio "Host"è richiesto l'indirizzo, quindi possiamo usare

apache_request_headers()['Host']

In modo che possiamo evitare i loop e metterlo in linea con gli output dell'eco


A partire da PHP 5.4. In 5.3, questa sintassi causerà un errore.
Robin K,

questo è testato con PHP 7.1
Dickens AS

0

PHP 7: Null Coalesce Operator

//$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

Questo funziona se hai un server Apache

Codice PHP:

$headers = apache_request_headers();

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

Risultato:

Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: www.example.com
Connection: Keep-Alive
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.