simple is better

JSON-RPC 2.0 Extension: Transports

Status: proposal/draft
Date: 2013-03-18
Author: Roland Koebler <rk at simple-is-better dot org>

1   Overview

JSON-RPC does not depend on any specific transport. Any transport should be possible.

Nevertheless, this document lists some recommendations how to use JSON-RPC over some commonly-used transports.

2   Sockets (Unix Domain Sockets or TCP/IP Sockets)

When using TCP or Unix Domain Sockets (or any other transport) without some high-level-protocol, you have to detect when a Request/Response is complete. Here, three ways are presented:

  • shutdown/close connection
  • netstrings
  • streaming JSON-decoder/splitter

2.1   JSON-RPC over TCP / Unix domain sockets

Use a new connection for every Request/Response.

The client MUST shutdown the writing (SHUT_WR) to signal the end of the Request. The server MUST close the connection to signal the end of the Response.

This is simple, straight-forward and robust. But it may be slow, since every Request needs a new connection.

Client-side:

  1. open a socket, connect
  2. send Request, shutdown socket-writing
  3. receive Response (=receive until close/shutdown)
  4. close socket

Server-side:

  1. open socket, bind, listen
  2. accept a connection
  3. receive Request (=receive until shutdown)
  4. send Response
  5. close connection
  6. goto 1

2.2   JSON-RPC over Netstrings

See:

Encode JSON-RPC objects in netstrings. Since netstrings are a self-delimiting encoding, a single connection can be used for several Requests/Responses.

But note that the server may close a connection e.g. after a timeout, so always use a new connection as fallback.

2.3   JSON-RPC over TCP / Unix domain sockets with a JSON-splitter

It's also possible to use a single connection for several Requests/Responses without an additional encoding. Then, (a) a streaming JSON-decoder or (b) a streaming JSON-splitter is needed, which detects the end of a JSON-object/array.

Streaming JSON-decoders seem to be rare, but a JSON-splitter which only detects the end of a JSON-object/array can easily be implemented:

TODO: JSON-splitter-example

But note that the server may close a connection e.g. after a timeout, so always use a new connection as fallback.

3   JSON-RPC over HTTP

JSON-RPC can be simply tunneled through HTTP.

SeeAlso:HTTP specification (RFC 2616)

3.1   POST Request

A HTTP POST request message MUST specify the following headers:

  • Content-Type: SHOULD be application/json or application/json-rpc
  • Content-Length: MUST contain the correct length according to the HTTP-specification.
  • Accept: SHOULD be the same as Content-Type.

Of course, additional HTTP-features and -headers (e.g. Authorization) can be used.

The Request itself is carried in the body of the HTTP message.

Example:

POST /myservice HTTP/1.1
Host: rpc.example.com
Content-Type: application/json
Content-Length: ...
Accept: application/json

{
    "jsonrpc": "2.0",
    "method": "sum",
    "params": { "b": 34, "c": 56, "a": 12 },
    "id": 123
}

3.2   GET Request

HTTP GET is not recommended for JSON-RPC, since it requries to encode the JSON-RPC-Request in the URL, and encoding nested data-structures in URLs can be problematic and results in (a) hardly-readable URLs and (b) an unusual GET-style.

Nevertheless, the following defines how it can be done. But note that:

  • Often, it's better to use HTTP POST.
  • Only procedures that are considered safe and idempotent MAY be invoked using HTTP GET (according to HTTP Section 9.1, Safe and Idempotent Methods).
  • Some old clients and proxies have issues wth URI lengths over 255 bytes.
  • URL-encoding may not work for all characters; especially non-ISO-8859-1-characters may be problematic.
  • It may be better to write a small wrapper which accepts a "normal" HTTP GET request (with flat parameters), decides if a JSON-RPC-service should be called and then converts it to JSON-RPC-request-syntax. It could additionally mangle the JSON-RPC-response before returning the result via HTTP to get a more REST-style interface.

A HTTP GET request message uses the JSON-RPC-members as query-fields in the URL, and the values SHOULD be URL-encoded. The id field always has to be considered as string.

Example:

{"jsonrpc": "2.0", "method": "sum", "params": [3, 4], "id": "1"}
->
http://rpc.example.com/myservice?jsonrpc=2.0&method=sum&params=%5B3%2C4%5D&id=1

{"jsonrpc": "2.0", "method": "sum", "params": {"a": 3, "b": 4}, "id": "2"}
->
http://rpc.example.com/myservice?jsonrpc=2.0&method=sum&params=%7B%27a%27%3A+3%2C+%27b%27%3A+4%7D&id=2

3.3   Response

The HTTP return message MUST specify the following headers:

  • Content-Type: SHOULD be application/json or application/json-rpc
  • Content-Length: MUST contain the correct length according to the HTTP-specification.

The status code MUST be 200, except for HTTP reasons/errors. For Notifications, 204 is also allowed.

The Response (both on success and error) is carried in the HTTP body.

Example on Success:

HTTP/1.1 200 OK
Connection: close
Content-Length: ...
Content-Type: application/json
Date: Sat, 08 Jul 2006 12:04:08 GMT

{
    "jsonrpc": "2.0",
    "result": 102,
    "id": 5
}

Example on Error:

HTTP/1.1 200 OK
Connection: close
Content-Length: ...
Content-Type: application/json
Date: Sat, 08 Jul 2006 12:04:08 GMT

{
    "jsonrpc": "2.0",
    "error": {
        "code": -32600,
        "message": "Invalid Request.",
        "data": "'method' is missing"
        },
    "id": 6
    }
}

View document source.

webmaster(at)simple-is-better(dot)org

best viewed with any browser Valid HTML 4.01 Transitional Wir speichern nicht - Weitere Informationen hier...