Skip to content

Commit 7ffef41

Browse files
committed
Introduced alternative way to pass params to the target action.
1 parent c9cbfab commit 7ffef41

File tree

4 files changed

+113
-13
lines changed

4 files changed

+113
-13
lines changed

Action.php

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use yii\base\InvalidRouteException;
66
use yii\base\UserException;
77
use yii\helpers\Json;
8+
use yii\web\NotFoundHttpException;
9+
use yii\web\Request;
810

911
/**
1012
* Class Action
@@ -17,6 +19,11 @@
1719
*/
1820
class Action extends \yii\base\Action {
1921

22+
/** @var Request $originalYiiRequest */
23+
private $originalYiiRequest;
24+
25+
public $paramsPassMethod;
26+
2027
/**
2128
* Parses json body.
2229
* @param $rawBody
@@ -39,7 +46,8 @@ public function parseJsonRpcBody($rawBody) {
3946

4047

4148
/**
42-
* Validates method string and converts it into a route.
49+
* Validates method string and converts it into a route, which is going to be parsed by UrlManager before executing
50+
* the request.
4351
* @param $method
4452
* @return bool|string
4553
*/
@@ -80,7 +88,7 @@ public function parseRequest($request) {
8088
throw new JsonRpcException($request->id, "The JSON sent is not a correct JSON-RPC request - missing or incorrect method.", JSON_RPC_ERROR_REQUEST_INVALID);
8189
}
8290

83-
$params = null;
91+
$params = [];
8492
if (isset($request->params)) {
8593
$params = (array) $request->params;
8694
}
@@ -121,30 +129,79 @@ public function parseRequests($params) {
121129
throw new JsonRpcException(null, "The JSON sent is not a correct JSON-RPC request.", JSON_RPC_ERROR_REQUEST_INVALID);
122130
}
123131

132+
/**
133+
* Preserves original Yii request.
134+
* @param $request
135+
* @return $this
136+
*/
137+
protected function preserveYiiRequest() {
138+
$this->originalYiiRequest = clone \Yii::$app->request;
139+
return $this;
140+
}
141+
142+
protected function restoreYiiRequest() {
143+
\Yii::$app->request->setUrl($this->originalYiiRequest->getUrl());
144+
\Yii::$app->request->setPathInfo($this->originalYiiRequest->getPathInfo());
145+
\Yii::$app->request->setBodyParams($this->originalYiiRequest->getBodyParams());
146+
\Yii::$app->request->setQueryParams($this->originalYiiRequest->getQueryParams());
147+
\Yii::$app->request->setRawBody($this->originalYiiRequest->getRawBody());
148+
return $this;
149+
}
150+
124151
/**
125152
* Executes JSON-RPC request by route.
126-
* @param JsonRpcRequest $request
153+
* @param JsonRpcRequest $jsonRpcRequest
127154
* @return JsonRpcException|mixed
128155
*/
129-
public function executeRequest($request) {
130-
$route = $request->route;
156+
public function executeRequest($jsonRpcRequest) {
157+
$this->preserveYiiRequest();
158+
$route = $jsonRpcRequest->route;
131159
try {
132-
\Yii::trace("Route requested: '$route'", __METHOD__);
160+
// Replacing requested URL and path info
161+
\Yii::$app->request->setUrl($route);
162+
\Yii::$app->request->setPathInfo(null);
163+
164+
try {
165+
$routeWithParams = \Yii::$app->request->resolve();
166+
}
167+
catch (NotFoundHttpException $exception) {
168+
$routeWithParams = false;
169+
}
170+
171+
if (!$routeWithParams) {
172+
$this->restoreYiiRequest();
173+
return new JsonRpcException($jsonRpcRequest->id, 'Method not found: ' . $route . '.',
174+
JSON_RPC_ERROR_METHOD_NOT_FOUND);
175+
}
176+
list($routeParsed, $params) = $routeWithParams;
177+
178+
// Replacing route
133179
\Yii::$app->requestedRoute = $route;
134-
$result = \Yii::$app->runAction($request->route, $request->params);
180+
if ($this->paramsPassMethod == JSON_RPC_PARAMS_PASS_BODY) {
181+
\Yii::$app->request->setBodyParams($jsonRpcRequest->params);
182+
\Yii::$app->request->setRawBody(Json::encode($jsonRpcRequest->params));
183+
$result = \Yii::$app->runAction($routeParsed, $params);
184+
}
185+
else {
186+
$params += $jsonRpcRequest->params;
187+
$result = \Yii::$app->runAction($routeParsed, $params);
188+
}
189+
$this->restoreYiiRequest();
190+
135191
return $result;
136192
}
137193
catch (\Exception $exception) {
138194
if ($exception instanceof InvalidRouteException) {
139-
$result = new JsonRpcException($request->id, 'Method not found: ' . $route . '.',
195+
$result = new JsonRpcException($jsonRpcRequest->id, 'Method not found: ' . $route . '.',
140196
JSON_RPC_ERROR_METHOD_NOT_FOUND, $exception);
141197
}
142198
else if ($exception instanceof JsonRpcException) {
143199
$result = $exception;
144200
}
145201
else {
146-
$result = new JsonRpcException($request->id, 'Internal error.', JSON_RPC_ERROR_INTERNAL, $exception);
202+
$result = new JsonRpcException($jsonRpcRequest->id, 'Internal error.', JSON_RPC_ERROR_INTERNAL, $exception);
147203
}
204+
$this->restoreYiiRequest();
148205

149206
return $result;
150207
}

Controller.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,25 @@
1212
const JSON_RPC_ERROR_METHOD_PARAMS_INVALID = -32602;
1313
const JSON_RPC_ERROR_INTERNAL = -32603;
1414

15+
// Pass params as function arguments
16+
const JSON_RPC_PARAMS_PASS_FUNCARGS = 1;
17+
18+
// Pass params as request body
19+
const JSON_RPC_PARAMS_PASS_BODY = 2;
20+
1521
class Controller extends \yii\web\Controller {
1622

23+
/**
24+
* @var int $paramsPassMethod Defines method to pass params to the target action.
25+
*/
26+
public $paramsPassMethod = JSON_RPC_PARAMS_PASS_FUNCARGS;
27+
1728
public function actions()
1829
{
1930
return [
2031
'index' => [
2132
'class' => Action::class,
33+
'paramsPassMethod' => $this->paramsPassMethod
2234
]
2335
];
2436
}

JsonRpcRequest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class JsonRpcRequest extends BaseObject {
1414

1515
public $id;
1616
public $route;
17-
public $params;
18-
public $originalRequest;
17+
public $params = [];
1918

2019
}

README.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,32 @@ Entry point:
1414
<?php
1515

1616
namespace app\controllers;
17+
use \georgique\yii2\json-rpc\Controller;
1718

18-
class JsonRpcController extends \georgique\yii2\json-rpc\Controller {
19+
class JsonRpcController extends Controller {
1920

2021
// Practically you don't need anything else in this controller,
2122
// unless you want to customize entry point somehow.
2223

2324
}
2425
```
2526

27+
Entry point with different way to pass params:
28+
```php
29+
<?php
30+
31+
namespace app\controllers;
32+
use \georgique\yii2\json-rpc\Controller;
33+
34+
class JsonRpcBodyController extends Controller {
35+
36+
// With the customization JSON RPC params will be passed to the target action
37+
// as request body params, not as action function arguments
38+
public $paramsPassMethod = JSON_RPC_PARAMS_PASS_BODY;
39+
40+
}
41+
```
42+
2643
Controller with target actions which we are going to call:
2744
```php
2845
<?php
@@ -47,6 +64,16 @@ class ExampleController extends \yii\web\Controller {
4764
public function actionTryWithParams($foo) {
4865
return "Params received: \$foo = $foo.";
4966
}
67+
68+
// Passing params as Yii request body params must be handy too, when we need to do a bulk
69+
// attribute assignment for example.
70+
public function actionTryWithBodyParams() {
71+
$output = "Params received: \n";
72+
foreach (\Yii::$app->request->getBodyParams() as $name => $value) {
73+
$output .= "$name = $value\n";
74+
}
75+
return $output;
76+
}
5077

5178
}
5279
```
@@ -59,6 +86,12 @@ Now this is how calls and responses will look like:
5986
-> {"jsonrpc": "2.0", "method": "api1.example.try-with-params", "params": {"foo": "bar"}, "id": 2}
6087
<- {"jsonrpc": "2.0", "result": "Params received: $foo = bar.", "id": 2}
6188
89+
// Using alternative entry point:
90+
-> {"jsonrpc": "2.0", "method": "api1.example.try-with-body-params", "params": {"foo": "bar"}, "id": 2}
91+
<- {"jsonrpc": "2.0", "result": "Params received:
92+
$foo = bar.
93+
", "id": 2}
94+
6295
-> {"jsonrpc": "2.0", "method": "api1.example.garbage", "id": 3}
6396
<- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": 3}
6497
@@ -74,5 +107,4 @@ Now this is how calls and responses will look like:
74107
]
75108
```
76109

77-
78110
Author: George Shestayev [email protected]

0 commit comments

Comments
 (0)