5. August 2007

Simple Remote Procedure Call

In my projects we often use remote procedure calls. We use various kinds, SOAP, XMLRPC, REST, JSON, conveyed by different protocols (HTTP, XMPP, even SMTP). We use whatever is appropriate in the situation, be it client-server, server-service, client-p2p, and depending on the code environment C++, C#, JScript, PHP.
With SOAP and XMLRPC you don't want to generate or parse SOAP-XML by hand. That's an avoidable error source. Rather you use a library, which does the RPC-encoding/decoding job. To do that you have to get used to the lib's API, modes of operations, and its quirks.
This is significant work until you are really in "complete advanced control" of the functionality. Especially, if there is only a method name with paramaters to exchange. Even more bothersome is the fact, that most such libraries need megabytes, have their own XML parser, their own network components. Stuff, we already have in our software for other purposes.
What we really need is a simple way to execute remote procedure calls

  • with an encoding so easy and fail safe, that it needs no library to en/decode,
  • that is so obvious, that we do not need an industry standard like SOAP, just to tell other
    developers what the RPC means.
The solution is a list of key-value pairs. This is Simple RPC (SRPC):
  • request and response are lists of key-value pairs,
  • each parameter is key=value
  • parameters separated by line feed
  • request as HTTP-POST body or HTTP-GET with query
  • response as HTTP response body
  • Content-type text/plain
  • all UTF-8
  • values must be single line (must not contain line feeds)
  • request method as Method=
Example (I love stock quote examples):
HTTP-POST request body:
  1. C: POST /srpc.php HTTP/1.1
  2. C: Content-type: text/plain; charset=UTF-8
  3. C: Content-length: 43
  4. C:
  5. C: Method=GetQuote
  6. C: Symbol=GOOG
  7. C: Date=1969-07-21
HTTP response body:
  1. S: HTTP/1.1 200 OK
  2. S: Content-type: text/plain; charset=UTF-8
  3. S:
  4. S: Status=1
  5. S: Average=123
  6. S: Low=121
  7. S: High=125
Additional options:
1. Multiline Values:
Of course, there are sometimes line feeds in RPC arguments and results. Line feeds must be encoded using HTTP-URL encoding (%0A) or a better readable "cstring" encoding (\n). The encoding is specified as meta parameter:
  1. News=Google%20Introduces%20New...%0AAnalyst%20says...
  2. News/Encoding=URL
or:
  1. News=Google Introduces New...\nAnalyst says...
  2. News/Encoding=cstring
The "cstring" encoding replaces carriage-return (\n), line-feed (\r), and back-slash (\\). The "cstring" encoding indication, e.g. "News/Encoding=cstring" may be omitted.
2. Binary Values:
Binary values in requests and responses are base64 encoded. An optional "Type" uses MIME types to indicate the data type in case of e.g. image data.
  1. Chart=R0lGODlhkAH6AIAAAOfo7by/wCH5BA... (base64 encoded GIF)
  2. Chart/Encoding=base64
  3. Chart/Type=image/gif
3. The Query Variant:
Even complex result values, such as XML data, must be single line. Following the scheme above, this can be done by using "base64" or "cstring" encoding. Both are not easily readable in case of XML. SRPC offers a simpler way to return a single result value: if the request is HTTP-GET with query then the result value comes as response body with Content-type. It's a normal HTTP request, but SRPC conform.
HTTP query:
  1. C: GET /srpc.php?Method=GetPrices&Symbol=GOOG&Date=1969-07-21 HTTP/1.1
HTTP response (with a sample xml as a single result value):
  1. S: HTTP/1.1 200 OK
  2. S: Content-type: text/xml
  3. S:
  4. S: <?xml version="1.0"?>
  5. S: <prices>
  6. S: <price time="09:00">121.10</price>
  7. S: <price time="09:05">121.20</price>
  8. S: </prices>
4. Special Keys
There are 3 special keys defined:
  • request "Method=FunctionName" (RPC method)
  • response "Status=1" (1=OK, 0=error)
  • response "Message=An explanation" (an accompanying explanation for Status=0 or 1)
This Simple RPC specifies exactly how RPC requests are encoded. It's just lists of key=value pairs. But still powerful enough for all RPCs we need.
happy_coding()

Kommentar veröffentlichen