SOA (рд╕рд░реНрд╡рд┐рд╕ рдУрд░рд┐рдПрдВрдЯреЗрдб рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░) рдХрд╛ рд╕рдВрдпреЛрдЬрди рдФрд░ рдвреАрд▓реА рдХрдкрд▓ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдкрд░рд╕реНрдкрд░ рдХреНрд░рд┐рдпрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИредрдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рджреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди, рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рджреВрд░рд╕реНрде рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЙрд▓ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдирдХреА рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░реЗрдВрдЧреЗ JSON-RPC 2.0
редрдЧреНрд░рд╛рд╣рдХ
рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреБрдЫ рд╕рд╛рдордЧреНрд░реА рдмрдирд╛рдиреЗ рдФрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдЗрдЯ рд╣реИред рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдкрд╛рд╕ рд╕реНрд╡рдпрдВ рдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХреЗ рдХрд╛рд░рдг рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИредрдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░, рдЗрдВрдЯрд░реИрдХреНрд╢рди рдПрдХ рд╡рд░реНрдЧ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИJsonRpcClient
namespace ClientApp\Services;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
class JsonRpcClient
{
const JSON_RPC_VERSION = '2.0';
const METHOD_URI = 'data';
protected $client;
public function __construct()
{
$this->client = new Client([
'headers' => ['Content-Type' => 'application/json'],
'base_uri' => config('services.data.base_uri')
]);
}
public function send(string $method, array $params): array
{
$response = $this->client
->post(self::METHOD_URI, [
RequestOptions::JSON => [
'jsonrpc' => self::JSON_RPC_VERSION,
'id' => time(),
'method' => $method,
'params' => $params
]
])->getBody()->getContents();
return json_decode($response, true);
}
}
рд╣рдореЗрдВ рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ GuzzleHttp
, рдЗрд╕реЗ рдкреВрд░реНрд╡-рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВредрд╣рдо рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдорд╛рдирдХ POST
рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ GuzzleHttp\Client
ред рдпрд╣рд╛рдБ рдореБрдЦреНрдп рдЪреЗрддрд╛рд╡рдиреА рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рд░реВрдк рд╣реИредрд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░, JSON-RPC 2.0
рдЕрдиреБрд░реЛрдз рдХреЛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:{
"jsonrpc": "2.0",
"method": "getPageById",
"params": {
"page_uid": "f09f7c040131"
},
"id": "54645"
}
jsonrpc
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕рдВрд╕реНрдХрд░рдг, "2.0" рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПmethod
рд╡рд┐рдзрд┐ рдХрд╛ рдирд╛рдоparams
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд░рдгреАid
рдЕрдиреБрд░реЛрдз рдЖрдИрдбреА
рдЙрддреНрддрд░{
"jsonrpc": "2.0",
"result": {
"id": 2,
"title": "Index Page",
"content": "Content",
"description": "Description",
"page_uid": "f09f7c040131"
},
"id": "54645"
}
рдпрджрд┐ рдЕрдиреБрд░реЛрдз рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рдерд╛, рддреЛ рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ{
"jsonrpc": "2.0",
"error": {
"code": -32700,
"message": "Parse error"
},
"id": "null"
}
jsonrpc
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕рдВрд╕реНрдХрд░рдг, "2.0" рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПresult
рдПрдХ рд╕рдлрд▓ рдХреНрд╡реЗрд░реА рдкрд░рд┐рдгрд╛рдо рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдбред рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПerror
рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдЬрдм рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИред рд╕рдлрд▓ рдкрд░рд┐рдгрд╛рдо рдкрд░ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПid
рдЧреНрд░рд╛рд╣рдХ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдЕрдиреБрд░реЛрдз
рд╕рд░реНрд╡рд░ рдЙрддреНрддрд░ рдмрдирд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдореЗрдВ рд╡рд╛рдкрд╕ рдЖрдПрдВрдЧреЗредрдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ, рдЖрд╡рд╢реНрдпрдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреБрд░реЛрдз рдмрдирд╛рдиреЗ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИредnamespace ClientApp\Http\Controllers;
use App\Services\JsonRpcClient;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
class SiteController extends Controller
{
protected $client;
public function __construct(JsonRpcClient $client)
{
$this->client = $client;
}
public function show(Request $request)
{
$data = $this->client->send('getPageById', ['page_uid' => $request->get('page_uid')]);
if (empty($data['result'])) {
abort(404);
}
return view('page', ['data' => $data['result']]);
}
public function create()
{
return view('create-form');
}
public function store(Request $request)
{
$data = $this->client->send('create', $request->all());
if (isset($data['error'])) {
return Redirect::back()->withErrors($data['error']);
}
return view('page', ['data' => $data['result']]);
}
}
JSON-RPC рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрд╡рд░реВрдк рдпрд╣ рджреЗрдЦрдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЕрдиреБрд░реЛрдз рд╕рдлрд▓ рд░рд╣рд╛ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рдХреЛрдИ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░реЗрдВредрд╕рд░реНрд╡рд░
рдЪрд▓реЛ рд░реВрдЯрд┐рдВрдЧ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдХреЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдлрд╝рд╛рдЗрд▓ routes/api.php
рдРрдб рдореЗрдВRoute::post('/data', function (Request $request, JsonRpcServer $server, DataController $controller) {
return $server->handle($request, $controller);
});
рдкрддреЗ рдкрд░ рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рд╕рднреА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ <server_base_uri>/data
рдХрдХреНрд╖рд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛JsonRpcServer
namespace ServerApp\Services;
class JsonRpcServer
{
public function handle(Request $request, Controller $controller)
{
try {
$content = json_decode($request->getContent(), true);
if (empty($content)) {
throw new JsonRpcException('Parse error', JsonRpcException::PARSE_ERROR);
}
$result = $controller->{$content['method']}(...[$content['params']]);
return JsonRpcResponse::success($result, $content['id']);
} catch (\Exception $e) {
return JsonRpcResponse::error($e->getMessage());
}
}
}
рдХрдХреНрд╖рд╛ JsonRpcServer
рдЙрддреНрддреАрд░реНрдг рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд╛рдВрдЫрд┐рдд рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐ рдХреЛ рдмрд╛рдВрдзрддреА рд╣реИред рдФрд░ рдпрд╣ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд JsonRpcResponse
рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрддрд╛ JSON-RPC 2.0
рд╣реИредuse ServerApp\Http\Response;
class JsonRpcResponse
{
const JSON_RPC_VERSION = '2.0';
public static function success($result, string $id = null)
{
return [
'jsonrpc' => self::JSON_RPC_VERSION,
'result' => $result,
'id' => $id,
];
}
public static function error($error)
{
return [
'jsonrpc' => self::JSON_RPC_VERSION,
'error' => $error,
'id' => null,
];
}
}
рдпрд╣ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИредnamespace ServerApp\Http\Controllers;
class DataController extends Controller
{
public function getPageById(array $params)
{
$data = Data::where('page_uid', $params['page_uid'])->first();
return $data;
}
public function create(array $params)
{
$data = DataCreate::create($params);
return $data;
}
}
рдореБрдЭреЗ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рдирд╣реАрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рдХрд╛рдлреА рдорд╛рдирдХ рддрд░реАрдХреЗред рдХрдХреНрд╖рд╛ DataCreate
рдореЗрдВ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд╕рднреА рддрд░реНрдХ рд╣реЛрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдЖрд╡рд╢реНрдпрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рдлреЗрдВрдХрдиреЗ рдХреЗ рд╕рд╛рде рдЦреЗрддреЛрдВ рдХреА рд╡реИрдзрддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИредрдирд┐рд╖реНрдХрд░реНрд╖
рдореИрдВрдиреЗ рд╕реНрд╡рдпрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рддрд░реНрдХ рдХреЛ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдЙрдирдХреА рдмрд╛рддрдЪреАрдд рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд┐рдпрд╛редJSON-RPC рдХреЗ рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖реЛрдВ рдХреЛ рдПрдХ рд▓реЗрдЦ рдореЗрдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХреА рдПрдХ рдХрдбрд╝реА рдореИрдВ рдиреАрдЪреЗ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдореНрдмреЗрдбреЗрдб рд░реВрдкреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордпредрд╕рдВрджрд░реНрдн