NAME

Riap - Rinci access protocol

VERSION

version 1.1.3

DESCRIPTION

Rinci access protocol (Riap for short), is a client/server, request/response protocol for requesting metadata and performing actions on code entities. It is modelled closely after HTTP, but a different protocol. It can be layered on top of HTTP (as its transport protocol) but can also uses other transports, including direct TCP. Riap::HTTP explains how Riap can be used over HTTP.

The server side is viewed as being a tree of code entities, with a package entity at the root. The other entities, such as subpackages, functions, variables, etc are discovered by client by performing a list action on a package entity. The client can also perform a meta action on any code entity to get its metadata, as specified by the Rinci specification. There are other actions that can be performed on code entities, like call on functions to perform remote call. The protocol can be extended by introducing more actions. The list of performable actions, as well as other information, can be discovered by performing an info action on the code entity first.

SPECIFICATION VERSION

1.1

ABSTRACT

This document specifies a simple, extensible, client/server, request/response protocol for requesting metadata and performing actions on code entities.

Examples are written in JSON (sometimes with added comments), but data structures can actually be encoded using other formats.

STATUS

The 1.1 specification is expected to stabilize after a few more iterations, perhaps around 1.1.10 or so. Before that, there will probably a few more incompatible changes, especially since Riap::TCP is new, so caveat implementor.

TERMINOLOGIES

  • Server

  • Client

  • Response

    Response is an enveloped result as defined in the Rinci::function specification.

  • Request

    A Riap request is modelled after HTTP request. It consists of an action (analogous to HTTP request method), code entity URI, protocol version, and zero or more extra arguments (analogous to HTTP headers). Some extra arguments might be required, depending on the action.

    For simplicity, the request can be expressed as a hash (or dictionary) of key/value pairs. There should at least be these keys: action, uri, and v (for protocol version). This also means the extra arguments cannot have those names. They must also start with letters or underscores followed by zero or more letters/underscores/digits.

    Server should return 400 status if required keys are missing, unknown keys are sent, or keys contain invalid values.

RIAP URI SCHEME

To refer to code entities, a new URI scheme riap is defined. URI scheme can be suffixed with transport, e.g. riap+tcp (see Riap::TCP), while riap+http/riap+https to refer to Riap over HTTP/HTTPS (see Riap::HTTP).

Without transport, the host part of URI can be used to refer to host language. For example:

# refer to Text::sprintfn module
riap://perl/Text/sprintfn/

# refer to sprintf function in Text::sprintfn
riap://perl/Text/sprintfn/sprintfn

# refer to PHP variable
riap://php/$var

Scheme/host and parts of path are optional if you refer from the same host language or module. Examples:

# refer to Text::sprintfn module from another Perl module
/Text/sprintfn/

# refer to Text::Wrap module from Text::sprintfn
../Wrap/

If transport is used, host (and port) means network host (and port) as usual:

riap+tcp://localhost:7001/Foo/bar
riap+http://gudangapi.com/tax/id/validate_npwp

Lest there is confusion, with Riap over HTTP/HTTPS there is also the <http>/https URLs to access the services. The URI path for these do not necessarily map directly to code entities like in riap URIs, they may also support additional features, as each service provider can choose custom URL layout. Example:

# access tax::id::validate_npwp function, call with arguments
http://gudangapi.com/ga/tax.id.validate_npwp?npwp=123456

# namespace/module can also be omitted when function name is unique. arguments
# can also be specified by position
http://gudangapi.com/ga/validate_npwp/123456

THE REQUEST

As mentioned previously, the Riap request is a mapping of request keys and their values. Some request keys:

  • v => FLOAT

    Required. Specify Riap protocol version. Currently must have the value of 1.1. The server should return 502 status if protocol version is not supported.

  • uri => STR

    Required. Specify the location to code entity. It is either a schemeless URI (e.g. /Package/SubPackage/func) to refer to "local" code entity or URI with a scheme to refer to a remote entity, e.g. http://example.org/api/Foo/Bar/func, in which case the server can decide to proxy it for the client or not.

    The server should return 404 status if uri does not map to an existing code entity, or 403 if uri is forbidden.

  • action => STR

    Required. Specify action to perform on the code entity.

    The server should return 502 status if an action is unknown for the specified URI. The server should return 401/403 status if authentication is required or action is not allowed for the specified code entity, respectively.

Additional keys might be recognized and/or required according to the action.

COMMON ACTIONS

Below are the actions which must be implemented by the server for all kinds of entities.

Action: info

Get general information and information about the code entity. This action requires no additional request keys. Upon success, the server must return a hash result with at least the following keys (remember that the result is actually enveloped with a 200 status):

{
 // server's protocol version
 "v": 1.1,

 // entity's canonical URL
 "url": "http://localhost:5000/api/Package/SubPkg/func",

 // entity's type
 "type": "function",

 // actions available for this entity
 "acts": ["info", "call", "complete"],

 // server base URL
 "srvurl": "http://localhost:5000/api/"
}

The server may add additional information.

Action: meta

Return Rinci metadata for the code entity. When the entity does not have metadata, server should return 534 status (metadata not found).

ACTIONS FOR package ENTITIES

Below are actions that must be supported by the package entities.

Action: list

List entities contained in this package. Additional request keys are: type (string, optional, to limit only listing entities of a certain type; default is undef which means list all kinds of entities), recursive (bool, optional, can be set to true to search subpackages; default is false which means only list entities in this namespace), q (string, search terms, to only return matching some search terms; default is undef which means return all entities), detail (bool, optional, whether to return just a list of code entity URIs or a detailed record for each entry, defaults to false).

The server should return 200 status or 206 if partial list is returned. If detail is true, for each entry a hash must be returned containing at least uri and type. Server may add additional information like summary, description, etc.

Example, a list action on the top namespace / might return the following:

[200,"OK",["pm:///Math","pm:///Utils"]]

Another example, a list action on the pm:///Math namespace, with type set to function and q to multiply, and detail set to true:

[200,"OK",
 [
  {"uri": "pm:///Math/multiply2",
   "type": "function",
   "summary": "Multiply two numbers"},

  {"uri": "pm:///Math/multmany",
   "type": "function",
   "summary": "Multiply several numbers"}
 ]
]

ACTIONS FOR function ENTITIES

Below are actions that are available for the function entities. At least call must be implemented by the server.

Action: call

Call a function and return its result. Additional request keys include:

  • args

    Hash, optional, function arguments, defaults to {}.

Action: complete

Complete function argument value, a la Bash tab completion where you have a semicompleted word and request possible values started by that word. Additional Riap request keys include:

  • arg

    String, required, the name of function argument to complete.

  • word

    String, optional, word that needs to be completed. Defaults to empty string.

The server should return a list of possible completions. Example, when completing a delete_user function for the argument username, and word is "st", the server might return:

[200,"OK",["stella","steven","stuart"]]

When there is no completion, the server should return an empty list:

[200,"OK",[]]

FAQ

Why no actions to modify metadata/code entities?

Since the specification is extensible by adding more actions, you can implement this on your system. These actions are not specified by this specification because currently the main goal of the protocol is to provide API service and read-only access to the metadata.

Alternatively, modifying metada/code entities can be implemented using calls to functions on the server which can perform the modifications.

There are also some issues which need to be considered when adding these actions. First of all, security. Second, you need to decide whether to modify the running/in-memory copy or the actual source code/files (as the code entities are usually stored as). When modifying the in-memory copy, the server-side architecture may have multiple copies (multiple processes and machines). Do you want to modify all those copies or just one the one process?

The name?

Riap stands for Rinci access protocol, but it is also an Indonesian word meaning: to gain in size or number.

HISTORY

1.1 (Jan 2012)

Rename specification to Riap. Version bumped to 1.1 to various backward-incompatible adjustments to Rinci's terminologies.

1.0 (Aug 2011)

Split specification to Sub::Spec::HTTP.

May 2011

First release of Sub::Spec::HTTP::Server.

SEE ALSO

Rinci

SOAP, WSDL. Popular in the early 2000's, with similar goals (easier service discovery, "simple" request/response protocol which can utilize HTTP or other transport layer). Falled out of favor along with the rise of JavaScript and REST and increased criticism against the complexity of XML. Which is ironic because SOAP was originally created to be the simpler alternative to ...

CORBA.

AUTHOR

Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Steven Haryanto.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.