¿Cómo leo cualquier encabezado de solicitud en PHP?

271

¿Cómo debo leer cualquier encabezado en PHP?

Por ejemplo la costumbre de cabecera: X-Requested-With.

Sabya
fuente

Respuestas:

345

SI : solo necesita un solo encabezado, en lugar de todos los encabezados, el método más rápido es:

<?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 : ejecuta PHP como un módulo de Apache o, a partir de PHP 5.4, utilizando FastCGI (método simple):

apache_request_headers ()

<?php
$headers = apache_request_headers();

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


ELSE: En cualquier otro caso, puede usar (implementación de usuario):

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


Consulte también :
getallheaders () - (PHP> = 5.4) edición multiplataforma Alias ​​de apache_request_headers() apache_response_headers () - Obtenga todos los encabezados de respuesta HTTP.
headers_list () - Obtiene una lista de encabezados para enviar.

Jacco
fuente
3
Asumo que esto es sólo cuando se utiliza el servidor Apache ... podría tener que dejar que el saber que OP :)
Alex
12
No me importa el 82% de los aficionados. Me importan las instalaciones profesionales. Nadie en el estado mental correcto trataría de ejecutar un sitio de alto tráfico en mod_php.
vartec
11
@Jacco Sí, y creo que eso es una razón perfecta para votar a favor. En cualquier momento dado, la mejor respuesta debe ser votada hacia arriba y las malas respuestas rechazadas. Este no es un sitio de soluciones históricas :-)
Thomas Jensen
3
@ThomasJensen Tenga en cuenta, sin embargo, que algunos podrían estar interesados ​​en otros o todos los encabezados y no especialmente en 'HTTP_X_REQUESTED_WITH'; La respuesta es absolutamente correcta y Jacco declaró explícitamente que solo funciona para apache; Que, en algunos escenarios, no sea la mejor / mejor solución no es motivo para rechazar una OMI.
Sebastian Hoffmann
1
@Paranaix A: No sé a qué te refieres, no he criticado el alcance de la respuesta y tu razonamiento es exactamente por qué comencé mi respuesta respondiendo la pregunta específica y luego elaboré con conocimientos más generales y enlaces para obtener más información. . B: Todavía no creo que debas alentar el uso de apache_request_headers (). Los novatos que encuentren esta pregunta comenzarán a usarla, lo cual es una pena IMO cuando existen mejores funciones.
Thomas Jensen el
371
$_SERVER['HTTP_X_REQUESTED_WITH']

RFC3875 , 4.1.18:

Las metavariables con nombres que comienzan con HTTP_contienen valores leídos de los campos de encabezado de solicitud del cliente, si el protocolo utilizado es HTTP. El nombre del campo del encabezado HTTP se convierte en mayúsculas, se -reemplaza por todas las apariciones _y se HTTP_antepone para dar el nombre de la meta-variable.

Quassnoi
fuente
66
¿Puedo esperar de manera confiable que cualquier servidor ponga cada encabezado en la $_SERVERvariable? La documentación de PHP en php.net/manual/en/reserved.variables.server.php es evasiva sobre lo que podemos estar seguros de que estará allí.
Mark Amery
44
Esto no funcionará (siempre), especialmente en PHP-fpm (o cgi). Este encabezado no siempre está disponible desde PHP.
Glenn Plas
Al usar esta solución, solo veo algunos de los encabezados de solicitud y, en este caso, no veo el que quiero. Chrome está enviando un cache-controlencabezado, pero no lo veo en ningún lado $_SERVER. Veo varios encabezados con el prefijo HTTP_, incluidos "HTTP_ACCEPT", y "HTTP_UPGRADE_INSECURE_REQUESTS" y "HTTP_USER_AGENT" (entre otros). Pero nada para "control de caché" tampoco para "pragma". Esto es independientemente del caso o HTTP_prefijo. ¿Me estoy perdiendo de algo?
Evan de la Cruz
@EvandelaCruz: leserged.online.fr/phpinfo.php Lo veo aquí:_SERVER["HTTP_CACHE_CONTROL"] max-age=0
Quassnoi
hmmm, gracias ... Esto está en mi servidor de desarrollo de wamp y creo que PHP se está ejecutando como un módulo de Apache, pero no estoy seguro. Permítanme revisar mi caja de productos con FPM y ver si puedo entender por qué no lo veo aquí en wamp ...
Evan de la Cruz
48

Debería encontrar todos los encabezados HTTP en la $_SERVERvariable global con el prefijo en HTTP_mayúsculas y con guiones (-) reemplazados por guiones bajos (_).

Por ejemplo, X-Requested-Withse puede encontrar en:

$_SERVER['HTTP_X_REQUESTED_WITH']

Puede ser conveniente crear una matriz asociativa a partir de la $_SERVERvariable. Esto se puede hacer en varios estilos, pero aquí hay una función que genera teclas en camello:

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

Ahora solo use $headers['XRequestedWith']para recuperar el encabezado deseado.

Manual de PHP en $_SERVER: http://php.net/manual/en/reserved.variables.server.php

Thomas Jensen
fuente
3
La mejor respuesta, en mi opinión, es la explicación de Thomas con el resultado final de Quassnoi. Una matriz asociativa generalmente no es lo que se necesita, y no es muy fácil encontrar la solución simple leyendo la parseRequestHeaders()función. Si se necesita dicha matriz asociativa, entonces IMO la función apache es la mejor opción, ya que devuelve exactamente los encabezados recibidos en lugar de una versión de CamelCase destrozada. (También tenga en cuenta que a partir de PHP 5.4, ya no es solo Apache.)
Brilliand
Si hubiera respondido esto 2 años y 11 meses más rápido, esta respuesta tendría más de 200 votos a favor.
DividedByZero
apache_request_headers()o getallheaders()no parece poner en mayúscula los nombres de encabezado cuando lo probé. Están regresando exactamente cuando paso del lado del cliente. Entonces, ¿por qué está capitalizando los nombres de encabezado en una función de reemplazo?
rineez
22

Desde PHP 5.4.0 puede usar la getallheadersfunción que devuelve todos los encabezados de solicitud como una matriz asociativa:

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

Anteriormente, esta función solo funcionaba cuando PHP se ejecutaba como un módulo Apache / NSAPI.

Salman A
fuente
20
Lo estoy usando en PHP-FPM 5.5 y NGINX. getallheaders () no existe.
CMCDragonkai
@CMCDragonkai en FPM, ¿cómo obtuviste la información del encabezado?
Ajit Singh
5

strtolowerfalta en varias de las soluciones propuestas, RFC2616 (HTTP / 1.1) define los campos de encabezado como entidades que no distinguen entre mayúsculas y minúsculas. Todo, no solo la parte del valor .

Por lo tanto, sugerencias como solo analizar entradas HTTP_ son incorrectas.

Mejor sería así:

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

Observe las diferencias sutiles con las sugerencias anteriores. La función aquí también funciona en php-fpm (+ nginx).

Glenn Plas
fuente
1
¿Dónde dice exactamente RFC 2616 que los valores de campo no distinguen entre mayúsculas y minúsculas? Explica explícitamente que "la fecha HTTP distingue entre mayúsculas y minúsculas", y eso va dentro del Dateencabezado, y que "los valores de los parámetros [texto en Tipo de contenido después del punto y coma] pueden o no distinguen entre mayúsculas y minúsculas". Entonces, dado que hay al menos dos encabezados con valores que distinguen entre mayúsculas y minúsculas, parece que estás equivocado.
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. Entonces supongo que te equivocas.
Glenn Plas
44
Los nombres de campo no distinguen entre mayúsculas y minúsculas. No hay nada sobre los valores de campo en este párrafo, mientras que otras partes del documento hablan explícitamente sobre valores de campo sensibles a mayúsculas y minúsculas.
Joker_vD
1
¿Por qué todos reemplazan subrayado al espacio y luego espacio al guión? ¿no funcionaría esto: $ headers [ucwords (strtolower (substr ($ name, 5)))] = $ value; ?
temirbek
5

Pase un nombre de encabezado a esta función para obtener su valor sin usar el forbucle. Devuelve nulo si no se encuentra el encabezado.

/**
 * @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: esto solo funciona con el servidor Apache, consulte: http://php.net/manual/en/function.getallheaders.php

Nota: esta función procesará y cargará todos los encabezados en la memoria y es menos eficaz que un forbucle.

Milap Kundalia
fuente
tiene la función de error, sustituya $ pHeaderKey a $ headerKey
Tegos
4

Para simplificar las cosas, así es como puede obtener lo que desea:

Sencillo:

$headerValue = $_SERVER['HTTP_X_REQUESTED_WITH'];

o cuando necesita obtener uno a la vez:

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

Los otros encabezados también están en la matriz súper global $ _SERVER, puede leer acerca de cómo obtenerlos aquí: http://php.net/manual/en/reserved.variables.server.php

b01
fuente
En comparación con otras respuestas, parece que su función no funcionará, ya que no antecede HTTP_a la$headerKey
EECOLOR
3

Estaba usando CodeIgniter y usé el siguiente código para obtenerlo. Puede ser útil para alguien en el futuro.

$this->input->get_request_header('X-Requested-With');
Rajesh
fuente
Era. Sin embargo, sabía sobre el método get_request_header (), pero no estaba seguro de poder usar el nombre del encabezado tal cual, es decir, sin tener que cambiar los guiones a guiones bajos.
Valkay
Me alegra que haya ayudado. Salud.
Rajesh
1

Así es como lo estoy haciendo. Debe obtener todos los encabezados si no se pasa $ header_name:

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

Me parece mucho más simple que la mayoría de los ejemplos dados en otras respuestas. Esto también obtiene el método (GET / POST / etc.) Y el URI solicitado al obtener todos los encabezados que pueden ser útiles si está tratando de usarlo en el registro.

Aquí está el resultado:

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
Jonnycake
fuente
0

Aquí hay una manera fácil de hacerlo.

// 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;
    }
}
Kehers
fuente
¿No son los encabezados que se envían?
CMCDragonkai
@CMCDragonkai No. "headers_list () devolverá una lista de encabezados que se enviarán al navegador / cliente" - php.net/manual/en/function.headers-list.php
kehers
2
Sí. A eso me refería.
CMCDragonkai
1
La pregunta es pedir encabezados enviados al servidor. Son los encabezados de solicitud.
CMCDragonkai
1
El origen y el destino, cuando se usan términos como "enviado", "fuera", "a", "desde", es relativo al contexto en el que se usan esos términos. En esta respuesta, el ejemplo muestra PHP ejecutándose en el servidor . Y, la pregunta del OP también hacía referencia a PHP del lado del servidor. Por lo tanto, @CMCDragonkai y MichaelLeany son correctos. Esta es una mala respuesta. "enviado", en este contexto, significa "encabezados de respuesta HTTP enviados desde el servidor". Kehers está comentando desde el punto de vista del cliente, pero tanto su respuesta como la pregunta del OP son desde el punto de vista del servidor.
Evan de la Cruz
0

Este pequeño fragmento de PHP puede serle útil:

<?php
foreach($_SERVER as $key => $value){
echo '$_SERVER["'.$key.'"] = '.$value."<br />";
}
?>
Technolust
fuente
0
function getCustomHeaders()
{
    $headers = array();
    foreach($_SERVER as $key => $value)
    {
        if(preg_match("/^HTTP_X_/", $key))
            $headers[$key] = $value;
    }
    return $headers;
}

Utilizo esta función para obtener los encabezados personalizados, si el encabezado comienza desde "HTTP_X_", insertamos la matriz :)

ZiTAL
fuente
0

si solo se requiere una clave para recuperarla, por ejemplo "Host", se requiere una dirección, entonces podemos usar

apache_request_headers()['Host']

Para que podamos evitar bucles y ponerlo en línea a las salidas de eco

Dickens AS
fuente
Comenzando con PHP 5.4. En 5.3, esta sintaxis causará un error.
Robin K
esto se prueba con PHP 7.1
Dickens AS
0

PHP 7: Operador de fusión nula

//$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;
Andamio
fuente
-1

Esto funciona si tienes un servidor Apache

Código PHP:

$headers = apache_request_headers();

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

Resultado:

Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: www.example.com
Connection: Keep-Alive
Emanuel Nogueiras
fuente