From 64873e0bd514a3f3a38d59ad38023516f0cb916e Mon Sep 17 00:00:00 2001 From: Tyler Ham Date: Wed, 23 Sep 2015 19:04:39 -0500 Subject: [PATCH 1/2] Add a "light" method protocol option to support specifying the method in the URL --- JsonRpc2/Controller.php | 10 ++-- JsonRpc2/LightMethodProtocolTrait.php | 83 +++++++++++++++++++++++++++ README.md | 50 ++++++++++++++++ 3 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 JsonRpc2/LightMethodProtocolTrait.php 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..5476f3d --- /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..f128002 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,56 @@ documentation for related information.
+###Light Method Protocol +If you wish, you may uuse 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. From 7585b8267c620fd1416211392b80571c6fbca821 Mon Sep 17 00:00:00 2001 From: Tyler Ham Date: Fri, 25 Sep 2015 08:25:15 -0500 Subject: [PATCH 2/2] Fix typos in light method protocol documentation --- JsonRpc2/LightMethodProtocolTrait.php | 4 ++-- README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/JsonRpc2/LightMethodProtocolTrait.php b/JsonRpc2/LightMethodProtocolTrait.php index 5476f3d..7b9c20e 100644 --- a/JsonRpc2/LightMethodProtocolTrait.php +++ b/JsonRpc2/LightMethodProtocolTrait.php @@ -21,7 +21,7 @@ * "jsonrpc": "2.0", * "id": 1, * "method": "update", - * "params": ["world"}] + * "params": ["world"] * } * ``` * @@ -34,7 +34,7 @@ * { * "jsonrpc": "2.0", * "id": 1, - * "params": ["world"}] + * "params": ["world"] * } * ``` * diff --git a/README.md b/README.md index f128002..4112aa9 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ documentation for related information.
###Light Method Protocol -If you wish, you may uuse a "light" method protocol that allows clients to +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 @@ -139,7 +139,7 @@ with data "jsonrpc": "2.0", "id": 1, "method": "update", - "params": ["world"}] + "params": ["world"] } ``` @@ -152,7 +152,7 @@ with data { "jsonrpc": "2.0", "id": 1, - "params": ["world"}] + "params": ["world"] } ```