Remoting NG

Remoting NG JSON-RPC Transport User Guide

Introduction

The JSON-RPC Transport is a very lightweight HTTP-based Transport implementation, supporting the JSON-RPC 2.0 protocol specification.

This transport is a good choice if web browser-based JavaScript applications need to invoke native methods on the server.

The JSON-RPC transport supports the following features:

  • HTTP compression (GZIP content transfer encoding) for requests and responses.
  • HTTP authentication (basic or digest, client only)
  • CORS (Cross-Origin Resource Sharing)
  • HTTPS

Basic JSON-RPC Transport Usage

Server Usage

To use the JSON-RPC Transport in a server, the following three steps must be performed:

  1. Register the Poco::RemotingNG::JSONRPC::TransportFactory with the ORB,
  2. Optionally configure the listener (e.g., to enable CORS),
  3. Register the Listener with the ORB, and finally,
  4. Register the individual objects with the ORB.

Following is an example code fragment for setting up a JSON-RPC Listener, configuring it to enable CORS (from any origin), and registering a service object for use with the listener.

Poco::RemotingNG::JSONRPC::Listener::Ptr pListener = new Poco::RemotingNG::JSONRPC::Listener("localhost:8080");
pListener->enableCORS(true);
std::string listener = Poco::RemotingNG::ORB::instance().registerListener(pListener);

st::string uri = Sample::TimeServiceServerHelper::registerObject(
    new Sample::TimeService, 
    "TheTimeService", 
    listener
);

Please see the Poco::RemotingNG::JSONRPC::Listener class documentation for detailed information about how to setup and configure the listener.

Client Usage

To use the JSON-RPC Transport in a client, the following two steps must be performed:

  1. Register the Poco::RemotingNG::JSONRPC::TransportFactory with the ORB, and
  2. Retrieve the interface (proxy) object using the helper class.

Following is an example code fragment for setting up a JSON-RPC Transport, and obtaining a Proxy object for invoking methods on the service object.

Poco::RemotingNG::JSONRPC::TransportFactory::registerFactory();
Sample::ITimeService::Ptr pTimeService = MyProject::MyClassHelper::find(
    "http://localhost:8080/jsonrpc/TimeService/TheTimeService");
);

Configuring The Client Transport

To configure the client transport (e.g., to , enable HTTP compression, or HTTP authentication), the Transport object must be obtained from the proxy. This is done in two steps. First, the interface pointer obtained from the client helper must be casted to a proxy:

Poco::RemotingNG::Proxy::Ptr pProxy = pTimeService.cast<Poco::RemotingNG::Proxy>();

Second, the Transport object can be obtained from the proxy:

Poco::RemotingNG::JSONRPC::Transport& trans = static_cast<Poco::RemotingNG::JSONRPC::Transport&>(pProxy->remoting__transport());

These two casts can also be put into a utility function transportFromInterface():

template <class I>
Poco::RemotingNG::JSONRPC::Transport& transportFromInterface(Poco::AutoPtr<I> pInterface)
{
    Poco::RemotingNG::Proxy::Ptr pProxy = pInterface.template cast<Poco::RemotingNG::Proxy>();
    if (pProxy)
    {
        return static_cast<Poco::RemotingNG::JSONRPC::Transport&>(pProxy->remoting__transport());
    }
    else throw Poco::BadCastException();
}

Using the transportFromInterface() function, we can write:

Poco::RemotingNG::JSONRPC::Transport& trans = transportFromInterface(pTimeService);

Now that we have access to the Transport object, we can configure it:

trans.enableCompression(true);

Configuration should be done before the first method is invoked over the proxy.

Please see the Poco::RemotingNG::JSONRPC::Transport class documentation for other configuration options, including timeouts and user-agent string.

Enabling HTTP Authentication

The JSON-RPC Transport supports HTTP Basic and Digest authentication. To enable authentication for a proxy object, first obtain the Transport object as shown in the previous section. HTTP Basic Authentication can then be enabled with:

trans.setAuthentication(Poco::RemotingNG::JSONRPC::Transport::AUTH_BASIC);
trans.setUsername("user");
trans.setPassword("s3cr3t");

To enable HTTP Digest Authentication:

trans.setAuthentication(Poco::RemotingNG::JSONRPC::Transport::AUTH_DIGEST);
trans.setUsername("user");
trans.setPassword("s3cr3t");
trans.enableChunkedTransferEncoding(false);

Please note that chunked transfer encoding must be disabled in order to use HTTP Digest Authentication.

It is also possible to enable both Basic and Digest authentication and use whatever the server requests:

trans.setAuthentication(Poco::RemotingNG::JSONRPC::Transport::AUTH_ANY);
trans.setUsername("user");
trans.setPassword("s3cr3t");
trans.enableChunkedTransferEncoding(false);

Cookies

The JSONRPC Transport supports HTTP cookies. Any cookies sent by the server through a HTTP response will be sent back to the server with subsequent HTTP requests. The lifetime (maximum age) of cookies, if set, will be honored, and expired cookies will not be sent back to the server.

Cookies are mostly useful for session-based authentication. The cookies stored in a Transport object can be obtained and shared with a different Transport object. This is useful if a JSONRPC server uses session cookies for authentication and the same session needs to be used by multiple proxy instances.

Cookies are stored in a Poco::RemotingNG::JSONRPC::CookieStore object. A pointer (Poco::RemotingNG::JSONRPC::CookieStore::Ptr) to this object can be obtained by calling Poco::RemotingNG::JSONRPC::Transport::getCookieStore(). The cookie store can then be shared with a different Transport by calling Poco::RemotingNG::JSONRPC::Transport::setCookieStore().

Performance Considerations

The performance of the JSON-RPC Transport is considerably lower than the that of the TCP Transport. Some of the reasons for this are:

  • JSON generation and especially JSON parsing overhead,
  • JSON uses more bandwidth than a binary protocol, and
  • the HTTP overhead is larger than the overhead for a simple socket connection.

Applications for which remote method call performance is critical, and which do not need to work with non Remoting applications should therefore prefer the TCP transport to the JSON-RPC transport.

Text Encoding Considerations

All strings used in remote interfaces must be properly UTF-8 encoded when using the JSON-RPC transport. Encoding errors may lead to failures when parsing JSON-RPC request or response messages.

Interoperability

The Remoting NG JSON-RPC Transport should work well with other JSON-RPC 2.0 client or server implementations. The client always passes arguments by name (as object), however, the server can handle objects passed by name and by position (as array). Furthermore, the JSON-RPC Transport does not support batched requests.

Using The JSON-RPC Transport With HTTPS

The JSON-RPC transport normally uses a plain, unencrypted HTTP connection between the client and the server. To make the JSON-RPC Transport use a secure HTTP socket connection, the following steps must be performed.

HTTPS On The Server Side

On the server side, the listener must be created using a Poco::Net::SecureServerSocket.

Poco::Net::SecureServerSocket serverSocket(8443);
std::string listener = Poco::RemotingNG::ORB::instance().registerListener(
    new Poco::RemotingNG::JSONRPC::Listener("localhost:8443", serverSocket)
);
std::string uri = MyProject::MyClassHelper::registerObject(
    new MyProject::MyClass, 
    "MyObject", 
    listener
);

HTTPS On The Client Side

On the client side, the JSON-RPC transport uses a private Poco::Net::HTTPSessionFactory object to create the Poco::Net::HTTPClientSession for talking to the server. So, all that needs to be done to enable HTTPS on the client is to register the Poco::Net::HTTPSSessionInstantiator with the session factory. Then, a https URI can be used to access the web service.

Poco::RemotingNG::JSONRPC::Transport::httpSessionFactory().registerProtocol(
    "https", 
    new Poco::Net::HTTPSSessionInstantiator
);

Poco::RemotingNG::JSONRPC::TransportFactory::registerFactory();

MyProject::IMyClass::Ptr pObj = MyProject::MyClassHelper::find(
    "https://localhost:8443/jsonrpc/MyClass/TheObject"
);