Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Commit

Permalink
Allow forcing response content type in ErrorCatcher (#296)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
  • Loading branch information
2 people authored and devanych committed Feb 1, 2021
1 parent 9b45610 commit 1d4e60d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
40 changes: 31 additions & 9 deletions src/ErrorHandler/ErrorCatcher.php
Expand Up @@ -32,6 +32,7 @@ final class ErrorCatcher implements MiddlewareInterface
private ResponseFactoryInterface $responseFactory;
private ErrorHandler $errorHandler;
private ContainerInterface $container;
private ?string $contentType = null;

public function __construct(
ResponseFactoryInterface $responseFactory,
Expand All @@ -46,14 +47,7 @@ public function __construct(
public function withRenderer(string $mimeType, string $rendererClass): self
{
$this->validateMimeType($mimeType);

if (trim($rendererClass) === '') {
throw new \InvalidArgumentException('The renderer class cannot be an empty string.');
}

if ($this->container->has($rendererClass) === false) {
throw new \InvalidArgumentException("The renderer \"$rendererClass\" cannot be found.");
}
$this->validateRenderer($rendererClass);

$new = clone $this;
$new->renderers[$this->normalizeMimeType($mimeType)] = $rendererClass;
Expand All @@ -77,9 +71,26 @@ public function withoutRenderers(string ...$mimeTypes): self
return $new;
}

/**
* Force content type to respond with regardless of request
* @param string $contentType
* @return $this
*/
public function forceContentType(string $contentType): self
{
$this->validateMimeType($contentType);
if (!isset($this->renderers[$contentType])) {
throw new \InvalidArgumentException(sprintf('The renderer for %s is not set.', $contentType));
}

$new = clone $this;
$new->contentType = $contentType;
return $new;
}

private function handleException(\Throwable $e, ServerRequestInterface $request): ResponseInterface
{
$contentType = $this->getContentType($request);
$contentType = $this->contentType ?? $this->getContentType($request);
$renderer = $this->getRenderer(strtolower($contentType));
if ($renderer !== null) {
$renderer->setRequest($request);
Expand Down Expand Up @@ -136,4 +147,15 @@ private function normalizeMimeType(string $mimeType): string
{
return strtolower(trim($mimeType));
}

private function validateRenderer(string $rendererClass): void
{
if (trim($rendererClass) === '') {
throw new \InvalidArgumentException('The renderer class cannot be an empty string.');
}

if ($this->container->has($rendererClass) === false) {
throw new \InvalidArgumentException("The renderer \"$rendererClass\" cannot be found.");
}
}
}
18 changes: 18 additions & 0 deletions tests/Middleware/ErrorCatcherTest.php
Expand Up @@ -110,6 +110,24 @@ public function testDefaultContentType(): void
$this->assertSame($expectedRendererOutput, $content);
}

public function testForceContentType(): void
{
$catcher = $this->getErrorCatcher(new Container())->forceContentType('application/json');
$response = $catcher->process(
new ServerRequest('GET', '/', ['Accept' => ['text/xml']]),
(new MockRequestHandler())->setHandleExcaption(new \RuntimeException())
);
$response->getBody()->rewind();
$this->assertSame('application/json', $response->getHeaderLine('Content-Type'));
}

public function testForceContentTypeSetInvalidType(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectErrorMessage('The renderer for image/gif is not set.');
$this->getErrorCatcher(new Container())->forceContentType('image/gif');
}

private function getContainerWithThrowableRenderer(string $id, string $expectedOutput): Container
{
return new Container(
Expand Down

0 comments on commit 1d4e60d

Please sign in to comment.