如何解析 PHP 中的响应头?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12433958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse response headers in PHP?
提问by pgtips
I have made an oauth signed request to a REST API and have the response headers in an array like so:
我已经向 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
I am trying to figure out how to parse the headers for easy retrieval of items such as the HTTP status code, Content-Location, oauth_token, and oauth_token_secret?
我想弄清楚如何解析标题以便轻松检索 HTTP 状态代码、内容位置、oauth_token 和 oauth_token_secret 等项目?
回答by Michael Berkowski
You'll need to iterate the array and check stripos()to find the header you're looking for. In most cases, you then explode()on :(limiting to 2 resultant parts), but the HTTP response code will require you to explode on the spaces.
您需要迭代数组并检查stripos()以找到您要查找的标头。在大多数情况下,你再explode()上:(限制到2个得到部分),但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;
}
}
回答by Felds Liscia
It seems that the only header withou a :is the HTTP version and status.
Do an array_shiftto extract that, iterate through the others creating an array like so:
似乎唯一没有 a 的标头:是 HTTP 版本和状态。做一个array_shift提取它,遍历其他创建一个数组,如下所示:
$parsedHeaders = array();
foreach ($headers as $header) {
if (! preg_match('/^([^:]+):(.*)$/', $header, $output)) continue;
$parsedArray[$output[1]] = $output[2];
}
ps: untested.
ps:未经测试。
— edit —
- 编辑 -
enjoy ;)
请享用 ;)
/**
* Parse a set of HTTP headers
*
* @param array The php headers to be parsed
* @param [string] The name of the header to be retrieved
* @return A header value if a header is passed;
* An array with all the headers otherwise
*/
function parseHeaders(array $headers, $header = null)
{
$output = array();
if ('HTTP' === substr($headers[0], 0, 4)) {
list(, $output['status'], $output['status_text']) = explode(' ', $headers[0]);
unset($headers[0]);
}
foreach ($headers as $v) {
$h = preg_split('/:\s*/', $v);
$output[strtolower($h[0])] = $h[1];
}
if (null !== $header) {
if (isset($output[strtolower($header)])) {
return $output[strtolower($header)];
}
return;
}
return $output;
}
回答by lethalman
Short answer if you have pecl_http: http://php.net/manual/it/function.explode.php
如果你有 pecl_http 的简短回答:http://php.net/manual/it/function.explode.php
Slightly longer answer:
稍微长一点的答案:
$header = "...";
$parsed = array_map(function($x) { return array_map("trim", explode(":", $x, 2)); }, array_filter(array_map("trim", explode("\n", $header))));
回答by Puffy
best way without http_parse_headers();
没有 http_parse_headers() 的最佳方法;
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;
}
回答by cjbarth
I ended up with this solution which uses regex to find all the keys and values in the header combined with some array mutation from https://stackoverflow.com/a/43004994/271351to get the regex matches into an associative array. This isn't 100% appropriate for the problem asked here since it takes in a string, but joining an array of strings to get a single string would work as a precursor to this. My case had to deal with raw headers, thus this solution.
我最终得到了这个解决方案,它使用正则表达式来查找标头中的所有键和值,并结合来自https://stackoverflow.com/a/43004994/271351 的一些数组变异,将正则表达式匹配到关联数组中。这不是 100% 适合这里提出的问题,因为它接受一个字符串,但加入一个字符串数组以获得单个字符串可以作为这个的前兆。我的情况必须处理原始标题,因此这个解决方案。
preg_match_all('/^([^:\n]*): ?(.*)$/m', $header, $headers, PREG_SET_ORDER);
$headers = array_merge(...array_map(function ($set) {
return array($set[1] => trim($set[2]));
}, $headers));
This yields an associative array of the headers. If the first line of the headers is included as input (e.g. GET / HTTP/1.1), this will ignore it for the output.
这产生了标题的关联数组。如果标题的第一行作为输入(例如GET / HTTP/1.1)包含在内,则输出时将忽略它。
回答by Lucas Bustamante
If you want to be extra-safe, use Symfony HTTP Foundation:
如果你想更加安全,请使用 Symfony HTTP Foundation:
composer require symfony/http-foundation
composer require symfony/http-foundation
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
// retrieves an HTTP request header, with normalized, lowercase keys
$request->headers->get('host');
$request->headers->get('content-type');
If you'd rather not have that dependency, here's an example that I've put together to find out if the Cache-Controlheader has the no-cachevalue, for instance:
如果你不想有这种依赖,这里有一个例子,我把它放在一起来找出Cache-Control标题是否有no-cache值,例如:
/**
* [
* 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;
}
}
}
回答by Ma'moon Al-Akash
It looks like you're using get_headersfunction, if so, use the second parameter of the this function which replaces the numerical values for the output array keys and replaces them with string keys, check out the manualfor get_headers function.
看起来您正在使用get_headers函数,如果是这样,请使用 this 函数的第二个参数替换输出数组键的数值并用字符串键替换它们,请查看get_headers 函数的手册。
a small example would be:
一个小例子是:
<?php
$output = get_headers('http://google.com', 1);
print_r($output);
will produce something like the following array:
将产生类似于以下数组的内容:
Array
(
[0] => HTTP/1.0 301 Moved Permanently
[Location] => http://www.google.com/
[Content-Type] => Array
(
[0] => text/html; charset=UTF-8
[1] => text/html; charset=ISO-8859-1
)
[Date] => Array
(
[0] => Tue, 24 Sep 2013 11:57:10 GMT
[1] => Tue, 24 Sep 2013 11:57:11 GMT
)
[Expires] => Array
(
[0] => Thu, 24 Oct 2013 11:57:10 GMT
[1] => -1
)
[Cache-Control] => Array
(
[0] => public, max-age=2592000
[1] => private, max-age=0
)
[Server] => Array
(
[0] => gws
[1] => gws
)
[Content-Length] => 219
[X-XSS-Protection] => Array
(
[0] => 1; mode=block
[1] => 1; mode=block
)
[X-Frame-Options] => Array
(
[0] => SAMEORIGIN
[1] => SAMEORIGIN
)
[Alternate-Protocol] => Array
(
[0] => 80:quic
[1] => 80:quic
)
[1] => HTTP/1.0 200 OK
[Set-Cookie] => Array
(
[0] => PREF=ID=58c8f706594fae17:FF=0:TM=1380023831:LM=1380023831:S=_ehOnNWODZqIarXn; expires=Thu, 24-Sep-2015 11:57:11 GMT; path=/; domain=.google.com
[1] => NID=67=L85IlJW5yG4l9Suyf1LwKMUTcVHyGv4u9tuuMlBH4pfT1syOJvspcgRJ9uTde1xLTDhI2QcOG_fuJY3sfhw49mayT5WdMHnGeMyhh3SgFTRYVF0RAtBXXmjyDFzMqPKu; expires=Wed, 26-Mar-2014 11:57:11 GMT; path=/; domain=.google.com; HttpOnly
)
[P3P] => CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
)

