Completed
Push — master ( 829799...5eed87 )
by John
02:56
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\UnknownEndpointException;
6
use LunixREST\Server\Exceptions\AccessDeniedException;
7
use LunixREST\Server\Exceptions\InvalidAPIKeyException;
8
use LunixREST\APIRequest\RequestFactory\RequestFactory;
9
use LunixREST\APIRequest\URLParser\Exceptions\InvalidRequestURLException;
10
use LunixREST\APIResponse\Exceptions\NotAcceptableResponseTypeException;
11
use LunixREST\Server\Exceptions\MethodNotFoundException;
12
use LunixREST\Server\Exceptions\ThrottleLimitExceededException;
13
use Psr\Http\Message\ResponseInterface;
14
use Psr\Http\Message\ServerRequestInterface;
15
use Psr\Log\LoggerAwareTrait;
16
use Psr\Log\LoggerInterface;
17
use Psr\Log\LogLevel;
18
19
/**
20
 * 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.
21
 * Class HTTPServer
22
 * @package LunixREST\Server
23
 */
24
class HTTPServer
25
{
26
    use LoggerAwareTrait;
27
28
    /**
29
     * @var Server
30
     */
31
    protected $server;
32
    /**
33
     * @var RequestFactory
34
     */
35
    private $requestFactory;
36
37
    /**
38
     * HTTPServer constructor.
39
     * @param Server $server
40
     * @param RequestFactory $requestFactory
41
     * @param LoggerInterface $logger
42
     */
43 10
    public function __construct(Server $server, RequestFactory $requestFactory, LoggerInterface $logger)
44
    {
45 10
        $this->server = $server;
46 10
        $this->requestFactory = $requestFactory;
47 10
        $this->logger = $logger;
48 10
    }
49
50
    /**
51
     * Clones a response, changing contents based on the handling of a given request.
52
     * Taking in a response allows us not to define a specific response implementation to create.
53
     * @param ServerRequestInterface $serverRequest
54
     * @param ResponseInterface $response
55
     * @return ResponseInterface
56
     */
57 10
    public function handleRequest(ServerRequestInterface $serverRequest, ResponseInterface $response): ResponseInterface
58
    {
59 10
        $response = $response->withProtocolVersion($serverRequest->getProtocolVersion());
60
61
        try {
62 10
            $APIRequest = $this->requestFactory->create($serverRequest);
63
64 8
            return $this->handleAPIRequest($APIRequest, $response);
65 2
        } catch (InvalidRequestURLException $e) {
66 1
            $this->logCaughtThrowableResultingInHTTPCode(400, $e, LogLevel::NOTICE);
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...
67 1
            return $response->withStatus(400, "Bad Request");
68 1
        } catch (\Throwable $e) {
69 1
            $this->logCaughtThrowableResultingInHTTPCode(500, $e, LogLevel::CRITICAL);
70 1
            return $response->withStatus(500, "Internal Server Error");
71
        }
72
    }
73
74
    /**
75
     * Takes an APIRequest and a ResponseInterface and creates a new ResponseInterface derived from the passed implementation and returns it.
76
     * @param APIRequest $APIRequest
77
     * @param ResponseInterface $response
78
     * @return ResponseInterface
79
     */
80 8
    protected function handleAPIRequest(APIRequest $APIRequest, ResponseInterface $response)
81
    {
82
        try {
83 8
            $APIResponse = $this->server->handleRequest($APIRequest);
84
85 1
            $response = $response->withStatus(200, "200 OK");
86 1
            $response = $response->withAddedHeader("Content-Type", $APIResponse->getMIMEType());
87 1
            $response = $response->withAddedHeader("Content-Length", $APIResponse->getAsDataStream()->getSize());
88 1
            $this->logger->debug("Responding to request successfully");
89 1
            return $response->withBody($APIResponse->getAsDataStream());
90 7
        } catch (InvalidAPIKeyException $e) {
91 1
            $this->logCaughtThrowableResultingInHTTPCode(400, $e, LogLevel::NOTICE);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Server\...InvalidAPIKeyException>, 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...
92 1
            return $response->withStatus(400, "Bad Request");
93 6
        } catch (UnknownEndpointException $e) {
94 1
            $this->logCaughtThrowableResultingInHTTPCode(404, $e, LogLevel::NOTICE);
0 ignored issues
show
Documentation introduced by
$e is of type object<LunixREST\Endpoin...knownEndpointException>, 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(404, "Not Found");
96 5
        } catch (NotAcceptableResponseTypeException $e) {
97 1
            $this->logCaughtThrowableResultingInHTTPCode(406, $e, LogLevel::NOTICE);
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...
98 1
            return $response->withStatus(406, "Not Acceptable");
99 4
        } catch (AccessDeniedException $e) {
100 1
            $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...
101 1
            return $response->withStatus(403, "Access Denied");
102 3
        } catch (ThrottleLimitExceededException $e) {
103 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...
104 1
            return $response->withStatus(429, "Too Many Requests");
105 2
        } catch (MethodNotFoundException | \Throwable $e) {
106 2
            $this->logCaughtThrowableResultingInHTTPCode(500, $e, LogLevel::CRITICAL);
107 2
            return $response->withStatus(500, "Internal Server Error");
108
        }
109
    }
110
111
    /**
112
     * Dumps a PSR-7 ResponseInterface to the SAPI.
113
     * @param ResponseInterface $response
114
     */
115 3
    public static function dumpResponse(ResponseInterface $response) {
116 3
        $statusLine = sprintf(
117 3
            "HTTP/%s %d %s",
118 3
            $response->getProtocolVersion(),
119 3
            $response->getStatusCode(),
120 3
            $response->getReasonPhrase()
121
        );
122
123 3
        header($statusLine, true, $response->getStatusCode());
124
125 3
        foreach ($response->getHeaders() as $name => $values) {
126 1
            foreach ($values as $value) {
127 1
                header(sprintf('%s: %s', $name, $value), false);
128
            }
129
        }
130
131 3
        $body = $response->getBody();
132 3
        while(!$body->eof()) {
133 3
            echo $body->read(1024);
134
        }
135 3
    }
136
137 9
    protected function logCaughtThrowableResultingInHTTPCode(int $code, \Throwable $exception, $level): void
138
    {
139 9
        $this->logger->log($level, "Returning HTTP {code}: {message}", ["code" => $code, "message" => $exception->getMessage()]);
140 9
    }
141
}
142