1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Phrest\Middleware; |
4
|
|
|
|
5
|
|
|
class JsonRequestBody implements \Interop\Http\ServerMiddleware\MiddlewareInterface |
6
|
|
|
{ |
7
|
|
|
const RAW_BODY_ATTRIBUTE = self::class . '::RAW_BODY_ATTRIBUTE'; |
8
|
|
|
const JSON_OBJECT_ATTRIBUTE = self::class . '::JSON_OBJECT_ATTRIBUTE'; |
9
|
|
|
|
10
|
|
|
static private $jsonDecodeErrorMapping = [ |
11
|
|
|
\JSON_ERROR_DEPTH => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_DEPTH, |
12
|
|
|
\JSON_ERROR_STATE_MISMATCH => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_STATE_MISMATCH, |
13
|
|
|
\JSON_ERROR_CTRL_CHAR => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_CTRL_CHAR, |
14
|
|
|
\JSON_ERROR_SYNTAX => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_SYNTAX, |
15
|
|
|
\JSON_ERROR_UTF8 => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_UTF8, |
16
|
|
|
\JSON_ERROR_RECURSION => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_RECURSION, |
17
|
|
|
\JSON_ERROR_INF_OR_NAN => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_INF_OR_NAN, |
18
|
|
|
\JSON_ERROR_UNSUPPORTED_TYPE => \Phrest\API\ErrorCodes::JSON_DECODE_ERROR_UNSUPPORTED_TYPE, |
19
|
|
|
]; |
20
|
|
|
|
21
|
|
|
public function process(\Psr\Http\Message\ServerRequestInterface $request, \Interop\Http\ServerMiddleware\DelegateInterface $delegate) |
22
|
|
|
{ |
23
|
|
|
$match = $this->match($request->getHeaderLine('Content-Type')); |
24
|
|
|
if (!$match || in_array($request->getMethod(), ['GET', 'HEAD', 'OPTIONS'])) { |
25
|
|
|
return $delegate->process($request); |
26
|
|
|
} |
27
|
|
|
|
28
|
|
|
$rawBody = (string)$request->getBody(); |
29
|
|
|
$parsedBody = json_decode($rawBody, true); |
30
|
|
|
if (!empty($rawBody) && json_last_error() !== JSON_ERROR_NONE) { |
31
|
|
|
$errorEntryCode = self::$jsonDecodeErrorMapping[json_last_error()] ?? \Phrest\API\ErrorCodes::UNKNOWN; |
32
|
|
|
throw \Phrest\Http\Exception::BadRequest( |
33
|
|
|
new \Phrest\API\Error( |
34
|
|
|
\Phrest\API\ErrorCodes::JSON_DECODE_ERROR, |
35
|
|
|
'json decode error', |
36
|
|
|
new \Phrest\API\ErrorEntry($errorEntryCode, '{body}', json_last_error_msg(), '') |
37
|
|
|
) |
38
|
|
|
); |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
return $delegate->process( |
42
|
|
|
$request |
43
|
|
|
->withAttribute(self::RAW_BODY_ATTRIBUTE, $rawBody) |
44
|
|
|
->withAttribute(self::JSON_OBJECT_ATTRIBUTE, json_decode($rawBody)) |
45
|
|
|
->withParsedBody($parsedBody) |
46
|
|
|
); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
private function match($contentType) |
50
|
|
|
{ |
51
|
|
|
$parts = explode(';', $contentType); |
52
|
|
|
$mime = array_shift($parts); |
53
|
|
|
return (bool)preg_match('#[/+]json$#', trim($mime)); |
54
|
|
|
} |
55
|
|
|
} |