Passed
Branch release/v3.0.0 (75e108)
by Anatoly
06:32
created

PayloadDecodingMiddleware::process()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 44
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 26
nc 6
nop 2
dl 0
loc 44
ccs 29
cts 29
cp 1
crap 6
rs 8.8817
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Nekhay <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Nekhay
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sunrise\Http\Router\Middleware;
15
16
use LogicException;
17
use Psr\Http\Message\ResponseInterface;
18
use Psr\Http\Message\ServerRequestInterface;
19
use Psr\Http\Server\MiddlewareInterface;
20
use Psr\Http\Server\RequestHandlerInterface;
21
use Sunrise\Coder\CodecManagerInterface;
22
use Sunrise\Coder\Exception\CodecException;
23
use Sunrise\Http\Router\Dictionary\HeaderName;
24
use Sunrise\Http\Router\Exception\HttpExceptionFactory;
25
use Sunrise\Http\Router\ServerRequest;
26
use Sunrise\Http\Router\StringableMediaType;
27
28
use function array_map;
29
use function sprintf;
30
31
/**
32
 * @since 3.0.0
33
 */
34
final class PayloadDecodingMiddleware implements MiddlewareInterface
35
{
36
    /**
37
     * @param array<array-key, mixed> $codecContext
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>.
Loading history...
38
     */
39 9
    public function __construct(
40
        private readonly CodecManagerInterface $codecManager,
41
        private readonly array $codecContext = [],
42
    ) {
43 9
    }
44
45
    /**
46
     * @inheritDoc
47
     */
48 9
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
49
    {
50 9
        $serverRequest = ServerRequest::create($request);
51 9
        $route = $serverRequest->getRoute();
52 9
        $serverConsumedMediaTypes = $route->getConsumedMediaTypes();
53
54
        // The server expects nothing from the client, just keep going...
55 9
        if ($serverConsumedMediaTypes === []) {
56 1
            return $handler->handle($request);
57
        }
58
59 8
        $clientProducedMediaType = $serverRequest->getClientProducedMediaType();
60 8
        if ($clientProducedMediaType === null) {
61 1
            throw HttpExceptionFactory::missingMediaType();
62
        }
63
64 7
        if (!$serverRequest->serverConsumesMediaType($clientProducedMediaType)) {
65 1
            throw HttpExceptionFactory::unsupportedMediaType()
66 1
                ->addHeaderField(HeaderName::ACCEPT, ...array_map(
67 1
                    StringableMediaType::create(...),
68 1
                    $serverConsumedMediaTypes,
69 1
                ));
70
        }
71
72 6
        if (!$this->codecManager->supportsMediaType($clientProducedMediaType)) {
73 1
            throw new LogicException(sprintf(
74 1
                'The route "%s" expects the media type "%s" that is not supported by the codec manager.',
75 1
                $route->getName(),
76 1
                $clientProducedMediaType->getIdentifier(),
77 1
            ));
78
        }
79
80
        try {
81
            /** @var array<array-key, mixed>|object|null $parsedBody */
82 5
            $parsedBody = $this->codecManager->decode(
83 5
                $clientProducedMediaType,
84 5
                (string) $request->getBody(),
85 5
                $this->codecContext,
86 5
            );
87 1
        } catch (CodecException $e) {
88 1
            throw HttpExceptionFactory::invalidBody(previous: $e);
89
        }
90
91 4
        return $handler->handle($request->withParsedBody($parsedBody));
92
    }
93
}
94