njs-jsonrpc-2.0
v0.2.2
Published
JSON-RPC 2.0 Client and Server
Downloads
30
Maintainers
Readme
njs-jsonrpc-2.0
Client and Server communicating via JSON-RPC 2.0
protocol.
javascript
implementation for node.js
.
Simple and convenient to use.
restrictions
by-name
parameters ({ "p1": v1, "p2": v2}) are not yet supported by either server or client
Installation
npm install njs-jsonrpc-2.0
Usage
Server
'use strict';
const express = require('express');
const app = express();
app.use(express.json());
const rpcServer = require('njs-jsonrpc-2.0').server('/api/?', app);
rpcServer.add(sum, mul);
rpcServer.add(
'div', (a, b) => a/b,
['inv', a => 1/a]
);
function sum(a, b, c) {
return a + b + c;
}
function mul(m1, m2) {
return m1 * m2;
}
app.listen(80);
Client
'use strict';
const jsonrpc = require('njs-jsonrpc-2.0');
jsonrpc.client('http://localhost/api')
.then(async (rpcClient) => {
let r;
// API method call via client property
try {
r = await rpcClient.sum(2, 3, 4);
console.log(r); // 9
} catch(err) {
console.error(err);
}
// calling an API method via the client's 'call' method
try {
r = await rpcClient.call('mul', 25, 4);
console.log(r); // 100
} catch(err) {
console.error(err);
}
// notification (the result is not important and is not sent by the server)
try {
r = await rpcClient.notify('div', 12, 3);
console.log(r); // undefined
} catch(err) {
// server may return an error if the request is invalid
// and is not recognized by it as 'notification'.
// client will throw appropriate exception
console.error(err);
}
// batch
try {
r = await rpcClient.batch()
.call('sum', 5, 7, 11)
.notify('test_notify')
.call('inv', 5)
.do();
console.log(r); // [23, 0.2]
} catch(err) {
console.error(err);
}
});
API
const jsonrpc = require('njs-jsonrpc-2.0');
exports methods for creating client and server
- server - creates a server instance
- client - creates an instance of the client with receiving a description of the API methods from the service and creating methods of the same name on the client. The method is asynchronous.
- bareClient - instantiates the client without building the service API methods on the client. The method is synchronous.
Server
jsonrpc.server()
jsonrpc.server(path, app)
Creates a server instance with add
, setEndpoints
and apiDescription
methods.
The return value is also a middleware
for express
that adds a jsonrpc
method to the request
object (http.IncomingMessage) to process requests.
const express = require('express');
const app = express();
app.use(express.json());
const server = require('njs-jsonrpc-2.0').server();
app.use(server);
app.get('/api/?', (req, res, next) => {
res.json(server.apiDescription());
});
app.post('/api/?', (req, res, next) => {
req.jsonrpc(res)
.catch(err => {
next(err);
});
});
// the server is created, routing and middleware is configured
// it remains to add API methods:
// server.add(...
// and the server is ready to handle calls
When calling the first form jsonrpc.server()
(no parameters) the server instance has access to
setEndpoints
method (see below), which simplifies server creation a bit
const express = require('express');
const app = express();
app.use(express.json());
const server = require('njs-jsonrpc-2.0').server();
server.setEndpoints('/api/?', app);
// the server is created, routing and middleware is configured
// it remains to add API methods:
// server.add(...
// and the server is ready to handle calls
The second form (jsonrpc.server(path, app)
) accepts parameters similar to setEndpoints
, configures routing and middleware.
With this call, setEndpoints
is not available on the server instance.
const express = require('express');
const app = express();
app.use(express.json());
const server = require('njs-jsonrpc-2.0').server('/api/?', app);
// the server is created, routing and middleware is configured
// it remains to add API methods:
// server.add(...
// and the server is ready to handle calls
methods
server.add(<[name,] fn | tuple>[, [name,] fn, ...])
name
<string> - method name. If specified, this is the name of the API method. If the method implementation (thefn
parameter) is an anonymous function, then this parameter is required.fn
<Function> - a function that implements the method. If the function is named and there is no correspondingname
parameter, then the function name will be used as the API method.
a pair <name>, <function> can be passed as one parameter as an array of two elements with indices 0 - name, 1 - function (elements with indices >1 will be ignored)
Adds a service API method.
API methods added to the service will be called on the request object, i.e. for these methods, this
is instance of http.IncomingMessage
.
server.setEndpoints(path, app)
- path - the path (relative to the application) where the API processed by this server will be available
- app -
express
application instance
Returns: <undefined>
Sets routing to process requests to the jsonrpc2.0 server.
The POST
request handler handles API method calls according to the JSON-RPC 2.0
protocol.
A GET
request returns a description of the API methods.
const app = express();
app.use(express.json());
const rpcServer = jsonrpc.server();
rpcServer.setEndpoints('/api/?', app)
server.apiDescription()
Returns: <Object> object with information about API methods (names of methods and parameters).
Client
const client = jsonrpc.bareClient(address, options)
address
<string|URL|Object> - url where the API is available or object withrequest
methodoptions
<Object> - http(s) request options (see http.request documentation).
Returns: <Object>
The method instantiates a "base" client with three base methods, no service API methods.
If the address
parameter is a string (or URL), then a simple default client based on the nodejs http/https modules is used to connect to the server. This simple client sets the Accept: application/json
and Content-Type: application/json
headers by default.
A custom client can be used to connect to the server (eg based on 'request'
or 'got'
).
If address
parameter is object it must implement request(data, options)
method which returns Promise<string|null|undefined>. If returned value is not empty string it must be JSON. Parameter data
if not <null|undefined> must be JSON-serializable object. It is data for send to the server. Parametert options
is options for request. At this time it is an object with property method
({ method: <"GET"|"POST">}).
Example:
const request = require("request-promise");
// transport protocol client
class TPClient {
constructor(options) {
this.client = request.defaults(options);
}
async request(data, options = {}) {
if (data)
options.body = JSON.stringify(data);
const res = await this.client(options);
return res;
}
}
const rpcClient = await jsonrpc.client(new TPClient({
uri: <apiUrl>,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
agentOptions: { rejectUnauthorized: false }
}));
methods
client.call(name, ...params)
- name <string> - the name of the API method to call
- params - parameters of the called method
Returns: <Promise>, resolved by the value returned by the called API method,
may be rejected with various errors, including errors provided for
protocol JSON-RPC 2.0
client.notify(name, ...params)
- name <string> - the name of the API method to call
- params - parameters of the called method
Returns: <Promise>, undefined
is allowed. Can be rejected with various errors,
for example, with network errors and with errors provided by the JSON-RPC 2.0
protocol
(if the server didn't recognize the request as a notification
).
client.batch()
Returns: <Object>
Creates (returns) a wrapper for a batch call
batch.call(name, ...params)
batch.notify(name, ...params)
Returns: <Object>, wrapper created by batch
method
These methods add a request of the appropriate type to the package.
batch.do()
Completes the formation of the request package and initiates the execution of the generated request.
Returns: <Promise>. If successful, an array of results is returned.
Array elements can be the results of API methods, or errors JsonRpcClientError
, JsonRpcServerError
.
The order of the results corresponds to the order of the queries.
Entries matching notification
are skipped, but may appear as errors if
server-side, the request entry was not recognized as a notification
(this situation can be
recognize by id: null
).
client = jsonrpc.client(address, headers, opts)
A method similar to bareClient
, but in addition it tries obtaining a description of API methods
from the service and creating methods of the same name on the client (if successful).
Returns: <Promise> which is resolved by the generated client. May be
rejected with invalid address
parameter value.
A wrapper created by the batch
method does not have methods created.
If the service API implements the call
, notify
and/or batch
methods, then such
methods will not be created on the client and can only be accessed by the base
way (client.call('batch', ...)
).
Errors
njs-jsonrpc-2.0
defines error classes to represent JSON-RPC 2.0
protocol errors.
Errors contain the following information:
{
code: <string> // string like 'E_JSONRPC20_*'
no: <number> // numeric error code like -3xxxx, according to the specification
message: <string> // string describing the error
}
JsonRpcError
base class ofJSON-RPC 2.0
protocol errors- 'E_JSONRPC20', -32000, 'Json RPC 2.0 protocol error' - generic protocol error
JsonRpcServerError
server errors, as per spec- 'E_JSONRPC20_АPPLICATION_ERROR', -32099, 'Application error' - Errors that occur in the application. Additional information about the error is passed in the 'data' field.
- 'E_JSONRPC20_INVALID_REQUEST', -32600, 'Invalid Request' - The JSON sent is not a valid Request object.
- 'E_JSONRPC20_METHOD_NOT_FOUND', -32601, 'Method not found' - The method does not exist / is not available.
- 'E_JSONRPC20_INVALID_PARAMS', -32602, 'Invalid params' - Invalid method parameter(s).
- 'E_JSONRPC20_INTERNAL_ERROR', -32603, 'Internal error' - Internal JSON-RPC error.
- 'E_JSONRPC20_PARSE_ERROR', -32700, 'Parse error' - Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.
JsonRpcClientError
(spec extension) errors occurring on the client side- 'E_JSONRPC20_INVALID_RESPONSE', -31600, 'Invalid response' - The JSON sent is not a valid Response object.
- 'E_JSONRPC20_MISMATCHED_IDS', -31601, 'Mmismatched IDs' - Mismatched request and response IDs.
- 'E_JSONRPC20_RESPONSE_PARSE_ERROR', -31700, 'Response parse error' - Invalid JSON was received by the client. An error occurred on the client while parsing the JSON text.