【问题标题】:How do I read any request header in PHP如何在 PHP 中读取任何请求标头
【发布时间】:2010-10-07 04:28:21
【问题描述】:

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

例如自定义标头:X-Requested-With

【问题讨论】:

    标签: php http-headers


    【解决方案1】:

    IF:你只需要一个header,而不是all headers,最快的方法是:

    <?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:您将 PHP 作为 Apache 模块运行,或者从 PHP 5.4 开始,使用 FastCGI(简单方法):

    apache_request_headers()

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


    ELSE: 在任何其他情况下,您都可以使用(用户区实现):

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


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

    【讨论】:

    • 我认为这只是在使用 Apache 服务器时...可能需要让 OP 知道 :)
    • 我不在乎 82% 的业余爱好者。我关心专业的安装。没有人会尝试在 mod_php 上运行高流量网站。
    • @Jacco 是的,我认为这是投反对票的完美理由。在任何给定时间,最好的答案都应该被赞成,而糟糕的答案应该被反对。这不是历史解决方案的网站:-)
    • @ThomasJensen 考虑一下,有些人可能对其他或所有标头感兴趣,而不是特别是在“HTTP_X_REQUESTED_WITH”;答案是绝对正确的,Jacco 明确表示它只适用于 apache;在某些情况下,它不是最好/性能最好的解决方案,这不是对 IMO 投反对票的理由。
    • @Paranaix A:我不明白你的意思,我没有批评答案的程度,你的推理正是我为什么通过回答具体问题开始我的回答,然后详细说明更多一般知识和更多信息的链接。 B:我仍然认为您不应该鼓励使用 apache_request_headers()。发现这个问题的新手将开始使用它,当存在更好的功能时,这是 IMO 的耻辱。
    【解决方案2】:
    $_SERVER['HTTP_X_REQUESTED_WITH']
    

    RFC3875,4.1.18:

    如果使用的协议是 HTTP,则名称以 HTTP_ 开头的元变量包含从客户端请求标头字段读取的值。 HTTP 标头字段名称转换为大写字母,将所有出现的 - 替换为 _,并在前面添加 HTTP_ 以提供元变量名称。

    【讨论】:

    • 我可以可靠地期望任何服务器将每个标头放入$_SERVER 变量吗? php.net/manual/en/reserved.variables.server.php 的 PHP 文档对我们可以确定的内容回避了。
    • 这不会(总是)有效,尤其是在 PHP-fpm(或 cgi)中。此标头在 PHP 中并不总是可用。
    • 使用这个解决方案我只能看到一些请求头,在这种情况下,我看不到我想要的。 Chrome 正在发送一个cache-control 标头,但我在$_SERVER 的任何地方都看不到它。我确实看到了几个以HTTP_ 为前缀的标题,包括“HTTP_ACCEPT”、“HTTP_UPGRADE_INSECURE_REQUESTS”和“HTTP_USER_AGENT”(以及其他几个)。但是“缓存控制”没有任何内容,“pragma”也没有。这与大小写或 HTTP_ 前缀无关。我错过了什么吗?
    • @EvandelaCruz:leserged.online.fr/phpinfo.php 我在这里看到:_SERVER["HTTP_CACHE_CONTROL"] max-age=0
    • 嗯,谢谢...这是在我的 wamp 开发服务器上,我认为 PHP 作为 Apache 模块运行,但我不确定。让我用 FPM 检查我的 prod 框,看看我是否能弄清楚为什么我在 wamp 上看不到它...
    【解决方案3】:

    您应该会在 $_SERVER 全局变量中找到所有 HTTP 标头,其前缀为 HTTP_ 大写,破折号 (-) 替换为下划线 (_)。

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

    $_SERVER['HTTP_X_REQUESTED_WITH']
    

    $_SERVER 变量创建关联数组可能会很方便。这可以通过多种样式完成,但这里有一个输出驼峰键的函数:

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

    现在只需使用$headers['XRequestedWith'] 来检索所需的标头。

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

    【讨论】:

    • 在我看来,最好的答案是 Thomas 对 Quassnoi 最终结果的解释。通常不需要关联数组,并且通过读取parseRequestHeaders() 函数来找出简单的解决方案也不是很容易。如果需要这样的关联数组,那么 IMO apache 函数是最佳选择,因为它准确返回接收到的标头而不是损坏的 CamelCase 版本。 (另请注意,从 PHP 5.4 开始,它不再仅限 Apache。)
    • 你能快 2 年零 11 个月回答这个问题吗,这个答案会有 200 多票。
    • apache_request_headers()getallheaders() 在我测试时似乎没有大写标题名称。他们完全按照我从客户端经过的方式返回。那你为什么在这样的替换函数中将标题名称大写?
    【解决方案4】:

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

    之前此功能仅在 PHP 作为 Apache/NSAPI 模块运行时才有效。

    【讨论】:

    • 我在 PHP-FPM 5.5 和 NGINX 上使用它。 getallheaders() 不存在。
    • @CMCDragonkai 在 FPM 中你是如何获得标头信息的?
    • TLFTP;如果您正在使用 FPM getallheaders() 在 7.3 之后可用
    【解决方案5】:

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

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

    【讨论】:

    • 是的。虽然知道 get_request_header() 方法,但不确定我是否可以按原样使用标题名称,即不必将连字符更改为下划线。
    【解决方案6】:

    strtolower 缺少几个建议的解决方案,RFC2616 (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();
    }
    

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

    【讨论】:

    • RFC 2616 究竟在哪里声明字段值不区分大小写?它明确指出“HTTP-date 区分大小写” - 并且进入 Date 标头 - 并且“参数值 [分号后 Content-Type 中的文本] 可能区分大小写,也可能不区分大小写”。因此,鉴于至少有两个标头具有区分大小写的值,看来您错了。
    • 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. 所以我猜你错了。
    • 字段 names 不区分大小写。本段中没有关于字段 values 的内容,而文档的其他部分明确说明了区分大小写的字段值。
    • 为什么你们都将下划线替换为空格然后空格替换为破折号?这不就行了: $headers[ucwords(strtolower(substr($name, 5)))] = $value; ?
    【解决方案7】:

    在不使用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;
    }
    

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

    注意:此函数将处理所有的标头并将其加载到内存中,它的性能不如for 循环。

    【讨论】:

    • 函数有错误,将$pHeaderKey替换为$headerKey
    【解决方案8】:

    为简单起见,您可以通过以下方式获得您想要的:

    简单:

    $headerValue = $_SERVER['HTTP_X_REQUESTED_WITH'];
    

    或者当您需要一次获得一个时:

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

    其他标头也在超级全局数组 $_SERVER 中,您可以在此处阅读有关如何获取它们的信息:http://php.net/manual/en/reserved.variables.server.php

    【讨论】:

    • 与其他答案相比,您的功能似乎无法正常工作,因为它没有将HTTP_ 预先添加到$headerKey
    【解决方案9】:

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

    apache_request_headers()['Host']
    

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

    【讨论】:

    • 从 PHP 5.4 开始。在 5.3 中,这种语法会导致错误。
    • 这是用 PHP 7.1 测试的
    【解决方案10】:

    这就是我的做法。如果 $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");
    ?>
    

    在我看来,它比其他答案中给出的大多数示例要简单得多。这还会获取方法(GET/POST/etc.)和获取所有标头时请求的 URI,如果您尝试在日志记录中使用它,这可能很有用。

    这是输出:

    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
    

    【讨论】:

      【解决方案11】:

      PHP 7:空合并运算符

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

      【讨论】:

        【解决方案12】:

        这是一个简单的方法。

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

        【讨论】:

        • 发送出去的不是headers吗?
        • @CMCDragonkai No. "headers_list() 将返回要发送到浏览器/客户端的标头列表" - php.net/manual/en/function.headers-list.php
        • 是的。我就是这个意思。
        • 问题是要求发送到服务器的标头。它们是请求标头。
        • 源和目的地在使用“sent”、“out”、“to”、“from”等术语时,与使用这些术语的上下文相关。在这个答案中,示例显示 PHP 在 服务器 上运行。而且,OP 的问题还引用了服务器端 PHP。因此,@CMCDragonkai 和 MichaelLeany 是正确的。这是一个糟糕的答案。在这种情况下,“发送出去”是指“从服务器发送的 HTTP 响应标头”。 kehers 是从客户端的角度发表评论,但他的回答和 OP 的问题都是从服务器的角度来看的。
        【解决方案13】:

        这个小小的 PHP sn-p 对你有帮助:

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

        【讨论】:

          【解决方案14】:
          function getCustomHeaders()
          {
              $headers = array();
              foreach($_SERVER as $key => $value)
              {
                  if(preg_match("/^HTTP_X_/", $key))
                      $headers[$key] = $value;
              }
              return $headers;
          }
          

          我使用这个函数来获取自定义标头,如果标头从“HTTP_X_”开始,我们将推入数组:)

          【讨论】:

            【解决方案15】:

            如果你有一个 Apache 服务器就可以了

            PHP 代码:

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

            结果:

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

            【讨论】:

              猜你喜欢
              • 2021-01-02
              • 1970-01-01
              • 2021-10-07
              • 2013-11-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多