Completed
Push — master ( 3d05f5...78c728 )
by John
08:45 queued 06:38
created

logCaughtThrowableResultingInHTTPCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 3
crap 1
1
<?php
2
namespace LunixREST\Server;
3
4
use LunixREST\APIRequest\APIRequest;
5
use LunixREST\Endpoint\Exceptions\ElementConflictException;
6
use LunixREST\Endpoint\Exceptions\ElementNotFoundException;
7
use LunixREST\Endpoint\Exceptions\InvalidRequestException;
8
use LunixREST\Endpoint\Exceptions\UnknownEndpointException;
9
use LunixREST\Server\Exceptions\AccessDeniedException;
10
use LunixREST\Server\Exceptions\InvalidAPIKeyException;
11
use LunixREST\APIRequest\RequestFactory\RequestFactory;
12
use LunixREST\APIRequest\URLParser\Exceptions\InvalidRequestURLException;
13
use LunixREST\APIResponse\Exceptions\NotAcceptableResponseTypeException;
14
use LunixREST\Server\Exceptions\MethodNotFoundException;
15
use LunixREST\Server\Exceptions\ThrottleLimitExceededException;
16
use Psr\Http\Message\ResponseInterface;
17
use Psr\Http\Message\ServerRequestInterface;
18
use Psr\Log\LoggerAwareTrait;
19
use Psr\Log\LoggerInterface;
20
use Psr\Log\LogLevel;
21
22
/**
23
 * A class that interfaces PSR-7 with our APIRequests and uses a Server to handle the APIRequest. Handles the PSR-7 response building as well.
24
 * Class HTTPServer
25
 * @package LunixREST\Server
26
 */
27
class HTTPServer
28
{
29
    use LoggerAwareTrait;
30
31
    /**
32
     * @var Server
33
     */
34
    protected $server;
35
    /**
36
     * @var RequestFactory
37
     */
38
    private $requestFactory;
39
40
    /**
41
     * HTTPServer constructor.
42
     * @param Server $server
43
     * @param RequestFactory $requestFactory
44
     * @param LoggerInterface $logger
45
     */
46 13
    public function __construct(Server $server, RequestFactory $requestFactory, LoggerInterface $logger)
47
    {
48 13
        $this->server = $server;
49 13
        $this->requestFactory = $requestFactory;
50 13
        $this->logger = $logger;
51 13
    }
52
53
    /**
54
     * Clones a response, changing contents based on the handling of a given request.
55
     * Taking in a response allows us not to define a specific response implementation to create.
56
     * @param ServerRequestInterface $serverRequest
57
     * @param ResponseInterface $response
58
     * @return ResponseInterface
59
     */
60 13
    public function handleRequest(ServerRequestInterface $serverRequest, ResponseInterface $response): ResponseInterface
61
    {
62 13
        $response = $response->withProtocolVersion($serverRequest->getProtocolVersion());
63
64
        try {
65 13
            $APIRequest = $this->requestFactory->create($serverRequest);
66
67 11
            return $this->handleAPIRequest($APIRequest, $response);
68 2
        } catch (InvalidRequestURLException $e) {
69 1
            $this->logCaughtThrowableResultingInHTTPCode(400, $e, LogLevel::INFO);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\APIRequ...lidRequestURLException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
70 1
            return $response->withStatus(400, "Bad Request");
71 1
        } catch (\Throwable $e) {
72 1
            $this->logCaughtThrowableResultingInHTTPCode(500, $e, LogLevel::CRITICAL);
73 1
            return $response->withStatus(500, "Internal Server Error");
74
        }
75
    }
76
77
    /**
78
     * Takes an APIRequest and a ResponseInterface and creates a new ResponseInterface derived from the passed implementation and returns it.
79
     * @param APIRequest $APIRequest
80
     * @param ResponseInterface $response
81
     * @return ResponseInterface
82
     */
83 11
    protected function handleAPIRequest(APIRequest $APIRequest, ResponseInterface $response)
84
    {
85
        try {
86 11
            $APIResponse = $this->server->handleRequest($APIRequest);
87
88 1
            $response = $response->withStatus(200, "200 OK");
89 1
            $response = $response->withAddedHeader("Content-Type", $APIResponse->getMIMEType());
90 1
            $response = $response->withAddedHeader("Content-Length", $APIResponse->getAsDataStream()->getSize());
91 1
            $this->logger->debug("Responding to request successfully");
92 1
            return $response->withBody($APIResponse->getAsDataStream());
93 10
        } catch (InvalidRequestException $e) {
94 1
            $this->logCaughtThrowableResultingInHTTPCode(400, $e, LogLevel::INFO);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Endpoin...nvalidRequestException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
95 1
            return $response->withStatus(400, "Bad Request");
96 9
        } catch (UnknownEndpointException | ElementNotFoundException $e) {
97 2
            $this->logCaughtThrowableResultingInHTTPCode(404, $e, LogLevel::INFO);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Endpoin...ementNotFoundException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
98 2
            return $response->withStatus(404, "Not Found");
99 7
        } catch (NotAcceptableResponseTypeException $e) {
100 1
            $this->logCaughtThrowableResultingInHTTPCode(406, $e, LogLevel::INFO);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\APIResp...eResponseTypeException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
101 1
            return $response->withStatus(406, "Not Acceptable");
102 6
        } catch (InvalidAPIKeyException | AccessDeniedException $e) {
103 2
            $this->logCaughtThrowableResultingInHTTPCode(403, $e, LogLevel::NOTICE);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Server\...\AccessDeniedException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
104 2
            return $response->withStatus(403, "Access Denied");
105 4
        }  catch (ElementConflictException $e) {
106 1
            $this->logCaughtThrowableResultingInHTTPCode(409, $e, LogLevel::NOTICE);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Endpoin...ementConflictException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
107 1
            return $response->withStatus(409, "Conflict");
108 3
        } catch (ThrottleLimitExceededException $e) {
109 1
            $this->logCaughtThrowableResultingInHTTPCode(429, $e, LogLevel::WARNING);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Server\...LimitExceededException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
110 1
            return $response->withStatus(429, "Too Many Requests");
111 2
        } catch (MethodNotFoundException | \Throwable $e) {
112 2
            $this->logCaughtThrowableResultingInHTTPCode(500, $e, LogLevel::CRITICAL);
113 2
            return $response->withStatus(500, "Internal Server Error");
114
        }
115
    }
116
117
    /**
118
     * Dumps a PSR-7 ResponseInterface to the SAPI.
119
     * @param ResponseInterface $response
120
     */
121 3
    public static function dumpResponse(ResponseInterface $response) {
122 3
        $statusLine = sprintf(
123 3
            "HTTP/%s %d %s",
124 3
            $response->getProtocolVersion(),
125 3
            $response->getStatusCode(),
126 3
            $response->getReasonPhrase()
127
        );
128
129 3
        header($statusLine, true, $response->getStatusCode());
130
131 3
        foreach ($response->getHeaders() as $name => $values) {
132 1
            foreach ($values as $value) {
133 1
                header(sprintf('%s: %s', $name, $value), false);
134
            }
135
        }
136
137 3
        $body = $response->getBody();
138 3
        while(!$body->eof()) {
139 3
            echo $body->read(1024);
140
        }
141 3
    }
142
143 12
    protected function logCaughtThrowableResultingInHTTPCode(int $code, \Throwable $exception, $level): void
144
    {
145 12
        $this->logger->log($level, "Returning HTTP {code}: {message}", ["code" => $code, "message" => $exception->getMessage()]);
146 12
    }
147
}
148