Skip to content

Commit 0e488c5

Browse files
committed
Better exception handling.
1 parent 7bf4326 commit 0e488c5

File tree

3 files changed

+62
-37
lines changed

3 files changed

+62
-37
lines changed

Action.php

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ public function parseJsonRpcBody($rawBody) {
2727
try {
2828
$parameters = Json::decode($rawBody, false);
2929
if (!$parameters) {
30-
throw new JsonRpcException('Could not parse JSON-RPC request body - empty result.', JSON_RPC_ERROR_REQUEST_INVALID);
30+
throw new JsonRpcException(null, 'Could not parse JSON-RPC request body - empty result.', JSON_RPC_ERROR_REQUEST_INVALID);
3131
}
3232

3333
return $parameters;
3434
}
3535
catch (JsonRpcException $e) {
36-
throw new JsonRpcException('Could not parse JSON-RPC request.', JSON_RPC_ERROR_PARSE, $e);
36+
throw new JsonRpcException(null, 'Could not parse JSON-RPC request.', JSON_RPC_ERROR_PARSE, $e);
3737
}
3838
}
3939

@@ -65,25 +65,26 @@ public function parseMethod($method) {
6565
* @throws \yii\base\InvalidConfigException
6666
*/
6767
public function parseRequest($request) {
68+
if (!isset($request->id)) {
69+
throw new JsonRpcException(null, "The JSON sent is not a correct JSON-RPC request - incorrect id.", JSON_RPC_ERROR_REQUEST_INVALID);
70+
}
71+
elseif (!is_int($request->id) && !ctype_digit($request->id)) {
72+
throw new JsonRpcException(null, "The JSON sent is not a correct JSON-RPC request - incorrect id.", JSON_RPC_ERROR_REQUEST_INVALID);
73+
}
74+
6875
if (!isset($request->jsonrpc) || $request->jsonrpc !== '2.0') {
69-
throw new JsonRpcException("The JSON sent is not a correct JSON-RPC request - missing or incorrect version.", JSON_RPC_ERROR_REQUEST_INVALID);
76+
throw new JsonRpcException($request->id, "The JSON sent is not a correct JSON-RPC request - missing or incorrect version.", JSON_RPC_ERROR_REQUEST_INVALID);
7077
}
7178

7279
if (!isset($request->method) || !is_string($request->method) || (!$route = $this->parseMethod($request->method))) {
73-
throw new JsonRpcException("The JSON sent is not a correct JSON-RPC request - missing or incorrect method.", JSON_RPC_ERROR_REQUEST_INVALID);
80+
throw new JsonRpcException($request->id, "The JSON sent is not a correct JSON-RPC request - missing or incorrect method.", JSON_RPC_ERROR_REQUEST_INVALID);
7481
}
7582

7683
$params = null;
7784
if (isset($request->params)) {
7885
$params = (array) $request->params;
7986
}
8087

81-
if (!isset($request->id)) {
82-
if (!is_int($request->id) && !ctype_digit($request->id)) {
83-
throw new JsonRpcException("The JSON sent is not a correct JSON-RPC request - incorrect id.", JSON_RPC_ERROR_REQUEST_INVALID);
84-
}
85-
}
86-
8788
return \Yii::createObject([
8889
'class' => JsonRpcRequest::className(),
8990
'id' => $request->id,
@@ -110,16 +111,14 @@ public function parseRequests($params) {
110111
$result = $this->parseRequest($request);
111112
}
112113
catch (\Exception $exception) {
113-
$result = ($exception instanceof JsonRpcException)
114-
? $exception
115-
: new JsonRpcException("Error happened during request parsing.", JSON_RPC_ERROR_INTERNAL, $exception);
114+
$result = $exception;
116115
}
117116
$results[] = $result;
118117
}
119118
return $results;
120119
}
121120

122-
throw new JsonRpcException("The JSON sent is not a correct JSON-RPC request.", JSON_RPC_ERROR_REQUEST_INVALID);
121+
throw new JsonRpcException(null, "The JSON sent is not a correct JSON-RPC request.", JSON_RPC_ERROR_REQUEST_INVALID);
123122
}
124123

125124
/**
@@ -137,14 +136,14 @@ public function executeRequest($request) {
137136
}
138137
catch (\Exception $exception) {
139138
if ($exception instanceof InvalidRouteException) {
140-
$result = new JsonRpcException('Method not found.', JSON_RPC_ERROR_METHOD_NOT_FOUND, $exception);
139+
$result = new JsonRpcException($request->id, 'Method not found: ' . $route . '.', JSON_RPC_ERROR_METHOD_NOT_FOUND);
141140
return $result;
142141
}
143142
else if ($exception instanceof JsonRpcException) {
144143
return $exception;
145144
}
146145
else {
147-
$result = new JsonRpcException('Internal error.', JSON_RPC_ERROR_INTERNAL, $exception);
146+
$result = new JsonRpcException($request->id, 'Internal error.', JSON_RPC_ERROR_INTERNAL);
148147
return $result;
149148
}
150149
}
@@ -154,14 +153,33 @@ public function executeRequest($request) {
154153
public function runWithParams($params)
155154
{
156155
// Parse errors will be caught and formatted by ErrorHandler
157-
$requests = $this->parseJsonRpcBody(file_get_contents('php://input'));
158-
$requestObjects = $this->parseRequests($requests);
156+
try {
157+
$requests = $this->parseJsonRpcBody(file_get_contents('php://input'));
158+
}
159+
catch (\Exception $e) {
160+
$this->renderError($e, null);
161+
}
162+
163+
try {
164+
$requestObjects = $this->parseRequests($requests);
165+
}
166+
catch (\Exception $e) {
167+
$this->renderError($e, null);
168+
}
159169

160170
$response = [];
161171
foreach ($requestObjects as $request) {
162-
$executionResult = $this->executeRequest($request);
163-
$renderMethod = ($executionResult instanceof \Exception) ? 'renderError' : 'renderSuccess';
164-
$response[] = $this->$renderMethod($executionResult, $request->id);
172+
if ($request instanceof JsonRpcRequest) {
173+
$executionResult = $this->executeRequest($request);
174+
$renderMethod = ($executionResult instanceof \Exception) ? 'renderError' : 'renderSuccess';
175+
$response[] = $this->$renderMethod($executionResult, $request->id);
176+
}
177+
elseif ($request instanceof JsonRpcException) {
178+
$this->renderError($request, $request->id);
179+
}
180+
else {
181+
$this->renderError($request, null);
182+
}
165183
}
166184

167185
return (sizeof($response) == 1) ? array_shift($response) : $response;
@@ -173,16 +191,19 @@ public function runWithParams($params)
173191
* @return array
174192
*/
175193
protected function renderException($exception) {
194+
176195
$result = [
177-
'code' => $exception->getCode(),
178196
'message' => $exception->getMessage(),
197+
'code' => ($exception instanceof JsonRpcException) ? $exception->getCode() : JSON_RPC_ERROR_INTERNAL
179198
];
180199

181-
$data = false;
200+
$data = [];
201+
if (!($exception instanceof JsonRpcException)) {
202+
$data['code'] = $exception->getCode();
203+
$data['type'] = get_class($exception);
204+
}
205+
182206
if (YII_DEBUG) {
183-
$data = [
184-
'type' => get_class($exception)
185-
];
186207
if (!$exception instanceof UserException) {
187208
$data += [
188209
'file' => $exception->getFile(),
@@ -194,18 +215,13 @@ protected function renderException($exception) {
194215
$data['error-info'] = $exception->errorInfo;
195216
}
196217
}
197-
}
198-
if (($prev = $exception->getPrevious()) !== null) {
199-
$data['previous'] = $this->renderException($prev);
218+
if (($prev = $exception->getPrevious()) !== null) {
219+
$data['previous'] = $this->renderException($prev);
220+
}
200221
}
201222

202-
if ($data) {
203-
if ($exception instanceof JsonRpcException) {
204-
$result['data'] = $data;
205-
}
206-
else {
207-
$result += $data;
208-
}
223+
if (!empty($data)) {
224+
$result['data'] = $data;
209225
}
210226

211227
return $result;

ErrorHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function renderException($exception)
4646
protected function convertExceptionToArray($exception)
4747
{
4848
if (!YII_DEBUG && !$exception instanceof JsonRpcException) {
49-
$exception = new JsonRpcException('Internal error.', JSON_RPC_ERROR_INTERNAL);
49+
$exception = new JsonRpcException(null, 'Internal error.', JSON_RPC_ERROR_INTERNAL);
5050
}
5151

5252
$errorArray = [

JsonRpcException.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
*/
1111
class JsonRpcException extends \yii\base\Exception {
1212

13+
public function __construct($id, $message = "", $code = 0, \Throwable $previous = null)
14+
{
15+
parent::__construct($message, $code, $previous);
16+
$this->id = $id;
17+
}
18+
19+
// Request ID if applicable
20+
public $id;
21+
1322
/**
1423
* @return string the user-friendly name of this exception
1524
*/

0 commit comments

Comments
 (0)