NAME
Riap - Rinci access protocol
VERSION
version 1.1.17
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 modeled closely after HTTP, but is a different protocol. It can be layered on top of HTTP (as its transport protocol) but can also use other transports, including direct TCP.
The server side is viewed as being a tree of code entities, with a package entity at the root. Other entities (such as subpackages, functions, variables) are discoverable by performing list
actions on package entities. Entity's metadata can be retrieved using the meta
action. There are other actions defined in the specification; and the protocol can be extended by introducing more actions.
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 series does not guarantee full backward compatibility between revisions, so caveat implementor. However, major incompatibility will bump the version to 1.2 or 2.0.
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
, andv
(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 SCHEMES
To refer to code entities on the Riap server, a new URI scheme riap
is defined. The URI path describes path to code entities while the URI host describes the host language. Examples:
# refer to Text::sprintfn Perl module
riap://perl/Text/sprintfn/
# refer to sprintf function in Text::sprintfn Perl module
riap://perl/Text/sprintfn/sprintfn
# refer to PHP variable
riap://php/$var
# UNDECIDED: refer to class metadata
riap://perl/My/Class/:class
# UNDECIDED: refer to distribution metadata
riap://perl/My/Dist/:distribution
There are some other schemes recognized.
pl. The pl
hostless scheme refers to code entities in Perl. This is preferred in many Perinci modules because the riap
scheme is more verbose. Examples:
# refer to Text::sprintfn Perl module
pl:/Text/sprintfn/
# refer to sprintf function in Text::sprintfn Perl module
pl:/Text/sprintfn/sprintfn
riap+tcp. This scheme is for Riap::Simple over TCP socket. The host (+port) part describes TCP host (+port), and the path part describes path to code entity. Currently there is no default port so please always specify port number. Examples:
riap+tcp://localhost:5000/Text/sprintfn/
riap+tcp://localhost:5000/Text/sprintfn/sprintfn
riap+unix. This scheme is for Riap::Simple over Unix socket. There is no host part (Unix socket is localhost-only). The path part describes path to the socket and path to code entity (separated by //
).
riap+unix:/path/to/unix/socket
riap+unix:/path/to/unix/socket//Text/sprintfn/sprintfn
riap+pipe. This scheme is for Riap::Simple over pipe, to refer to starting a program and talking the protocol over the pipe. There is no host. The path part describes path to program, //
separator, arguments separated by /
, //separator
, and path to code entity.
# refer to accessing code entity via executing "/path/to/program"
riap+pipe:/path/to/program////Text/sprintfn/sprintfn
# refer to via accessing code entity via executing "/path/to/program arg1 arg2"
riap+pipe:/path/to/program//arg1/arg2//Text/sprintfn/sprintfn
RIAP OVER HTTP/HTTPS
For Riap over HTTP/HTTPS as the transport layer, the standard URI scheme http/https is used. The URI path for these do not necessarily map directly to code entities like in riap
or pl
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.npwp/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
However, any Riap request and any code entity URI can still be requested from any http/https URL following the Riap::HTTP protocol..
THE REQUEST
As mentioned previously, the Riap request is a mapping of request keys and their values. Some request keys:
v => FLOAT
Specify Riap protocol version. If not specified, default is
1.1
. Server should return 502 status if it does not support requested protocol version.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 can be implemented by the server. Server can choose to not implement any action, or implement additional actions. But for actions mentioned below, the specification must be followed.
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):
[200,"OK",
{
// server's protocol version
"v": 1.1,
// entity's type
"type": "function",
// canonical URI for the entity
"uri": "/Package/SubPkg/",
}
]
Server may add additional information keys.
Action: actions
List available actions for code entity. The server should return a list of action names:
[200,"OK",
["info","actions","meta","call","complete_arg_val"]
]
Additional request key: detail (bool, optional, default false, can be set to true to make server return a list of records instead).
Under detail, server should return something like this:
[200,"OK",
[
{"name":"info", "summary":"Get general information about code entity"},
{"name":"actions","summary":"List available actions for code entity"},
{"name":"meta","summary":"Get metadata for code entity"},
{"name":"call","summary":"Call function"},
{"name":"complete_arg_val","summary":"Complete function's argument value"}
]
]
It can return additional field like keys
to explain additional required/optional request keys (XXX not yet specified).
Action: meta
Return Rinci metadata for the code entity. When the entity does not have metadata, server should return 404 status or better yet 534 (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; if true, then server must return info hash for each entry, where each info hash like that returned by the info
action).
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",
["pl:/Math","pl:/Utils"]
]
Another example, a list
action on the pl:/Math
namespace, with type
set to function
and q
to multiply
, and detail
set to true:
[200,"OK",
[
{"uri": "pl:/Math/multiply2",
"type": "function",
"summary": "Multiply two numbers"},
{"uri": "pl:/Math/multmany",
"type": "function",
"summary": "Multiply several numbers"}
]
]
Action: child_metas
Get metadata for all the children entities of the package entity.
This action can reduce the number of round-trips, as opposed to client performing list
action followed by meta
for each child.
Example, an child_metas
action on the top namespace /
might return the following:
[200,"OK",
{
"pl:/Math": {"v":1.1, "summary":"This is metadata for Math"},
,"pl:/Utils": {"v":1.1, "summary":"This is metadata for Utils"}
}
]
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_arg_val
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",
[]
]
ACTIONS FOR variable
ENTITIES
Below are actions that are available for the variable
entities.
Action: get
Get variable value.
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
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). Fell 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.
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.
CHANGES
Version 1.1.17 (2012-08-01)
Allow riap+pipe scheme to specify program arguments.
Version 1.1.16 (2012-07-31)
Rename Riap::TCP to Riap::Simple.
Introduce schemes: riap+unix (previously mixed together with riap+tcp), riap+pipe.
Version 1.1.15 (2012-07-19)
Riap::TCP: Allow single-line request using j<JSON><CRLF>
Version 1.1.14 (2012-06-22)
Some small changes, mainly transaction status labels (final statuses are in uppercase: C, R, U, X; while transient statuses are in lowercase: i, a, u, d, e).
Now requires Rinci 1.1.19.
Version 1.1.13 (2012-05-31)
Some revision and incompatible changes to Riap::Transaction specification: rename requests (begin -> begin_tx, commit -> commit_tx, and so on), tweak some status codes, mention status E (prepared).
Now requires Rinci 1.1.17.
Version 1.1.12 (2012-05-03)
(NEW) Riap::Transaction, specification for doing transaction and undo over Riap.
Version 1.1.11 (2012-04-03)
(REMOVED) Remove mention of 'riap+http' and 'riap+https' as they are useless. Use 'http' and 'https'.
Version 1.1.10 (2012-04-03)
(Change, or rather define, as it has not been specified formally) 'pm' URI scheme to (or, as) 'pl'.
Version 1.1.9 (2012-03-08)
Add new action for variable: get
Version 1.1.8 (2012-03-01)
Add new action for package: child_metas
HTTP: Add new action: srvinfo
HTTP: The valid values of 'fmt' is now up to the implementation (except that 'json' still needs to be supported).
Version 1.1.7 (2012-02-22)
(REMOVE, INCOMPATIBLE) Remove action 'complete_arg_name'. This action can be implemented in the client side by retrieving function metadata using 'meta' action (this requires larger bandwidth, but clients can do caching). It is better to implement this on the client side due to specific requirements like --foo vs -foo, --boolopt as well as --noboolopt (or --no-boolopt), and so on.
Version 1.1.6 (2012-02-22)
Add new action 'actions'. To list available actions on a code entity, use this action now instead of 'info'.
(INCOMPATIBLE) Rename 'complete' action to 'complete_arg_val'.
Add new action 'complete_arg_name'.
Version 1.1.5 (2012-02-15)
Some fixes (build/deps, examples, 'info' action should contain 'acts')
and minor updates.
Version 1.1.4 (2012-02-01)
Declare that in 1.1 series, minor backward compatibility problems between revisions are to be expected.
Make 'v' request key optional, defaults to 1.1.
Rename 'ofmt' request key to 'fmt'.
Change required result keys of 'info' action.
Version 1.1.3 (2012-01-27)
Specify riap URI scheme (moved from Rinci). + Add Riap::TCP.
Version 1.1.2 (2012-01-17)
Rename distribution from Rinci-HTTP as Riap.
Version 1.1.1 (2012-01-15)
No spec changes. Fix misplaced section in POD.
Version 1.1.0 (2012-01-15)
First release. Renamed from Sub::Spec::HTTP. Now follow the Rinci
specification instead of Sub::Spec. Generalized to perform actions on
any code entities instead of just functions. Change terminologies.