Skip to content

alanbem/Josser

Repository files navigation

Josser - JSON-RPC client for PHP 5.3+

Build Status

JSON-RPC? What is it?

JSON-RPC is a stateless, light-weight remote procedure call protocol encoded in JSON. It is a very simple protocol, defining only a handful of data types and commands.

Which specification of JSON-RPC does Josser support?

Josser supports [JSON-RPC 1.0] (http://json-rpc.org/wiki/specification) and [revised JSON-RPC 2.0] (http://www.jsonrpc.org/specification). Unfortunately only client-server connections are possible with Josser - albeit JSON-RPC 1.0 was designed as P2P - due to PHP limitations.

It is worth to mention that Josser's architecture allows to plug your own JSON-RPC flavours or implement existing semi-standardized JSON-RPC protocols e.g. abandoned JSON-RPC 1.1WD.

Transport mechanism

As specification (both 1.0 and 2.0) states, JSON-RPC is transport agnostic. Josser sticks to that and allows to use http, sockets, tcp/ip or anything else your project requires (like post-it notes on a fridge :D). Currently only http transport is implemented.

Documentation

Usage

Invoking remote methods is fairly simple:

<?php

namespace Josser;

use GuzzleHttp\Client;
use Josser\Client\Transport\Guzzle6Transport as HttpTransport; // there is also guzzle 5 implementation available
use Josser\Protocol\JsonRpc1;

$guzzle    = new Client(['base_uri' => 'http://user:password@your-service.com/math:8888']); // http client
$transport = new HttpTransport($guzzle); // RPC over http
$protocol  = new JsonRpc1; // lets use JSON-RPC 1.0

$client = new Client($transport, $protocol);

// send a request
$sum = $client->request('sum', array(5, 4));

var_dump($sum); // int(9)

If remote method does not return anything, notifications are what you need:

<?php

// instantiate client

$client->notify('logout');

Error handling

Josser informs about errors through  set of exceptions.

<?php

namespace Josser;

use Josser\Exception\RpcFaultException;
use Josser\Exception\TransportFailureException;
use Josser\Exception\RequestResponseMismatchException;
use Josser\Exception\InvalidResponseException;
use Josser\Exception\InvalidRequestException;

// instantiate client

try {
    $client->request('method', array(1, "param2"));
} catch (RpcFaultException $e) {
    echo 'Ups! Remote server sent an error.';
} catch (TransportFailureException $e) {
    echo 'Josser did not send remote call.';
} catch (RequestResponseMismatchException $e) {
    echo "Response id does not match request id.";
} catch (InvalidResponseException $e) {
    echo "Response object is invalid due to protocol constraints.";
} catch(InvalidRequestException $e) {
    echo "Request is invalid due to protocol constraints.";
}              

For convenience catch-all exception exists.

<?php

namespace Josser;

use Josser\Client;
use Josser\Exception\JosserException;

// instantiate client

try {
    $client->request('method', array(1, "param2"));
} catch (JosserException $e) {
    echo 'Josser error occurred.';
}           

Request objects

When you call remote procedures, those calls are internally translated into generic request objects.

<?php

namespace Josser;

use Josser\Client;
use Josser\Client\Request\Request;
use Josser\Client\Request\Notification;

// instantiate transport and protocol

$client = new Client($transport, $protocol);
$client->request('math.divide', array(1, 2));
$client->notify('system.logout');

// code above is equivalent of

$request = new Request('math.divide', array(1, 2), 213123); // 213123 is a request identifier
$client->call($request);

$notification = new Notification('system.logout');
$client->call($notification);

As you can see, you can work with those low-level objects directly but downside of this approach is that you must provide your own id for every request. By default Client::request() generates this id for you on its own. Also remember that Client::call() does not return result directly - it return response object instead. To get to underlying result data use Response::getResult() like this:

<?php

namespace Josser;

use Josser\Client;
use Josser\Client\Request\Request;
use Josser\Client\Request\Notification;

// instantiate client

$request = new Request('math.sum', array(2, 2), 6564653);
$response = $client->call($request);

var_dump($response->getResult()); // int(4)

Notice the possibility of creating your own, project specific, request objects.

<?php

namespace MyProject\Request;

use Josser\Client\Request\Request;

class Divide extends Request
{
    public function __construct($divident, $divisor)
    {
        $requestId = uniqid(); // random request id
        parent::__construct('math.divide', array($divident, $divisor), $requestId);
    }
}

About

Requirements

PHP >= 5.3

Submitting bugs and feature requests

Bugs and feature request are tracked on Github

Author

Alan Gabriel Bem - alan.bem@gmail.com

License

Josser is licensed under the MIT License - see the LICENSE file for details