JSON-RPC 2.0 Extension: Transports
Status: | proposal/draft |
---|---|
Date: | 2013-03-18 |
Author: | Roland Koebler <rk at simple-is-better dot org> |
Table of Contents
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:
- open a socket, connect
- send Request, shutdown socket-writing
- receive Response (=receive until close/shutdown)
- close socket
Server-side:
- open socket, bind, listen
- accept a connection
- receive Request (=receive until shutdown)
- send Response
- close connection
- 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¶ms=%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¶ms=%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 } }