client_prefers()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 1
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
use Koded\Http\{AcceptHeaderNegotiator, HTTPError};
4
use Koded\Http\Interfaces\{Request, Response};
5
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
6
use function Koded\Http\create_stream;
7
8
9
function start_response(Request $request, Response $response): void
10
{
11
    if (false === $response->hasHeader('Content-Type')) {
12
        $media = $request->getAttribute('@media') ?? client_prefers($request);
13
        // [NOTE]: Web browsers have weird Accept headers and
14
        // this renderer overrules the default XML and/or XHTML type
15
        // by preferring JSON, hence forcing the response for ReST apps.
16
        if (str_contains($media, 'html')) {
17
            $media = 'application/json';
18
        }
19
        $response = $response
20
            ->withHeader('Content-Type', $media)
21
            ->withAddedHeader('Vary', 'Content-Type');
22
    }
23
    $response->getBody()->rewind();
24
    $response->sendHeaders();
0 ignored issues
show
Bug introduced by
The method sendHeaders() does not exist on Psr\Http\Message\MessageInterface. It seems like you code against a sub-type of Psr\Http\Message\MessageInterface such as Koded\Http\Interfaces\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

24
    $response->/** @scrutinizer ignore-call */ 
25
               sendHeaders();
Loading history...
25
    echo $response->sendBody();
0 ignored issues
show
Bug introduced by
The method sendBody() does not exist on Psr\Http\Message\MessageInterface. It seems like you code against a sub-type of Psr\Http\Message\MessageInterface such as Koded\Http\Interfaces\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

25
    echo $response->/** @scrutinizer ignore-call */ sendBody();
Loading history...
26
}
27
28
/**
29
 * Content type negotiation.
30
 * Finds the closest match for Accept request header.
31
 *
32
 * @param ServerRequestInterface $request
33
 * @return string The content type that matches the Accept header.
34
 *                If catch-all is provided, defaults to application/json
35
 */
36
function client_prefers(ServerRequestInterface $request): string
37
{
38 4
    $media = (new AcceptHeaderNegotiator('*/*'))
39 4
        ->match($request->getHeaderLine('Accept') ?: '*/*')
40 4
        ->value();
41
42 4
    if ('*' === $media) {
43 3
        return 'application/json';
44
    }
45 1
    return $media . (str_contains($media, 'json') ? '' : '; charset=UTF-8');
46
}
47
48
/**
49
 * Exceptions serializer (follows the RFC-7807).
50
 *
51
 * @param ServerRequestInterface $request
52
 * @param ResponseInterface      $response
53
 * @param HTTPError              $exception
54
 * @return ResponseInterface
55
 * @see https://tools.ietf.org/html/rfc7807
56
 */
57
function default_serialize_error(
58
    ServerRequestInterface $request,
59
    ResponseInterface $response,
60
    HTTPError $exception): ResponseInterface
61
{
62 4
    $exception->setInstance($request->getUri()->getPath());
63 4
    $response = $response
64 4
        ->withHeader('X-Error-Status', join(' ', [$response->getStatusCode(), $response->getReasonPhrase()]))
65 4
        ->withHeader('X-Error-Message', str_replace(["\n", "\r", "\t"], ' ', $exception->getDetail()))
66 4
        ->withHeader('Cache-Control', 'no-cache, max-age=0')
67 4
        ->withHeader('Connection', 'close');
68
69 4
    if (str_contains(client_prefers($request), 'xml')) {
70
        return $response
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response->withHe...m($exception->toXml())) returns the type Psr\Http\Message\MessageInterface which includes types incompatible with the type-hinted return Psr\Http\Message\ResponseInterface.
Loading history...
71
            ->withHeader('Content-Type', 'application/problem+xml')
72
            ->withBody(create_stream($exception->toXml()));
73
    }
74 4
    return $response
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response->withHe...($exception->toJson())) returns the type Psr\Http\Message\MessageInterface which includes types incompatible with the type-hinted return Psr\Http\Message\ResponseInterface.
Loading history...
75 4
        ->withHeader('Content-Type', 'application/problem+json')
76 4
        ->withBody(create_stream($exception->toJson()));
77
}
78