-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathAction.php
147 lines (130 loc) · 4.7 KB
/
Action.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
namespace georgique\yii2\jsonrpc;
use georgique\yii2\jsonrpc\exceptions\JsonRpcException;
use georgique\yii2\jsonrpc\exceptions\InternalErrorException;
use georgique\yii2\jsonrpc\exceptions\InvalidRequestException;
use georgique\yii2\jsonrpc\exceptions\ParseErrorException;
use georgique\yii2\jsonrpc\responses\ErrorResponse;
use georgique\yii2\jsonrpc\responses\SuccessResponse;
use yii\base\InvalidArgumentException;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\web\Request;
/**
* Class Action
*
* Standalone action responsible for parsing json-rpc request, executing it
* and formatting json-rpc response.
*
* @author George Shestayev [email protected]
* @package georgique\yii2\jsonrpc
*/
class Action extends \yii\base\Action
{
/** @var Request $originalYiiRequest */
private $originalYiiRequest;
/**
* @var int $paramsPassMethod Defines method to pass params to the target action.
*/
public $paramsPassMethod;
/**
* @var array Whether JSON parse should parse objects in `params` as associate arrays or objects
*/
public $requestParseAsArray;
/**
* Parses json body.
* @param $rawBody
* @return mixed
* @throws InvalidRequestException
* @throws ParseErrorException
*/
public function parseJsonRpcBody($rawBody)
{
try {
$parameters = Json::decode($rawBody, false);
if (!$parameters) {
throw new InvalidRequestException();
}
return $parameters;
} catch (InvalidArgumentException $e) {
throw new ParseErrorException('', [], $e);
}
}
/**
* Preserves original Yii request.
* @return $this
*/
protected function preserveYiiRequest()
{
$this->originalYiiRequest = clone \Yii::$app->request;
return $this;
}
/**
* @return $this
* @throws \yii\base\InvalidConfigException
*/
protected function restoreYiiRequest()
{
\Yii::$app->request->setUrl($this->originalYiiRequest->getUrl());
\Yii::$app->request->setPathInfo($this->originalYiiRequest->getPathInfo());
\Yii::$app->request->setBaseUrl($this->originalYiiRequest->getBaseUrl());
\Yii::$app->request->setBodyParams($this->originalYiiRequest->getBodyParams());
\Yii::$app->request->setQueryParams($this->originalYiiRequest->getQueryParams());
\Yii::$app->request->setRawBody($this->originalYiiRequest->getRawBody());
return $this;
}
/**
* @inheritdoc
*/
public function runWithParams($params)
{
$batchResponse = [];
try {
$isBatch = false;
$batchRequestData = $this->parseJsonRpcBody(\Yii::$app->request->getRawBody());
if (is_array($batchRequestData)) {
$isBatch = true;
} else {
// For simple processing
$batchRequestData = [$batchRequestData];
}
foreach ($batchRequestData as $requestData) {
$this->preserveYiiRequest();
try {
$request = new JsonRpcRequest();
$request->paramsPassMethod = $this->paramsPassMethod;
$request->parseAsArray = $this->requestParseAsArray;
$request->load(ArrayHelper::toArray($requestData), '');
if ($request->validate()) {
$result = $request->execute();
if (!is_null($request->id)) {
$batchResponse[] = new SuccessResponse($request, $result);
}
} else {
foreach ($request->getFirstErrors() as $attribute => $error) {
$request->$attribute = null;
}
throw new InvalidRequestException();
}
}
catch (InvalidRequestException $e) {
$batchResponse[] = new ErrorResponse($e, $request ?: null);
}
catch (JsonRpcException $e) {
// We do not return response to notifications
if ($request && !is_null($request->id)) {
$batchResponse[] = new ErrorResponse($e, $request ?: null);
}
}
$this->restoreYiiRequest();
}
}
catch (JsonRpcException $e) {
return new ErrorResponse($e);
}
catch (\Throwable $e) {
return new InternalErrorException('Error while processing request', [], $e);
}
return !$isBatch ? array_shift($batchResponse) : $batchResponse;
}
}