Skip to content

Commit

Permalink
fix: Fixes sending headers for HTTP response.
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavofreze committed Jun 14, 2023
1 parent c71eb29 commit de8dcb3
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 25 deletions.
2 changes: 2 additions & 0 deletions infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"LogicalOr": false,
"IfNegation": false,
"InstanceOf_": false,
"UnwrapArrayMap": false,
"ArrayItemRemoval": false,
"UnwrapArrayUnique": false,
"MethodCallRemoval": false,
"LogicalOrAllSubExprNegation": false,
"LogicalOrSingleSubExprNegation": false
Expand Down
23 changes: 17 additions & 6 deletions src/HttpHeaders.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,25 @@ final class HttpHeaders
{
private array $values = [];

private function __construct()
{
}

public static function build(): HttpHeaders
{
return new HttpHeaders();
}

public function add(Header $header): HttpHeaders
{
$key = $header->key();
$this->values['header'][$key] = sprintf('%s: %s', $key, $header->value());
$this->values[$header->key()][] = $header->value();

return $this;
}

public function getHeader(): array
public function getHeader(string $key): array
{
return $this->values['header'] ?? [];
return $this->values[$key] ?? [];
}

public function hasHeaders(): bool
Expand All @@ -33,11 +41,14 @@ public function hasHeaders(): bool

public function hasHeader(string $key): bool
{
return !empty($this->getHeader()[$key]);
return !empty($this->getHeader(key: $key));
}

public function toArray(): array
{
return $this->values;
return array_map(
fn(array $values): array => [end($values)],
array_map(fn(array $values): array => array_unique($values), $this->values)
);
}
}
6 changes: 3 additions & 3 deletions src/Internal/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private function __construct(
public static function from(HttpCode $code, mixed $data, ?HttpHeaders $headers): ResponseInterface
{
if (is_null($headers) || !$headers->hasHeaders()) {
$headers = (new HttpHeaders())->add(header: HttpContentType::APPLICATION_JSON);
$headers = HttpHeaders::build()->add(header: HttpContentType::APPLICATION_JSON);
}

return new Response(code: $code, body: StreamFactory::from(data: $data), headers: $headers);
Expand Down Expand Up @@ -76,12 +76,12 @@ public function hasHeader(string $name): bool

public function getHeader(string $name): array
{
return $this->headers->getHeader();
return $this->headers->getHeader(key: $name);
}

public function getHeaderLine(string $name): string
{
return implode(', ', $this->getHeader(name: $name));
return implode(', ', $this->headers->getHeader(key: $name));
}

public function getBody(): StreamInterface
Expand Down
7 changes: 6 additions & 1 deletion tests/HttpResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

class HttpResponseTest extends TestCase
{
private array $defaultHeader = ['header' => ['Content-Type' => 'Content-Type: application/json']];
private array $defaultHeader;

protected function setUp(): void
{
$this->defaultHeader = ['Content-Type' => [HttpContentType::APPLICATION_JSON->value]];
}

/**
* @dataProvider providerData
Expand Down
9 changes: 4 additions & 5 deletions tests/Internal/HeadersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ class HeadersTest extends TestCase
{
public function testAddAndGetValues(): void
{
$headers = (new HttpHeaders())->add(header: HttpContentType::APPLICATION_JSON);
$expected = ['header' => ['Content-Type' => 'Content-Type: application/json']];
$headers = HttpHeaders::build()->add(header: HttpContentType::APPLICATION_JSON);
$expected = ['Content-Type' => [HttpContentType::APPLICATION_JSON->value]];

self::assertEquals($expected, $headers->toArray());
}

public function testAddAndGetUniqueValues(): void
{
$headers = (new HttpHeaders())
$headers = HttpHeaders::build()
->add(header: HttpContentType::TEXT_HTML)
->add(header: HttpContentType::APPLICATION_PDF);

$expected = ['header' => ['Content-Type' => 'Content-Type: application/pdf']];
$expected = ['Content-Type' => [HttpContentType::APPLICATION_PDF->value]];

self::assertEquals($expected, $headers->toArray());
}
Expand Down
17 changes: 7 additions & 10 deletions tests/Internal/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@

class ResponseTest extends TestCase
{
private const TEXT_PLAIN = 'Content-Type: text/plain';
private const APPLICATION_JSON = 'Content-Type: application/json';

public function testDefaultHeaders(): void
{
$response = Response::from(code: HttpCode::OK, data: [], headers: null);
$expected = ['header' => ['Content-Type' => self::APPLICATION_JSON]];
$expected = ['Content-Type' => [HttpContentType::APPLICATION_JSON->value]];

self::assertEquals($expected, $response->getHeaders());
}
Expand All @@ -31,30 +28,30 @@ public function testGetProtocolVersion(): void

public function testGetHeaders(): void
{
$headers = (new HttpHeaders())->add(header: HttpContentType::APPLICATION_JSON);
$headers = HttpHeaders::build()->add(header: HttpContentType::APPLICATION_JSON);
$response = Response::from(code: HttpCode::OK, data: [], headers: $headers);
$expected = ['Content-Type' => self::APPLICATION_JSON];
$expected = [HttpContentType::APPLICATION_JSON->value];

self::assertEquals($headers->toArray(), $response->getHeaders());
self::assertEquals($expected, $response->getHeader(name: 'Content-Type'));
}

public function testHasHeader(): void
{
$headers = (new HttpHeaders())->add(header: HttpContentType::TEXT_PLAIN);
$headers = HttpHeaders::build()->add(header: HttpContentType::TEXT_PLAIN);
$response = Response::from(code: HttpCode::OK, data: [], headers: $headers);
$expected = ['Content-Type' => self::TEXT_PLAIN];
$expected = [HttpContentType::TEXT_PLAIN->value];

self::assertTrue($response->hasHeader(name: 'Content-Type'));
self::assertEquals($expected, $response->getHeader(name: 'Content-Type'));
}

public function testGetHeaderLine(): void
{
$headers = (new HttpHeaders())->add(header: HttpContentType::APPLICATION_JSON);
$headers = HttpHeaders::build()->add(header: HttpContentType::APPLICATION_JSON);
$response = Response::from(code: HttpCode::OK, data: [], headers: $headers);

self::assertEquals(self::APPLICATION_JSON, $response->getHeaderLine(name: 'Content-Type'));
self::assertEquals(HttpContentType::APPLICATION_JSON->value, $response->getHeaderLine(name: 'Content-Type'));
}

public function testExceptionWhenBadMethodCallOnWithBody(): void
Expand Down

0 comments on commit de8dcb3

Please sign in to comment.