Passed
Push — master ( 6a5936...88a431 )
by Mihail
12:09
created

default_serialize_error()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.0491

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 13
nc 2
nop 3
dl 0
loc 20
ccs 10
cts 13
cp 0.7692
crap 2.0491
rs 9.8333
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
use Koded\Framework\HTTPError;
4
//use Koded\Framework\I18n\{I18n, I18nCatalog};
5
use Koded\Http\AcceptHeaderNegotiator;
6
use Koded\Http\Interfaces\{Request, Response};
7
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
8
use function Koded\Http\create_stream;
9
10
11
function start_response(Request $request, Response $response): void
12
{
13
    if (false === $response->hasHeader('Content-Type')) {
14
        $media = $request->getAttribute('@media') ?? client_prefers($request);
15
        // [NOTE]: Web browsers have weird Accept headers and
16
        // this renderer overrules the default XML and/or XHTML type
17
        // by preferring JSON, hence forcing the response for ReST apps.
18
        if (str_contains($media, 'html')) {
19
            $media = 'application/json';
20
        }
21
        $response = $response
22
            ->withHeader('Content-Type', $media)
23
            ->withAddedHeader('Vary', 'Content-Type');
24
    }
25
    $response->getBody()->rewind();
26
    $response->sendHeaders();
27
    echo $response->sendBody();
28
}
29
30
/**
31
 * Content type negotiation.
32
 * Finds the closest match for Accept request header.
33
 *
34
 * @param ServerRequestInterface $request
35
 * @return string The content type that matches the Accept header.
36
 *                If catch-all is provided, defaults to application/json
37
 */
38
function client_prefers(ServerRequestInterface $request): string
39
{
40 4
    $media = (new AcceptHeaderNegotiator('*/*'))
41 4
        ->match($request->getHeaderLine('Accept') ?: '*/*')
42 4
        ->value();
43
44 4
    if ('*' === $media) {
45 3
        return 'application/json';
46
    }
47 1
    return $media . (str_contains($media, 'json') ? '' : '; charset=UTF-8');
48
}
49
50
/**
51
 * Exceptions serializer (follows the RFC-7807).
52
 *
53
 * @param ServerRequestInterface $request
54
 * @param ResponseInterface      $response
55
 * @param HTTPError              $exception
56
 * @return ResponseInterface
57
 * @see https://tools.ietf.org/html/rfc7807
58
 */
59
function default_serialize_error(
60
    ServerRequestInterface $request,
61
    ResponseInterface $response,
62
    HTTPError $exception): ResponseInterface
63
{
64 4
    $exception->setInstance($request->getUri()->getPath());
65 4
    $response = $response
66 4
        ->withHeader('X-Error-Status', join(' ', [$response->getStatusCode(), $response->getReasonPhrase()]))
67 4
        ->withHeader('X-Error-Message', str_replace(["\n", "\r", "\t"], ' ', $exception->getDetail()))
68 4
        ->withHeader('Cache-Control', 'no-cache, max-age=0')
69 4
        ->withHeader('Connection', 'close');
70
71 4
    if (str_contains(client_prefers($request), 'xml')) {
72
        return $response
73
            ->withHeader('Content-Type', 'application/problem+xml')
74
            ->withBody(create_stream($exception->toXml()));
75
    }
76 4
    return $response
77 4
        ->withHeader('Content-Type', 'application/problem+json')
78 4
        ->withBody(create_stream($exception->toJson()));
79
}
80