Completed
Push — master ( f7424d...b53e51 )
by Alejandro
07:43
created

BodyParserMiddleware::process()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 3
nop 2
dl 0
loc 22
ccs 12
cts 12
cp 1
crap 4
rs 8.9197
c 0
b 0
f 0
1
<?php
2
namespace Shlinkio\Shlink\Rest\Middleware;
3
4
use Fig\Http\Message\RequestMethodInterface;
5
use Interop\Http\ServerMiddleware\DelegateInterface;
6
use Interop\Http\ServerMiddleware\MiddlewareInterface;
7
use Psr\Http\Message\ResponseInterface as Response;
8
use Psr\Http\Message\ServerRequestInterface as Request;
9
use Shlinkio\Shlink\Common\Exception\RuntimeException;
10
11
class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterface
12
{
13
    /**
14
     * Process an incoming server request and return a response, optionally delegating
15
     * to the next middleware component to create the response.
16
     *
17
     * @param Request $request
18
     * @param DelegateInterface $delegate
19
     *
20
     * @return Response
21
     */
22 3
    public function process(Request $request, DelegateInterface $delegate)
23
    {
24 3
        $method = $request->getMethod();
25 3
        $currentParams = $request->getParsedBody();
26
27
        // In requests that do not allow body or if the body has already been parsed, continue to next middleware
28 3
        if (! empty($currentParams) || in_array($method, [
29 3
            self::METHOD_GET,
30 3
            self::METHOD_HEAD,
31
            self::METHOD_OPTIONS
32 3
        ], true)) {
33 1
            return $delegate->process($request);
34
        }
35
36
        // If the accepted content is JSON, try to parse the body from JSON
37 2
        $contentType = $this->getRequestContentType($request);
38 2
        if (in_array($contentType, ['application/json', 'text/json', 'application/x-json'], true)) {
39 1
            return $delegate->process($this->parseFromJson($request));
40
        }
41
42 1
        return $delegate->process($this->parseFromUrlEncoded($request));
43
    }
44
45
    /**
46
     * @param Request $request
47
     * @return string
48
     */
49 2
    protected function getRequestContentType(Request $request)
50
    {
51 2
        $contentType = $request->getHeaderLine('Content-type');
52 2
        $contentTypes = explode(';', $contentType);
53 2
        return trim(array_shift($contentTypes));
54
    }
55
56
    /**
57
     * @param Request $request
58
     * @return Request
59
     */
60 1
    protected function parseFromJson(Request $request)
61
    {
62 1
        $rawBody = (string) $request->getBody();
63 1
        if (empty($rawBody)) {
64
            return $request;
65
        }
66
67 1
        $parsedJson = json_decode($rawBody, true);
68 1
        if (json_last_error() !== JSON_ERROR_NONE) {
69
            throw new RuntimeException(sprintf('Error when parsing JSON request body: %s', json_last_error_msg()));
70
        }
71
72 1
        return $request->withParsedBody($parsedJson);
73
    }
74
75
    /**
76
     * @param Request $request
77
     * @return Request
78
     */
79 1
    protected function parseFromUrlEncoded(Request $request)
80
    {
81 1
        $rawBody = (string) $request->getBody();
82 1
        if (empty($rawBody)) {
83
            return $request;
84
        }
85
86 1
        $parsedBody = [];
87 1
        parse_str($rawBody, $parsedBody);
88
89 1
        return $request->withParsedBody($parsedBody);
90
    }
91
}
92