comodojo/rpcserver documentation

This library provides a framework (and transport) independent XML and JSON(2.0) RPC server.

It is designed to work in combination with a REST framework that could handle the transport side (such as comodojo/dispatcher).

Main features are:

  • full XMLRPC and JSONRPC(2.0) protocols support, including multicall and batch requests
  • embedded introspection methods
  • PSR-3 compliant logging
  • payload decoding/econding and encryption
  • support for multiple signatures per method

Following capabilities are supported out of the box:

Additional capabilities could be implemented Extending the library.

Installation

First install composer, then:

composer require comodojo/rpcserver

Requirements

To work properly, comodojo/rpcserver requires PHP >=5.6.0.

Basic Usage

Following a quick and dirty example of lib basic usage, without a framework that mediates RPC requests.

Note

For more detailed informations, please see Using the RPC Server and Creating methods pages.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 <?php

 use \Comodojo\RpcServer\RpcServer;
 use \Comodojo\RpcServer\RpcMethod;
 use \Exception;

 // get the raw request payload (using, for example, an HTTP::POST)
 $payload = file_get_contents('php://input');

 try {

     // create a RpcServer instance (i.e. JSON)
     $server = new RpcServer(RpcServer::JSONRPC);

     // create a method (using a lambda functions)
     $method = RpcMethod::create("example.sum", function($params) {
             $a = $params->get('a');
             $b = $params->get('b');
             return intval($a) + intval($b);
     })
     ->setDescription("Sum two integers")
     ->setReturnType('int')
     ->addParameter('int','a')
     ->addParameter('int','b');

     // register newly created method into server
     $server->getMethods()->add($method);

     // set the payload
     $server->setPayload($request);

     // serve the request
     $result = $server->serve();

 } catch (Exception $e) {

     /* something did not work :( */
     throw $e;

 }

 echo $result;

Creating methods

The \Comodojo\RpcServer\RpcMethod class should can be used to create custom RPC methods to inject into server.

It requires basically a method name and a callable, provided as lambda function, named function or couple class::method.

Parameters can be added using RpcMethod::addParameter; multiple signatures can be specified using the RpcMethod::addSignature method.

For example, to create a my.method RPC method mapped to \My\RpcClass::mymethod() that supports two different signatures:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 <?php

 use \Comodojo\RpcServer\RpcMethod;

 // create a method using class::method pattern
 $method = RpcMethod::create('my.method', '\My\RpcClass::mymethod')
     // provide a description for the method
     ->setDescription("My method")

     // for now on, parameters and return type will be associated
     // to the first (default) signature, until next addSignature() marker

     // set the return type (default: undefined)
     ->setReturnType('boolean')

     // start another signature, the second one
     ->addSignature()

     // set the return type for second signature
     ->setReturnType('boolean')

     // add expected parameters (if any) for second signature
     ->addParameter('int','a')
     ->addParameter('int','b');

Note

Signatures are automatically matched by the server as well as received parameters.

If a request does not match any valid signature, an Invalid params (-32602) error is returned to the client.

Defining Callbacks

As in previous example, the \My\RpcClass::mymethod() has to be created to handle the request.

This method should expect a \Comodojo\RpcServer\Request\Parameters object that provides:

  • received parameters (Parameters::get)
  • server properties
    • capabilities (Parameters::getCapabilities)
    • methods (Parameters::getMethods)
    • errors (Parameters::getErrors)
  • RPC protocol in use (Parameters::getProtocol)
  • logging interface (Parameters::getLogger)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 <?php

 use \Comodojo\RpcServer\Request\Parameters;

 class RpcClass {

     public static function mymethod(Parameters $params) {

         // retrieve 'a' param
         $a = $params->get('a');

         // retrieve 'b' param
         $b = $params->get('b');

         // get current PSR-3 logger
         $logger = $params->getLogger();

         // get current protocol
         $current_rpc_protocol = $params->getProtocol();

         // log something...
         $logger->info("mymethod called, current protocol: $current_rpc_protocol, parameters in context", [$a, $b]);

         return $a === $b;

     }

 }

Injecting extra arguments

In case the callback method needs extra arguments in input, they should be specified as additional arguments in method declaration.

Server will transfer them when callback is fired.

As an example, a method declaration like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 <?php

 use \Comodojo\RpcServer\RpcMethod;

 // create a method that transfer two additional arguments
 $method = RpcMethod::create(
     'my.method',
     '\My\RpcClass::mymethod',
     \My\Extra\Attribute $attribute,
     $another_attribute
 )
 ->setDescription("My method")
 ->setReturnType('boolean');

Will invoke a callback like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 <?php

 use \Comodojo\RpcServer\Request\Parameters;
 use \My\Extra\Attribute;

 class RpcClass {

     public static function mymethod(
         Parameters $params,
         Attribute $attribute,
         $another_attribute
     ) {

         // ... method internals

     }

 }

Using the RPC Server

The class \Comodojo\RpcServer\RpcServer realizes the core server component.

Note

As already mentioned, the server component does not provide transport management but just the logic to understand and serve RPC requests.

Other frameworks or custom implementations can be used to mediates requests using HTTP, sockets or any other message-delivery transport.

An RPC Server should be created specifying the desired RPC protocol; constants RpcServer::JSONRPC and RpcServer::XMLRPC are available to setup server correctly.

The optional parameter $logger expects an implementation of \Psr\Log\LoggerInterface and implicitly enable internal logging.

Once created, server expects a payload, and starts processing it when RpcServer::serve method is invoked:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 <?php

 use \Comodojo\RpcServer\RpcServer;

 // create the server
 $server = new RpcServer(RpcServer::XMLRPC);

 // (optional) set encoding (default to *utf-8*)
 $server->setEncoding('ISO-8859-1');

 // feed server with request's payload and start serving the request
 $result = $server->setPayload($request)->serve();

Encrypting communications

This package provides a non-standard PSK message-level encryption (using AES).

This working mode could be enabled specifying the pre shared key using RpcServer::setEncryption method.

Note

The only client that supports this communication mode is the one provided by comodojo/rpcclient package.

Extending the library

Beside RPC methods, server capabilities and errors can be added or removed using dedicated server methods.

Server Capabilities

The RpcServer::getCapabilites allows access to capabilities manager that can be used to modify standard supported capabilities.

For example, to add a new capability:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 <?php

 use \Comodojo\RpcServer\RpcServer;

 // init the server
 $server = new RpcServer(RpcServer::JSONRPC);

 // ad a new capability
 $capabilities = $server->getCapabilities();
 $capabilities->add("my.capability", "http://url.to.my/capability", 1.0);

Custom Errors

Errors can be managed using the RpcServer::getErrors method.

For example, to add a new error:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 <?php

 use \Comodojo\RpcServer\RpcServer;

 // init the server
 $server = new RpcServer(RpcServer::JSONRPC);

 // ad a new capability
 $errors = $server->getErrors();
 $errors->add(-31010, "Transphasic torpedo was banned by the United Federation of Planets");