Skip to content

Commit

Permalink
Replicate the logic used to set Content-Type when transforming reponses
Browse files Browse the repository at this point in the history
When converting responses into PSR7, we need to follow the same logic
when the Content-Type header has not already been set.

Refs #9315
  • Loading branch information
markstory committed Aug 21, 2016
1 parent 905c020 commit 8b42486
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 4 deletions.
37 changes: 36 additions & 1 deletion src/Http/ResponseTransformer.php
Expand Up @@ -160,7 +160,7 @@ public static function toPsr(CakeResponse $response)
$status = $response->statusCode();
$headers = $response->header();
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = $response->type();
$headers = static::setContentType($headers, $response);
}
$cookies = $response->cookie();
if ($cookies) {
Expand All @@ -182,6 +182,41 @@ public static function toPsr(CakeResponse $response)
return new DiactorosResponse($stream, $status, $headers);
}

/**
* Add in the Content-Type header if necessary.
*
* @param array $headers The headers to update
* @param CakeResponse $response The CakePHP response to convert
* @return The updated headers.
*/
protected static function setContentType($headers, $response)
{
if (isset($headers['Content-Type'])) {
return $headers;
}
if (in_array($response->statusCode(), [204, 304])) {
return $headers;
}
$whitelist = [
'application/javascript', 'application/json', 'application/xml', 'application/rss+xml'
];

$type = $response->type();
$charset = $response->charset();

$hasCharset = false;
if ($charset && (strpos($type, 'text/') === 0 || in_array($type, $whitelist))) {
$hasCharset = true;
}

$value = $type;
if ($hasCharset) {
$value = "{$type}; charset={$charset}";
}
$headers['Content-Type'] = $value;
return $headers;
}

/**
* Convert an array of cookies into header lines.
*
Expand Down
48 changes: 45 additions & 3 deletions tests/TestCase/Http/ResponseTransformerTest.php
Expand Up @@ -281,9 +281,51 @@ public function testToPsrCookieAttributes()
public function testToPsrContentType()
{
$cake = new CakeResponse();
$cake->type('js');
$cake->type('html');
$cake->charset('utf-8');
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('application/javascript', $result->getHeaderLine('Content-Type'));
$this->assertSame('text/html; charset=utf-8', $result->getHeaderLine('Content-Type'));
}

/**
* Test conversion omitting content-type on 304 and 204 status codes
*
* @return void
*/
public function testToPsrContentTypeStatusOmission()
{
$cake = new CakeResponse();
$cake->type('html');
$cake->statusCode(304);
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('', $result->getHeaderLine('Content-Type'));

$cake->statusCode(204);
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('', $result->getHeaderLine('Content-Type'));
}

/**
* Test conversion omitting content-type on 304 and 204 status codes
*
* @return void
*/
public function testToPsrContentTypeCharsetIsTypeSpecific()
{
$cake = new CakeResponse();
$cake->charset('utf-8');

$cake->type('text/html');
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('text/html; charset=utf-8', $result->getHeaderLine('Content-Type'));

$cake->type('application/octet-stream');
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('application/octet-stream', $result->getHeaderLine('Content-Type'));

$cake->type('application/json');
$result = ResponseTransformer::toPsr($cake);
$this->assertSame('application/json; charset=utf-8', $result->getHeaderLine('Content-Type'));
}

/**
Expand All @@ -302,7 +344,7 @@ public function testToPsrHeaders()
$expected = [
'X-testing' => ['one', 'two'],
'Location' => ['http://example.com/testing'],
'Content-Type' => ['text/html'],
'Content-Type' => ['text/html; charset=UTF-8'],
];
$this->assertSame($expected, $result->getHeaders());
}
Expand Down

0 comments on commit 8b42486

Please sign in to comment.