Skip to content

Instantly share code, notes, and snippets.

@bastman
Created November 7, 2011 11:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bastman/1344759 to your computer and use it in GitHub Desktop.
Save bastman/1344759 to your computer and use it in GitHub Desktop.
simple jsonrpc server howto php
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