Created
November 7, 2011 11:46
-
-
Save bastman/1344759 to your computer and use it in GitHub Desktop.
simple jsonrpc server howto php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
the request ... | |
================ | |
{ | |
"method":"foobar", | |
"params":["foo", "bar", "baz"] | |
} | |
the service ... | |
=============== | |
class MyService | |
{ | |
public function foobar($foo, $bar, $baz) | |
{ | |
return "HelloWord" | |
} | |
} | |
the dispatcher .... | |
=================== | |
class Dispatcher | |
{ | |
/** | |
* @throws Exception | |
* @return void | |
*/ | |
public function run() | |
{ | |
$this->_init(); | |
$responseData = array( | |
"result" => null, | |
"error" => null, | |
); | |
try { | |
$requestText = "" . $this->_fetchRequestText(); | |
$rpc = json_decode($requestText, true); | |
/* | |
$rpc = array( | |
"method"=>"foobar", | |
"params"=>array("foo","bar","baz"), | |
); | |
*/ | |
if (!is_array($rpc)) { | |
throw new Exception("Invalid rpc request"); | |
} | |
$rpcMethod = null; | |
if (array_key_exists("method", $rpc)) { | |
$rpcMethod = $rpc["method"]; | |
} | |
$rpcParams = $rpc["params"]; | |
if (array_key_exists("params", $rpc)) { | |
$rpcParams = $rpc["params"]; | |
if ($rpcParams === null) { | |
$rpcParams = array(); | |
} | |
} | |
if (!is_string($rpcMethod)) { | |
throw new Exception("Invalid rpc method"); | |
} | |
if (!is_array($rpcParams)) { | |
throw new Exception("Invalid rpc params"); | |
} | |
$service = new MyService(); | |
$reflectionClass = new ReflectionClass($service); | |
if (!$reflectionClass->hasMethod($rpcMethod)) { | |
throw new Exception("rpc method does not exist!"); | |
} | |
$reflectionMethod = $reflectionClass->getMethod($rpcMethod); | |
$this->_validateReflectionMethod($reflectionMethod); | |
$serviceResult = $reflectionMethod->invokeArgs( | |
$service, (array)$rpcParams | |
); | |
$responseData["result"] = $serviceResult; | |
} catch (Exception $e) { | |
$responseData["error"] = array( | |
"message" => $e->getMessage(), | |
); | |
} | |
$responseText = null; | |
try { | |
$responseText = json_encode($responseData); | |
} catch (Exception $e) { | |
} | |
if (!is_string($responseText)) { | |
$responseData = array( | |
"error" => array( | |
"message" => "error encoding rpc response", | |
), | |
"result" => null | |
); | |
$responseText = "".json_encode($responseData); | |
} | |
echo $responseText; | |
} | |
/** | |
* @throws ErrorException | |
* @return void | |
*/ | |
protected function _init() | |
{ | |
/* | |
RECOMMENDED SETUP | |
================= | |
*/ | |
ini_set("display_errors", true); | |
error_reporting(E_ALL|E_STRICT & ~E_NOTICE); | |
// php 5.3+ | |
set_error_handler(function($errno, $errstr, $errfile, $errline){ | |
throw new ErrorException($errstr, 0, $errno, $errfile, $errline); | |
}); | |
// php < 5.3 | |
/* | |
set_error_handler(array($this, "phpErrorHandler")); | |
*/ | |
} | |
/** | |
* for php<5.3 | |
* @throws ErrorException | |
* @param $errno | |
* @param $errstr | |
* @param $errfile | |
* @param $errline | |
* @return void | |
*/ | |
public function phpErrorHandler($errno, $errstr, $errfile, $errline) | |
{ | |
throw new ErrorException($errstr, 0, $errno, $errfile, $errline); | |
} | |
/** | |
* @return string | |
*/ | |
protected function _fetchRequestText() | |
{ | |
$requestText = file_get_contents('php://input'); | |
return $requestText; | |
} | |
/** | |
* @throws Exception | |
* @param ReflectionMethod $reflectionMethod | |
* @return void | |
*/ | |
protected function _validateReflectionMethod( | |
ReflectionMethod $reflectionMethod | |
) | |
{ | |
$reflectionMethodName = $reflectionMethod->getName(); | |
if ($reflectionMethodName[0] === "_") { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
if (!$reflectionMethod->isPublic()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
if ($reflectionMethod->isStatic()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
if ($reflectionMethod->isAbstract()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
if ($reflectionMethod->isInternal()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
if(method_exists($reflectionMethod, "isConstructor")) { | |
if ($reflectionMethod->isConstructor()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
} | |
if(method_exists($reflectionMethod, "isDestructor")) { | |
if ($reflectionMethod->isDestructor()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
} | |
if(method_exists($reflectionMethod, "isClosure")) { | |
if ($reflectionMethod->isClosure()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
} | |
if(method_exists($reflectionMethod, "isDeprecated")) { | |
if ($reflectionMethod->isDeprecated()) { | |
throw new Exception("rpc method is not invokable!"); | |
} | |
} | |
} | |
} | |
the application: | |
================ | |
$dispatcher = new Dispatcher(); | |
$dispatcher->run(); | |
the response: | |
============= | |
{ | |
"result":"HelloWorld", | |
"error":null | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment