diff --git a/JsonRpc2/Controller.php b/JsonRpc2/Controller.php index 0227acb..c158834 100644 --- a/JsonRpc2/Controller.php +++ b/JsonRpc2/Controller.php @@ -49,7 +49,7 @@ public function runAction($id, $params = []) $resultData = [Helper::formatResponse(null, new Exception("Invalid Request", Exception::INVALID_REQUEST))]; } else { foreach ($requests as $request) { - if($response = $this->getActionResponse($request)) + if($response = $this->getActionResponse($request, $id)) $resultData[] = $response; } } @@ -67,11 +67,11 @@ public function runAction($id, $params = []) * @throws \yii\web\HttpException * @return Response */ - private function getActionResponse($requestObject) + private function getActionResponse($requestObject, $id) { $this->requestObject = $result = $error = null; try { - $this->parseAndValidateRequestObject($requestObject); + $this->parseAndValidateRequestObject($requestObject, $id); ob_start(); $dirtyResult = parent::runAction($this->requestObject->method); ob_clean(); @@ -178,7 +178,7 @@ public function bindActionParams($action, $params) * Request has to be sent as POST and with Content-type: application/json * @throws \yii\web\HttpException */ - private function initRequest($id) + protected function initRequest($id) { list($contentType) = explode(";", Yii::$app->request->getContentType()); //cut charset if (!empty($id) || !Yii::$app->request->getIsPost() || empty($contentType) || $contentType != "application/json") @@ -190,7 +190,7 @@ private function initRequest($id) * @param $requestObject string * @throws Exception */ - private function parseAndValidateRequestObject($requestObject) + protected function parseAndValidateRequestObject($requestObject, $id) { if (null === $requestObject) throw new Exception("Parse error", Exception::PARSE_ERROR); diff --git a/JsonRpc2/LightMethodProtocolTrait.php b/JsonRpc2/LightMethodProtocolTrait.php new file mode 100644 index 0000000..7b9c20e --- /dev/null +++ b/JsonRpc2/LightMethodProtocolTrait.php @@ -0,0 +1,83 @@ + + */ +trait LightMethodProtocolTrait +{ + /** + * @inheritdoc + */ + protected function initRequest($id) + { + // parent will throw an exception if $id is non-empty, but we want to + // allow a non-empty $id in Light-mode + parent::initRequest(''); + } + + /** + * @inheritdoc + */ + protected function parseAndValidateRequestObject($requestObject, $id) + { + if ($requestObject !== null) + { + // if method is specified both in the URL and in the $id, and + // they do not match, we throw an error + if (!empty($requestObject->method) && !empty($id) && $requestObject->method != $id) + { + throw new Exception("Invalid Request - method mismatch", Exception::INVALID_REQUEST); + } + + // if the $requestObject method is not specified or isn't a string, + // use the $id from the URL instead + if ((empty($requestObject->method) || "string" != gettype($requestObject->method)) && !empty($id)) + { + $requestObject->method = $id; + } + } + + parent::parseAndValidateRequestObject($requestObject, ''); + } +} diff --git a/README.md b/README.md index 9f9ae88..4112aa9 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,56 @@ documentation for related information.
+###Light Method Protocol +If you wish, you may use a "light" method protocol that allows clients to +encode the method name in the URL instead of in the "method" parameter of the +request object. To do this, use the \JsonRpc2\LightMethodProtocolTrait in your +instance of \JsonRpc2\Controller like + +~~~php +class ServicesController extends \JsonRpc2\Controller +{ + use \JsonRpc2\LightMethodProtocolTrait; +} +~~~ + +One advantage of the light method format is that web server access logs will +contain the method invoked, because it is in the URL. The standard "heavy" +format will not, because the method is inside the POST data. + +Without the LightMethodProtocol, a client would post to +``` +http://yoursite/services +``` +with data +```javascript +{ + "jsonrpc": "2.0", + "id": 1, + "method": "update", + "params": ["world"] +} +``` + +However, with the LightMethodProtocol, a client could instead post to +``` +http://yoursite/services/update +``` +with data +```javascript +{ + "jsonrpc": "2.0", + "id": 1, + "params": ["world"] +} +``` + +The method may be specified both in the URL and in the request object +provided that they match. If the method is specified in both places, an +error is thrown if they do not match. + +
+ ###Params validation For validation params data you MUST create [phpDoc @param](http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.param.pkg.html) tags comments with type to action method.
After that param data will be converted to documented type.