JsonRPC PHP Client and Server ============================= A simple Json-RPC client/server that just works. Features -------- - JSON-RPC 2.0 only - The server support batch requests and notifications - Authentication and IP based client restrictions - Custom Middleware - Fully unit tested - Requirements: PHP >= 5.3.4 - License: MIT Author ------ Frédéric Guillot Installation with Composer -------------------------- ```bash composer require fguillot/json-rpc @stable ``` Examples -------- ### Server Callback binding: ```php getProcedureHandler() ->withCallback('addition', function ($a, $b) { return $a + $b; }) ->withCallback('random', function ($start, $end) { return mt_rand($start, $end); }) ; echo $server->execute(); ``` Callback binding from array: ```php function() { return 'A'; }, 'getB' => function() { return 'B'; }, 'getC' => function() { return 'C'; } ); $server = new Server(); $server->getProcedureHandler()->withCallbackArray($callbacks); echo $server->execute(); ``` Class/Method binding: ```php getProcedureHandler(); // Bind the method Api::doSomething() to the procedure myProcedure $procedureHandler->withClassAndMethod('myProcedure', 'Api', 'doSomething'); // Use a class instance instead of the class name $procedureHandler->withClassAndMethod('mySecondProcedure', new Api, 'doSomething'); // The procedure and the method are the same $procedureHandler->withClassAndMethod('doSomething', 'Api'); // Attach the class, the client will be able to call directly Api::doSomething() $procedureHandler->withObject(new Api()); echo $server->execute(); ``` Class/Method binding from array: ```php array( 'MathApi', addition ), 'subtraction' => array( 'MathApi', subtraction ), 'multiplication' => array( 'MathApi', multiplication ), 'division' => array( 'MathApi', division ) ); $server = new Server(); $server->getProcedureHandler()->withClassAndMethodArray($callbacks); echo $server->execute(); ``` Server Middleware: Middleware might be used to authenticate and authorize the client. They are executed before each procedure. ```php getMiddlewareHandler()->withMiddleware(new MyMiddleware()); $server->getProcedureHandler()->withObject(new Api()); echo $server->execute(); ``` You can raise a `AuthenticationFailureException` when the API credentials are wrong or a `AccessDeniedException` when the user is not allowed to access to the procedure. ### Client Example with positional parameters: ```php execute('addition', [3, 5]); ``` Example with named arguments: ```php execute('random', ['end' => 10, 'start' => 1]); ``` Arguments are called in the right order. Examples with the magic method `__call()`: ```php random(50, 100); ``` The example above use positional arguments for the request and this one use named arguments: ```php $result = $client->random(['end' => 10, 'start' => 1]); ``` ### Client batch requests Call several procedures in a single HTTP request: ```php batch() ->foo(['arg1' => 'bar']) ->random(1, 100) ->add(4, 3) ->execute('add', [2, 5]) ->send(); print_r($results); ``` All results are stored at the same position of the call. ### Client exceptions Client exceptions are normally thrown when an error is returned by the server. You can change this behaviour by using the `$returnException` argument which causes exceptions to be returned. This can be extremely useful when executing the batch request. - `BadFunctionCallException`: Procedure not found on the server - `InvalidArgumentException`: Wrong procedure arguments - `JsonRPC\Exception\AccessDeniedException`: Access denied - `JsonRPC\Exception\ConnectionFailureException`: Connection failure - `JsonRPC\Exception\ServerErrorException`: Internal server error ### Enable client debugging You can enable the debug mode to see the JSON request and response: ```php getHttpClient()->withDebug(); ``` The debug output is sent to the PHP system logger. You can configure the log destination in your `php.ini`. Output example: ```json ==> Request: { "jsonrpc": "2.0", "method": "removeCategory", "id": 486782327, "params": [ 1 ] } ==> Response: { "jsonrpc": "2.0", "id": 486782327, "result": true } ``` ### IP based client restrictions The server can allow only some IP addresses: ```php allowHosts(['192.168.0.1', '127.0.0.1']); [...] // Return the response to the client echo $server->execute(); ``` If the client is blocked, you got a 403 Forbidden HTTP response. ### HTTP Basic Authentication If you use HTTPS, you can allow client by using a username/password. ```php authentication(['user1' => 'password1', 'user2' => 'password2']); [...] // Return the response to the client echo $server->execute(); ``` On the client, set credentials like that: ```php getHttpClient() ->withUsername('Foo') ->withPassword('Bar'); ``` If the authentication failed, the client throw a RuntimeException. Using an alternative authentication header: ```php use JsonRPC\Server; $server = new Server(); $server->setAuthenticationHeader('X-Authentication'); $server->authentication(['myusername' => 'mypassword']); ``` The example above will use the HTTP header `X-Authentication` instead of the standard `Authorization: Basic [BASE64_CREDENTIALS]`. The username/password values need be encoded in base64: `base64_encode('username:password')`. ### Local Exceptions By default, the server will relay all exceptions to the client. If you would like to relay only some of them, use the method `Server::withLocalException($exception)`: ```php withLocalException('MyException1') ->withLocalException('MyException2') ; [...] echo $server->execute(); ``` ### Callback before client request You can use a callback to change the HTTP headers or the URL before to make the request to the server. Example: ```php getHttpClient()->withBeforeRequestCallback(function(HttpClient $client, $payload) { $client->withHeaders(array('Content-Length: '.strlen($payload))); }); $client->myProcedure(123); ```