如何在PHP中读取任何请求标头

Sab*_*bya 249 php http-headers

我应该如何阅读PHP中的任何标题?

例如自定义标题:X-Requested-With.

Qua*_*noi 359

$_SERVER['HTTP_X_REQUESTED_WITH']
Run Code Online (Sandbox Code Playgroud)

RFC3875,4.1.18:

HTTP_如果使用的协议是HTTP,则名称以包含值的元变量从客户端请求头字段读取.HTTP标头字段名称转换为大写,所有出现的-替换为,_并且已经HTTP_预先赋予元变量名称.

  • 我可以可靠地期望任何服务器将每个头放入`$ _SERVER`变量吗?http://php.net/manual/en/reserved.variables.server.php上的PHP文档回避了我们可以确定的内容. (6认同)
  • 这不会(总是)起作用,特别是在PHP-fpm(或cgi)中.PHP中并不总是可以使用此标头. (4认同)

Jac*_*cco 309

IF:您只需要一个标题,而不是所有标题,最快的方法是:

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


ELSE IF:您将PHP作为Apache模块运行,或者从PHP 5.4开始,使用FastCGI(简单方法):

apache_request_headers()

<?php
$headers = apache_request_headers();

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


ELSE:在任何其他情况下,您都可以使用(userland implementation):

<?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";
}
Run Code Online (Sandbox Code Playgroud)


另请参阅:
getallheaders() - (PHP> = 5.4)跨平台版本apache_request_headers() apache_response_headers()的别名- 获取所有HTTP响应头.
headers_list() - 获取要发送的标头列表.

  • 我不关心82%的业余爱好者.我关心专业装置.没有人处于正确的心态会尝试在mod_php上运行高流量站点. (9认同)
  • @Jacco是的,我认为这是完美的理由.在任何给定的时间,最好的答案应该被投票,而坏的答案应该被低估.这不是历史解决方案的网站:-) (9认同)
  • 我假设这只是在使用Apache服务器时...可能需要让OP知道:) (3认同)
  • @ThomasJensen考虑一下,有些可能在其他或所有标题中被强制插入,而不是特别在'HTTP_X_REQUESTED_WITH'中; 回答是绝对正确的,Jacco明确表示它只适用于apache; 它在某些情况下不是最佳/最佳性能的解决方案是没有理由进行downvote IMO. (3认同)
  • 对于下注者...请记住,这个问题在2009年得到了回答 (2认同)
  • @Paranaix A:我不知道你的意思,我没有批评答案的范围,你的推理正是为什么我通过回答具体问题来开始我的答案,然后用更一般的知识和更多信息的链接进行阐述。B:我仍然认为你不应该鼓励使用 apache_request_headers()。发现这个问题的新手将开始使用它,当存在更好的功能时,这在我看来是一种耻辱。 (2认同)
  • 您只扫描大写的 HTML,这是错误的,RFC2616 (HTTP/1.1) 声明标头不区分大小写,而不仅仅是您所涵盖的值部分。标头名称也可以全部小写。 (2认同)

Tho*_*sen 46

您应该在$_SERVER全局变量中找到所有HTTP标头,前缀为HTTP_大写字母,短划线( - )替换为下划线(_).

例如,您X-Requested-With可以在以下位置找到:

$_SERVER['HTTP_X_REQUESTED_WITH']
Run Code Online (Sandbox Code Playgroud)

$_SERVER变量创建关联数组可能很方便.这可以用几种样式完成,但这是一个输出camelcased键的函数:

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

现在只需用于$headers['XRequestedWith']检索所需的标题.

PHP手册$_SERVER:http://php.net/manual/en/reserved.variables.server.php

  • 在我看来,最好的答案是托马斯对Quassnoi最终结果的解释.关联数组通常不是所需要的,并且通过读取`parseRequestHeaders()`函数来计算简单的解决方案并不容易.如果需要这样的关联数组,那么IMO apache函数是最好的选择,因为它确切地返回收到的头而不是一个受损的CamelCase版本.(另请注意,从PHP 5.4开始,它不再仅限Apache.) (3认同)

Sal*_*n A 20

从PHP 5.4.0开始,您可以使用getallheaders将所有请求标头作为关联数组返回的函数:

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) [...]"
// }
Run Code Online (Sandbox Code Playgroud)

之前,此功能仅在PHP作为Apache/NSAPI模块运行时才起作用.

  • 我在PHP-FPM 5.5和NGINX上使用它.getallheaders()不存在. (18认同)

Dic*_*A S 6

如果只需要检索一个密钥,例如"Host"需要地址,那么我们可以使用

apache_request_headers()['Host']
Run Code Online (Sandbox Code Playgroud)

这样我们就可以避免循环并将其内联到回显输出


Gle*_*las 5

strtolowerRFC2616(HTTP/1.1)缺少若干提议的解决方案,将头字段定义为不区分大小写的实体.整个事情,不仅仅是价值部分.

因此,仅解析HTTP_条目的建议是错误的.

更好的是这样的:

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();
}
Run Code Online (Sandbox Code Playgroud)

请注意与先前建议的细微差别.这里的函数也适用于php-fpm(+ nginx).

  • 字段*名称*不区分大小写.本段中没有关于字段*值*的内容,而文档的其他部分明确说明了区分大小写的字段值. (3认同)

Mil*_*lia 5

将标题名称传递给此函数以获取其值而不使用for循环.如果未找到标头,则返回null.

/**
 * @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;
}
Run Code Online (Sandbox Code Playgroud)

注意:这仅适用于Apache服务器,请参阅:http://php.net/manual/en/function.getallheaders.php

注意:此函数将处理并将所有标头加载到内存中,并且它的性能低于for循环.


Raj*_*esh 5

我正在使用 CodeIgniter 并使用下面的代码来获取它。将来可能对某人有用。

$this->input->get_request_header('X-Requested-With');
Run Code Online (Sandbox Code Playgroud)