This specification documents the RecipeRPC protocol, version 0.2. You can look at earlier versions here.

RecipeRPC is a protocol for supplying recipes to clients over a network from one or more central servers. It is:

Table of contents

XML-RPC
base64
Sample session
Host name and URI
Usernames and passwords
Config method
Search method
Fetch method
Optional methods
Odds and ends
Earlier versions
Copyright and disclaimer

XML-RPC

RecipeRPC clients make remote procedure calls using XML-RPC. You should read the XML-RPC specification before reading this document. (Don't worry, it's short and simple.)

There are free or cheap XML-RPC libraries available for most major languages (PHP, C, Java, Perl, and more). Generally, these libraries make XML-RPC calls very simple to use - there's no need to mess about with HTTP requests. For example, with one such library for PHP, you write code like this to call the reciperpc.config() method:

$f=new xmlrpcmsg('reciperpc.config()',
                 array(new xmlrpcval("squirrel", "string"),
                       new xmlrpcval("mypassword", "string")));
$c=new xmlrpc_client("/RPC2", "reciperpc.sourceforge.net", 80);
$r=$c->send($f);
$v=$r->value();

base64

RecipeRPC uses base64-encoded binary to pass recipes from the server to the client. Base64-encoded binary is a safe method of sending arbitrary binary data through channels that can only accept ASCII text. It's the usual way of sending Unicode or other special characters via email, for example.

Why use a base64 type instead of a string? Well, as the XML-RPC specification says, a string must encode the less-than sign < as &lt; and the ampersand & as &amp; - if your recipe is in an XML format, that will be a lot of substitutions. Making those substitutions requires a bit of extra coding and is a source for bugs.

By contrast, XML-RPC libraries normally do the encoding and decoding for you when you use a base64 type, so you don't even have to think about it.

If your library doesn't happen to do this, there are lots of standalone base64 libraries for almost any language (since the encoding is so pervasively used for email) and you should be able to use one of these almost as easily. Just see Google's list of base64 libraries.

Sample session

Here is an example of the messages that pass between a RecipeRPC client and a RecipeRPC server in a typical session. To keep the description clear and simple, this sample session shows neither fault handling nor handling of extended result lists. There are links to the detailed HTTP messages, if you need that level of detail (you shouldn't normally if you are using an XML-RPC library).

1A. Client calls the XML-RPC procedure

  reciperpc.config("squirrel", "mypassword")

Here is the HTTP request for this reciperpc.config() call.

1B. Server returns the struct

Key Value
version 0.2
description RecipeRPC Reference Implementation Server
criteria [name, category]
formats [RecipeML, CookML]

Here is the HTTP response for this reciperpc.config() call.

2A. Client calls the XML-RPC procedure

  reciperpc.search("squirrel", "mypassword", criteria, 1)

where criteria is the struct

Key Value
name spaghetti
category vegetarian

Here is the HTTP request for this reciperpc.search() call.

2B. Server returns the struct

Key Value
total 2
recipes See below.

in which recipes is an array containing these two structs:

Key Value
name Mom's Spaghetti
id 12345

and

Key Value
name Spaghetti Medici
id 65432

Here is the HTTP response for this reciperpc.search() call.

3A. Client calls the XML-RPC procedure

  reciperpc.fetch("squirrel", "mypassword", 12345, "RecipeML")

Here is the HTTP request for this reciperpc.fetch() call.

3B. Server returns a base64 object, containing the "Mom's Spaghetti" recipe in RecipeML format, encoded in base64.

Here is the HTTP response for this reciperpc.fetch() call.

Host name and URI

An XML-RPC client needs only two things to connect to a server: the server's host name and a URI for that server. These are familiar objects, appearing in any web address: in the address for this page

http://reciperpc.sourceforge.net/spec.html
we have a host name of reciperpc.sourceforge.net and a URI of /spec.html. Basically, the host name tells you where to go on the Internet to get to the server, and the URI tells the server where to direct your request.

The host name of an XML-RPC server will almost always be its domain name. The standard URI for an XML-RPC server is /RPC2, but a server can use any convenient URI (including the trivial URI consisting only of a single slash / - you would normally only do this if your host is doing nothing but serving XML-RPC requests).

Usernames and Passwords

Each method described below takes username and password parameters. These are strings with the obvious meanings and may be used by the server for authentication or ignored.

A client may, as a standard procedure, make its first call to the server with blank username and password. If fault 1, invalid username or password, is returned, the client should fetch a valid username and password (for instance, by prompting the user) and use it in future method calls to this server. If the server gives a valid response, the client may continue to use blank username and password in future method calls.

config method

struct reciperpc.config(string username, string password)

Description. Fetches configuration information about the RecipeRPC server.

Parameters. The username and password parameters have the standard types and meanings.

Return value. This struct:

Key Value type Value description
version string The version of RecipeRPC supported by this server.
description string Brief description of this server. May be used, for example, in a list of available servers.
criteria array of strings Identifiers for the criteria that can be used in searches. Examples: name, category, rating, equipment.
formats array of strings Names of the formats available from this server. Examples: RecipeML, MealMaster.

Faults. The server may return these faults:

Fault code Fault description
1 Invalid username or password.
Any value > 100 Implementation-specific faults.

search method

struct reciperpc.search(string username, string password, struct criteria, int index)

Description. Searches for recipes matching given criteria.

Parameters. The username and password parameters have the standard types and meanings.

The criteria parameter is a struct in which:

This struct may be empty (contain no keys) which should be interpreted as a request for all recipes from the server. The server may respond with an implementation-specific fault in this case, if such queries are not allowed.

For example, the sample criteria structure above indicates that the server should return vegetarian recipes with names containing "Spaghetti".

The index parameter is an int indicating the index of the first recipe to return. That is, if this parameter is set to n and the list of all recipes matching the criteria is numbered 1, 2, 3, ..., then the server should send recipes beginning with the one numbered n. If n is greater than the number of recipes matching the criteria, then the server should return fault 3.

Normally, the client will send the value 1 for this parameter on the first call to reciperpc.search(). If the server sends, say, only the first 25 matching recipes in response to this call, and if the client requires more recipes, the client will normally then call reciperpc.search() again with index equal to 26. If still more are required, repeat with 51, 76, 101, ....

Return value. This struct:

Key Value type Value description
total int The total number of recipes that match the criteria.
recipes array An array of recipe data. See below.

The recipes element of this struct is an array, possibly empty, of structs with this form:

Key Value type Value description
name string The name of a recipe matching the given criteria.
id string An identifier that uniquely identifies this recipe to the server.

Notice that the server need not return all matching recipes, but it must return the total number of matching recipes in the member total (naturally total may be zero if nothing matches). The client can easily determine whether there are any more recipes to be had: the server has sent all the recipes if and only if

total = index + size(recipes) - 1.

Faults. The server may return these faults:

Fault code Fault description
1 Invalid username or password.
2 Invalid criterion name.
3 Index greater than total number of matching recipes.
Any value > 100 Implementation-specific faults.

fetch method

struct reciperpc.fetch(string username, string password, string id, string format)

Description. Fetches a specific recipe, using an id returned by reciperpc.search() and specifying a format.

Parameters. The username and password parameters have the standard types and meanings.

The id parameter is a string containing an identifier returned by the reciperpc.search() method.

The format parameter is a string containing one of the format identifiers returned by the reciperpc.config() method.

Return value. The requested recipe in the requested format, encoded as base64-encoded binary in a base64 type.

Faults. The server may return these faults:

Fault code Fault description
1 Invalid username or password.
4 Invalid recipe identifier.
5 Invalid format.
Any value > 100 Implementation-specific faults.

Optional methods

Servers are strongly encouraged, but not required, to implement the introspection methods

system.listMethods()
system.methodSignature()
system.methodHelp()
These methods are described in the
XML-RPC for PHP documentation.

The text returned by each of these methods is likely to be nearly identical for each server. The reference implementation isolates these descriptions in a file, which is public domain and may be used or modified by any implementation.

Servers and clients may implement boxcarring, a technique for sending or receiving multiple requests using the method

array system.multicall(array calls)
However, be forewarned that this technique is not supported by many XML-RPC implementations. This method is not implemented in the reference implementation.

Odds and ends

The meaning of criterion values. A criterion is normally the name of a recipe attribute, such as "name" or "ingredient", and so when you specify a string value for the criterion in the reciperpc.search() method, the server typically fetches recipes whose attribute contains that string (searching case-insensitively): hence in the example we match any recipe whose name contains "spaghetti" (searching case-insensitively).

However, the server is free to behave differently. For instance, it may search for exact matches only. Or it may interpret the value as a number and search for values greater or less than the given one. Or it may require a format, such as a-b for a range from one number a to another b. In any of these cases, the server should (but is not required to) provide and document implementation-specific fault codes (integers > 100) and detailed, helpful fault messages for invalid criterion values.

Fault descriptions. This protocol only prescribes the fault codes and their meanings; a server may return any fault string that preserves the meaning. For instance, a server may return a fault string describing the fault in a different natural language, such as German.

Order of method calls. The normal order of method calls is shown in the example above, although a real session might include multiple calls to reciperpc.search() (if the server does not return all matching recipes the first time) and multiple calls to reciperpc.fetch() (if more than one recipe is desired). However, clients are free to call any method at any time; for instance, if the identifier is known, the client can simply issue the reciperpc.fetch() call immediately.

Earlier versions

For historical interest, earlier versions of this document are archived here.

RecipeRPC specification version 0.1

Copyright and disclaimer

Copyright 2004 Douglas Squirrel.

This document and translations of it may be copied and furnished to others, but not modified except as described in the next paragraph.

Derviative works of any kind whatsoever, including modified versions of this document or explanations or paraphrases of it, may be created and used in any way, so long as the word RecipeRPC is not used to identify any protocol materially different from the one described in this document. For example, you can document your own protocol based on RecipeRPC and use parts of this document in the description of your new protocol, but you can't refer to your new protocol as RecipeRPC.

While these copyright restrictions apply to the written RecipeRPC specification, no claim of ownership is made to the protocol it describes. Any party may, for commercial or non-commercial purposes, implement this protocol or any variation on it without royalty or license fee. The limited permissions granted herein are perpetual and will not be revoked.

This document and the information contained herein is provided on an "AS IS" basis and THE AUTHOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Last updated 9 February 2004
This web site copyright 2004 D. Squirrel
Graphics provided by Jeff Bucchino,
the Wizard of Draws, for noncommercial use.
SourceForge.net Logo