Skip to content

Commit

Permalink
Merge pull request #122 from clue-labs/headers
Browse files Browse the repository at this point in the history
Fix ignoring invalid incoming Transfer-Encoding response header
  • Loading branch information
jsor authored Feb 8, 2018
2 parents f8ac7af + 7d0a84d commit 5c6ffbd
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
34 changes: 25 additions & 9 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,10 @@ public function __construct(ReadableStreamInterface $stream, $protocol, $version
$this->code = $code;
$this->reasonPhrase = $reasonPhrase;
$this->headers = $headers;
$normalizedHeaders = array_change_key_case($headers, CASE_LOWER);

if (isset($normalizedHeaders['transfer-encoding']) && strtolower($normalizedHeaders['transfer-encoding']) === 'chunked') {
if (strtolower($this->getHeaderLine('Transfer-Encoding')) === 'chunked') {
$this->stream = new ChunkedStreamDecoder($stream);

foreach ($this->headers as $key => $value) {
if (strcasecmp('transfer-encoding', $key) === 0) {
unset($this->headers[$key]);
break;
}
}
$this->removeHeader('Transfer-Encoding');
}

$this->stream->on('data', array($this, 'handleData'));
Expand Down Expand Up @@ -75,6 +68,29 @@ public function getHeaders()
return $this->headers;
}

private function removeHeader($name)
{
foreach ($this->headers as $key => $value) {
if (strcasecmp($name, $key) === 0) {
unset($this->headers[$key]);
break;
}
}
}

private function getHeader($name)
{
$name = strtolower($name);
$normalized = array_change_key_case($this->headers, CASE_LOWER);

return isset($normalized[$name]) ? (array)$normalized[$name] : array();
}

private function getHeaderLine($name)
{
return implode(', ' , $this->getHeader($name));
}

/** @internal */
public function handleData($data)
{
Expand Down
31 changes: 31 additions & 0 deletions tests/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,36 @@ public function chunkedEncodingResponse()
$response->getHeaders()
);
}

/** @test */
public function doubleChunkedEncodingResponseWillBePassedAsIs()
{
$stream = new ThroughStream();
$response = new Response(
$stream,
'http',
'1.0',
'200',
'ok',
array(
'content-type' => 'text/plain',
'transfer-encoding' => array(
'chunked',
'chunked'
)
)
);

$this->assertSame(
array(
'content-type' => 'text/plain',
'transfer-encoding' => array(
'chunked',
'chunked'
)
),
$response->getHeaders()
);
}
}

0 comments on commit 5c6ffbd

Please sign in to comment.