Passed
Pull Request — master (#806)
by Paolo
03:59
created

StatusMiddleware::process()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 15
c 1
b 0
f 1
dl 0
loc 30
rs 9.4555
cc 5
nc 6
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace App\Middleware;
5
6
use BEdita\WebTools\ApiClientProvider;
7
use Cake\Http\Exception\MethodNotAllowedException;
8
use Cake\Http\Exception\ServiceUnavailableException;
9
use Cake\Log\LogTrait;
10
use Laminas\Diactoros\Response\EmptyResponse;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Psr\Http\Server\MiddlewareInterface;
14
use Psr\Http\Server\RequestHandlerInterface;
15
use Psr\Log\LogLevel;
16
use Throwable;
17
18
/**
19
 * Middleware to serve a status endpoint.
20
 */
21
class StatusMiddleware implements MiddlewareInterface
22
{
23
    use LogTrait;
24
25
    /**
26
     * Path to the status endpoint.
27
     *
28
     * @var string
29
     */
30
    protected string $path = '/status';
31
32
    /**
33
     * Status middleware constructor.
34
     *
35
     * @param string|null $path Path to the status endpoint.
36
     */
37
    public function __construct(?string $path = null)
38
    {
39
        $this->path = $path ?? $this->path;
40
    }
41
42
    /**
43
     * @inheritDoc
44
     */
45
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
46
    {
47
        if ($request->getUri()->getPath() !== $this->path) {
48
            // Request is not addressed to the status endpoint.
49
            return $handler->handle($request);
50
        }
51
52
        if (!in_array(strtoupper($request->getMethod()), ['GET', 'HEAD', 'OPTIONS'])) {
53
            // Status endpoint only supports GET and HEAD requests.
54
            throw new MethodNotAllowedException();
55
        }
56
57
        $queryParams = $request->getQueryParams();
58
        $full = filter_var($queryParams['full'] ?? null, FILTER_VALIDATE_BOOLEAN);
59
        if (!$full) {
60
            // Just a liveliness probe to check whether the server is up.
61
            return new EmptyResponse();
62
        }
63
64
        try {
65
            // Check if the API is reachable and up.
66
            $client = ApiClientProvider::getApiClient();
67
            $client->get('/status'); // Upon error, this will throw a \BEdita\SDK\BEditaClientException.
68
        } catch (Throwable $e) {
69
            $this->log(sprintf('API status endpoint failed or unreachable: %s', $e), LogLevel::CRITICAL);
70
71
            throw new ServiceUnavailableException('API status returned an error or is unreachable');
72
        }
73
74
        return new EmptyResponse();
75
    }
76
}
77