如何在PHP中解析响应头?

如何在PHP中解析响应头?,php,api,rest,http-headers,Php,Api,Rest,Http Headers,我向REST API发出了一个oauth签名请求,并将响应头放在如下数组中: [0] => HTTP/1.1 200 OK [1] => Cache-Control: private [2] => Transfer-Encoding: chunked [3] => Content-Type: text/html; charset=utf-8 [4] => Content-Location: https://*** [5] => Server: Microsof

我向REST API发出了一个oauth签名请求,并将响应头放在如下数组中:

[0] => HTTP/1.1 200 OK
[1] => Cache-Control: private
[2] => Transfer-Encoding: chunked
[3] => Content-Type: text/html; charset=utf-8
[4] => Content-Location: https://***
[5] => Server: Microsoft-IIS/7.0
[6] => Set-Cookie: ASP.NET_SessionId=***; path=/; HttpOnly
[7] => X-AspNetMvc-Version: 2.0
[8] => oauth_token: ***
[9] => oauth_token_secret: ***
[10] => X-AspNet-Version: 4.0.30319
[11] => X-Powered-By: ASP.NET
[12] => Date: Sat, 15 Sep 2012 02:01:15 GMT

我正在试图找出如何解析头以便轻松检索项目,如HTTP状态码、内容位置、oauth_令牌和oauth_令牌密钥?

您需要迭代数组并检查
stripos()
,以找到要查找的头。在大多数情况下,您将在
上执行
分解()
(限制为两个结果部分),但HTTP响应代码将要求您在空格上进行分解

// Get any header except the HTTP response...
function getResponseHeader($header, $response) {
  foreach ($response as $key => $r) {
     // Match the header name up to ':', compare lower case
     if (stripos($r, $header . ':') === 0) {
        list($headername, $headervalue) = explode(":", $r, 2);
        return trim($headervalue);
     }
  }
}
// example:
echo getResponseHeader("Content-Type");
// text/html; charset=utf-8

// Get the HTTP response code
foreach ($response as $key => $r) {
  if (stripos($r, 'HTTP/') === 0) {
    list(,$code, $status) = explode(' ', $r, 3);
    echo "Code: $code, Status: $status";
    break;
  }
}

似乎只有HTTP版本和状态的头上有一个
。 执行一个
数组\u shift
来提取该数组,遍历其他数组,创建如下数组:

$parsedHeaders = array();
foreach ($headers as $header) {
    if (! preg_match('/^([^:]+):(.*)$/', $header, $output)) continue;
    $parsedArray[$output[1]] = $output[2];
}
附言:未经测试

-编辑-

享受;)


看起来您正在使用
get_headers
函数,若是,请使用此函数的第二个参数,该参数将替换输出数组键的数值并将其替换为字符串键,请检查for get_headers函数

一个小例子是:

<?php
    $output = get_headers('http://google.com', 1);
    print_r($output);

如果您有pecl_http,请简短回答:

稍长一点的回答:

$header = "...";
$parsed = array_map(function($x) { return array_map("trim", explode(":", $x, 2)); }, array_filter(array_map("trim", explode("\n", $header))));

没有http_解析_头()的最佳方式


我最终得到了这个解决方案,它使用正则表达式查找头中的所有键和值,并结合来自的一些数组变异,将正则表达式匹配到一个关联数组中。这并不是100%适合这里所问的问题,因为它需要一个字符串,但是连接一个字符串数组来获得一个字符串将作为这个问题的前奏。我的案例必须处理原始标题,因此这是一个解决方案

preg_match_all('/^([^:\n]*):?(.*)$/m',$header,$headers,preg_SET_顺序);
$headers=数组\合并(…数组\映射(函数($set)){
返回数组($set[1]=>trim($set[2]);
}($);

这将产生一个标题的关联数组。如果标题的第一行作为输入包含(例如,
GET/HTTP/1.1
),这将在输出中忽略它。

如果您想更加安全,请使用Symfony HTTP Foundation:

composer需要symfony/http基金会

使用Symfony\Component\HttpFoundation\Request;
$request=request::createFromGlobals();
//使用规范化的小写键检索HTTP请求头
$request->headers->get('host');
$request->headers->get('content-type');
如果您不希望有这种依赖关系,下面是一个示例,我将其放在一起,以确定
缓存控件
头是否具有
无缓存
值,例如:

/**
*  [
*    0 => 'Cache-Control: no-cache, no-store, no-validate',
*    1 => 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0',
*  ]
*/
$headers = headers_list();

foreach ( $headers as $header_string ) {
     /*
     * Regex Samples:
     * "Foo: Bar"
     * "Foo-Bar: Baz-Bar:1"
     *
     * Matches:
     * "Foo"
     * "Foo-Bar"
     */
    preg_match( '#^.+?(?=:)#', $header_string, $key );

    if ( empty( $key ) ) {
        continue;
    }

    $key   = strtolower( reset( $key ) );
    $value = strtolower( ltrim( strtolower( $header_string ), $key . ':' ) );

    if ( $key == 'cache-control' ) {
        if ( strpos( $value, 'no-cache' ) !== false || strpos( $value, 'no-store' ) !== false ) {
            $nocache = true;
        }
    }
}

不,你不能这样做。这将盲目返回不存在但其值中包含字段名的标题。例如,getResponseHeader(“会话”)将返回cookie。响应代码假定为“HTTP/1.1”。还包含一个只获取状态的第一个字的bug。“HTTP/1.1 404找不到”怎么办?@Phil_1984_这是真的。字符串的左锚定匹配是必要的,以防止值匹配问题,并使用
explode()
限制对状态代码进行稍微智能化的解析。我将在以后有时间时修改这些函数(同时函数定义没有足够的参数)。您可以随时提出编辑建议或发布新答案。请注意,某些标题具有相同的标题名称,如
Set Cookie
,此函数将仅返回其中的第一个标题。答案很好,但仍然准确,只有一个问题。需要考虑其他HTTP协议版本,现在我们可以有第一个头看起来像“HTTP / 2 200”。因此,对于所有人来说,在解析过程中都要注意这一点!它不仅限于
stripos($r,'HTTP/1.1')
更好地使用
stripos($r,'HTTP/')
您的第一个正则表达式需要分隔符(
/
):
如果(!preg_match('/^([^:]):(*)$/,$header,$output))继续
$header = "...";
$parsed = array_map(function($x) { return array_map("trim", explode(":", $x, 2)); }, array_filter(array_map("trim", explode("\n", $header))));
function strHeaders2Hash($r) {
    $o = array();
    $r = substr($r, stripos($r, "\r\n"));
    $r = explode("\r\n", $r);
    foreach ($r as $h) {
        list($v, $val) = explode(": ", $h);
        if ($v == null) continue;
        $o[$v] = $val;
    }
    return $o;
}
/**
*  [
*    0 => 'Cache-Control: no-cache, no-store, no-validate',
*    1 => 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0',
*  ]
*/
$headers = headers_list();

foreach ( $headers as $header_string ) {
     /*
     * Regex Samples:
     * "Foo: Bar"
     * "Foo-Bar: Baz-Bar:1"
     *
     * Matches:
     * "Foo"
     * "Foo-Bar"
     */
    preg_match( '#^.+?(?=:)#', $header_string, $key );

    if ( empty( $key ) ) {
        continue;
    }

    $key   = strtolower( reset( $key ) );
    $value = strtolower( ltrim( strtolower( $header_string ), $key . ':' ) );

    if ( $key == 'cache-control' ) {
        if ( strpos( $value, 'no-cache' ) !== false || strpos( $value, 'no-store' ) !== false ) {
            $nocache = true;
        }
    }
}