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

Allow set return content type #296

Merged
merged 9 commits into from Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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