php-json-rpc/src/Server/JsonRpcServer.php

139 lines
3.8 KiB
PHP
Raw Normal View History

2019-01-05 03:25:30 +00:00
<?php
namespace JsonRpc\Server;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class JsonRpcServer
{
const Rpc_Error_Parse_Error = -32700;
const Rpc_Error_Invalid_Request = -32600;
const Rpc_Error_NOT_FOUND = -32601;
const Rpc_Error_Invalid_Params = -32602;
const Rpc_Error_Internal_Error = -32603;
const ErrorMsg = [
self::Rpc_Error_NOT_FOUND => 'Method not found',
self::Rpc_Error_Parse_Error => 'Json parse error',
self::Rpc_Error_Invalid_Request => 'Invalid request',
self::Rpc_Error_Invalid_Params => 'Invalid params',
];
/**
* @var Request
*/
public $request;
public function __construct($config)
{
2019-01-05 04:47:51 +00:00
$this->config = $config;
2019-01-05 03:25:30 +00:00
$this->request = function_exists('app') ? app('request') : Request::capture();
2019-01-05 04:47:51 +00:00
$this->map = require_once $config['map'];
2019-01-05 03:25:30 +00:00
}
public function handler()
{
2019-01-05 04:47:51 +00:00
// if ($this->request->getContentType() != 'json') {
// return $this->error(self::Rpc_Error_Invalid_Request);
// }
2019-01-05 03:25:30 +00:00
try {
2019-01-05 04:47:51 +00:00
if ($this->request->method() == Request::METHOD_GET) {
$method = $this->request->input('method');
$id = $this->request->input('id');
$params = \GuzzleHttp\json_decode($this->request->input('params'),true);
} else {
list($method, $params, $id) = $this->parseJson($this->request->getContent());
}
2019-01-14 04:03:47 +00:00
app('log')->info('rpc ser', [$method, $params, $id, $this->request->header('client_app')]);
2019-01-05 04:47:51 +00:00
list($class, $function) = $this->parseMethodWithMap($method);
// dump($class,$function);exit;
2019-01-05 03:25:30 +00:00
if (!class_exists($class) || !method_exists($class, $function)) {
return $this->error(self::Rpc_Error_NOT_FOUND);
}
if (!$this->isEnoughParameter($class, $function, $params)) {
return $this->error(self::Rpc_Error_Invalid_Params);
}
$ret = call_user_func_array([(new $class($id, $this->request)), $function], $params);
return $ret;
} catch (\InvalidArgumentException $e) {
return $this->error(self::Rpc_Error_Parse_Error);
}
}
protected function parseJson($data)
{
$data = \GuzzleHttp\json_decode($data, true);
$method = $data['method'];
$params = $data['params'];
$id = $data['id'];
return [$method, $params, $id];
}
2019-01-05 04:47:51 +00:00
protected function parseMethodWithMap($method)
{
return isset($this->map[$method]) ? $this->map[$method] : ['', ''];
}
2019-01-05 03:25:30 +00:00
protected function parseMethod($method)
{
$method = explode('.', $method);
if (count($method) < 2) {
return ['', ''];
}
$function = array_pop($method);
$class = 'Rpc' . ucwords(array_pop($method));
foreach ($method as $one) {
$class = ucwords($one) . '\\' . $class;
}
$class = "App\Rpc\\$class";
return [$class, $function];
}
protected function isEnoughParameter($class, $method, $parameters)
{
$r = new \ReflectionMethod($class, $method);
$params = $r->getParameters();
$n = 0;
foreach ($params as $param) {
//$param is an instance of ReflectionParameter
if (!$param->isOptional()) {
$n++;
}
}
return count($parameters) >= $n;
}
protected function error($code, $msg = null, $id = null)
{
if ($msg === null) {
$msg = isset(self::ErrorMsg[$code]) ? self::ErrorMsg[$code] : 'undefined';
}
return JsonResponse::create([
'jsonrpc' => '2.0',
'error' => [
'code' => $code,
'message' => $msg,
],
'id' => $id
]);
}
}