@rowanmanning/rpc v1.0.0-beta.3
@rowanmanning/rpc
Handle RPC endpoints, standalone or for Express and Koa. The RPC endpoint accepts JSON POST requests and takes some influence from JSON-RPC 2.0.
:warning: This is pre-release software, use in production at your own risk
Table of Contents
Requirements
This library requires the following to run:
- Node.js 10+
Usage
Install with npm:
npm install @rowanmanning/rpc
Load the library into your code with a require
call:
const RPC = require('@rowanmanning/rpc');
Creating an RPC endpoint
const rpc = new RPC(options);
The available options are:
method
: The HTTP method to add the RPC API on. Defaults toPOST
.path
: The path to add the RPC API on. Defaults to/rpc
.
Adding a method
To add a method to the RPC endpoint, use:
rpc.addMethod('sum', params => {
return params.a + params.b;
});
Methods also have access to the original request that resulted in the call, as well as the RPC instance that it belongs to:
rpc.addMethod('sum', (params, request, rpc) => {
// ...
});
Mounting in Express
Mount on an Express application by adding as middleware:
const app = express();
app.use(rpc.express());
Mounting in Koa
Mount on a Koa application by adding as middleware:
const app = new Koa();
app.use(rpc.koa());
Using the API
Once you have set up an application, you can access the rpc endpoint that you set up over HTTP. All methods (even methods that only retrieve data) are called with a POST request with a JSON request body.
Making a call
There are a couple of rules to follow when making calls to the RPC API:
- The
Content-Type
header must beapplication/json
- The request body must be a JSON object:
{}
- Each JSON object in the request body must have a
method
property set to a non-empty string - Each JSON object in the request body may have an
id
property set to a non-empty string - Each JSON object in the request body may have a
params
property set to an object
Assuming that your application is running locally on port 8080
:
POST /rpc HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{"method": "sum", "params": {"a": 100, "b": 37}}
Will result in the response:
HTTP/1.1 200 OK
Content-Type: application/json
{"id": null, "result": 137}
Batching calls
You can call multiple methods in parallel by batching calls together. There are a couple of rules to follow when making batch calls to the RPC API:
- The
Content-Type
header must beapplication/json
- The request body must be a JSON array:
[]
- Each entry in the JSON array must be an object which meets the rules outlined in "Making a call"
Assuming that your application is running locally on port 8080
:
POST /rpc HTTP/1.1
Host: localhost:8080
Content-Type: application/json
[
{"method": "sum", "params": {"a": 100, "b": 37}},
{"method": "sum", "params": {"a": 63, "b": 74}}
]
Will result in the response:
HTTP/1.1 200 OK
Content-Type: application/json
[
{"id": null, "result": 137},
{"id": null, "result": 137}
]
Identifying call responses
Mostly when batching calls, it's useful to be able to identify which call output which result. You can do this by specifying an id
property on each of your calls. The id
will be reflected in the result:
POST /rpc HTTP/1.1
Host: localhost:8080
Content-Type: application/json
[
{"id": "call1", "method": "sum", "params": {"a": 100, "b": 37}},
{"id": "call2", "method": "sum", "params": {"a": 63, "b": 74}}
]
Will result in the response:
HTTP/1.1 200 OK
Content-Type: application/json
[
{"id": "call1", "result": 137},
{"id": "call2", "result": 137}
]
We recommend using UUIDs for call IDs.
Handling errors
If an error occurs when executing a call, the response will contain an error property rather than a result property. It's important to note that even erroring responses have a 200
HTTP status code – don't rely on this meaning that your call was successful.
Assuming that your application is running locally on port 8080
:
POST /rpc HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{"method": "sum", "params": "invalid"}
Will result in the response:
HTTP/1.1 200 OK
Content-Type: application/json
{"id": null, "error": {"code": "INVALID_REQUEST", "message": "Call params must be a plain object or undefined"}}
Some errors will also have a data
property which gives more context to the error.
When batching calls, it's possible for some calls to succeed and some to fail as they're executed separately. Take this into consideration when processing results.
Contributing
To contribute to this library, clone this repo locally and commit your code on a separate branch. Please write unit tests for your code, and run the linter before opening a pull-request:
make test # run all tests
make verify # run all linters
License
Licensed under the MIT license. Copyright © 2019, Rowan Manning