Description
What steps will reproduce the problem?
Assume possible response headers of these forms.
HTTP:/1.1 400 InvalidParamSince
HTTP:/1.1 400 MissingParamSince
HTTP:/1.1 400 MissingQueryParams
HTTP:/1.1 400 NoMatchForQueryParams
In your current implementation, the method call getHeaders() only returns the header status code (ie. 400) but we may need to distinguish the response header using the corresponding phrase as well. It would also be nice to parse it into constituent parts. How can we get it ?
What's expected?
Additional granularity of the HTTP status line header returned from getHeaders(). For example, assume the raw response headers from a call were:
php
array(3) {
[0]=>
string(48) "HTTP/1.1 404 RequestNotFound (request id=0:98:0)"
[1]=>
string(17) "Content-Length: 0"
[2]=>
string(17) "Connection: Close"
}
Expected output would provide added granularity. For example,
php
$headers = $response->getHeaders();
echo '<pre>';
var_dump($headers);
echo '</pre>';
//output
yii\web\HeaderCollection Object
(
[_headers:yii\web\HeaderCollection:private] => Array
(
[http-status-line] => Array
(
[0] => HTTP/1.1 404 RequestNotFound
)
[http-version] => Array
(
[0] => HTTP/1.1
)
[http-status-code] => Array
(
[0] => 404
)
[http-reason-phrase] => Array
(
[0] => RequestNotFound
)
[http-status-code-reason-phrase] => Array
(
[0] => 404 RequestNotFound
)
[http-code] => Array
(
[0] => 404
)
[content-length] => Array
(
[0] => 0
)
[connection] => Array
(
[0] => Close
)
)
)
What do you get instead?
php
$headers = $response->getHeaders();
echo '<pre>';
var_dump($headers);
echo '</pre>';
//output
object(yii\web\HeaderCollection)#131 (1) {
["_headers":"yii\web\HeaderCollection":private]=>
array(3) {
["http-code"]=>
array(1) {
[0]=>
string(3) "404"
}
["content-length"]=>
array(1) {
[0]=>
string(1) "0"
}
["connection"]=>
array(1) {
[0]=>
string(5) "Close"
}
}
}
Additional info
After some investigations, I was able to obtain my expected result by overriding createResponse and extending httpclient\Client. In the code below, you could remove the bit about filtering out '(request id=' as that is specific to my application. For example,
php
use yii\httpclient\Client as Client;
class modClient extends Client
{
/**
* {@inheritDoc}
*/
public function createResponse($content = null, array $headers = [])
{
return parent::createResponse( $content, $this->modifyHeaders($headers) );
}
/**
* Returns the modified headers.
* This function appends additional headers to $headers.
* The additional headers consist of:
* 'http-status-line': The full status line (ie. 'HTTP/1.1 200 OK')
* 'http-version': The http version returned from the server (ie. 'HTTP/1.1')
* 'http-status-code': The Status code (ie. '200')
* 'http-reason-phrase': The reason phrase (ie. 'OK')
* 'http-status-code-reason-phrase': The status line without the HTTP version (ie. '200 OK')
* Additional filtering removes everything after and including '(request id=' from 'http-reason-phrase' and 'http-status-line' if found.
* @param array $headers headers list.
* @return array modified headers list
*/
public function modifyHeaders(array $headers = [])
{
$newHeaders = $headers;
$addHeaders = [
'http-status-line' => '',
'http-version' => '',
'http-status-code' => '',
'http-reason-phrase' => '',
'http-status-code-reason-phrase' =>'',
];
if (!is_object($newHeaders)) {
if (is_array($newHeaders)) {
foreach ($newHeaders as $name => $value) {
if (is_int($name)) {
// parse raw header :
$rawHeader = $value;
if (strpos($rawHeader, 'HTTP/') === 0) {
//removes everything after and including '(request id='
if( ($separatorPos = strpos($rawHeader,'(request id=')) !== false ) {
$rawHeader = trim(substr($rawHeader, 0, $separatorPos));
}
//parse out the various parts
$parts = explode(' ', $rawHeader, 3);
$addHeaders['http-status-line'] = $rawHeader;
$addHeaders['http-version'] = $parts[0];
$addHeaders['http-status-code'] = sizeof($parts)>1?trim($parts[1]):'';
$addHeaders['http-reason-phrase'] = sizeof($parts)>2?trim($parts[2]):'';
$addHeaders['http-status-code-reason-phrase'] = $addHeaders['http-status-code']. ' '.$addHeaders['http-reason-phrase'];
}
}
}
}
}
return array_merge($addHeaders,$newHeaders);
}
}
With the override, and using the extended client the same original headers provides added granularity. For example,
php
$client = new modClient();
$request = $client->get('http://example.com');
$headers = $response->getHeaders();
echo '<pre>';
var_dump($headers);
echo '</pre>';
//output
object(yii\web\HeaderCollection)#131 (1) {
["_headers":"yii\web\HeaderCollection":private]=>
array(8) {
["http-status-line"]=>
array(1) {
[0]=>
string(28) "HTTP/1.1 404 RequestNotFound"
}
["http-version"]=>
array(1) {
[0]=>
string(8) "HTTP/1.1"
}
["http-status-code"]=>
array(1) {
[0]=>
string(3) "404"
}
["http-reason-phrase"]=>
array(1) {
[0]=>
string(15) "RequestNotFound"
}
["http-status-code-reason-phrase"]=>
array(1) {
[0]=>
string(19) "404 RequestNotFound"
}
["http-code"]=>
array(1) {
[0]=>
string(3) "404"
}
["content-length"]=>
array(1) {
[0]=>
string(1) "0"
}
["connection"]=>
array(1) {
[0]=>
string(5) "Close"
}
}
}
Q | A |
---|---|
Yii version | 2.0.35 |
Yii HTTP Client version | 2.0.12 |
PHP version | 7.4.5 |
Operating system | UNIX |