JSON-RPC MSG
Zero-dependencies library for Node.js and JavaScript to parse and create JSON RPC 2.0 messages.
The json-rpc-msg is a library with zero dependencies that provides an API to parse and create valid JSON-RPC 2.0 messages.
Install:
npm install --save json-rpc-msg
Usage:
const JsonRPC = require('json-rpc-msg');
function sendMessageToClient(message) {
// Some code that sends passed message to clients, e.g. over HTTP or websocket
}
/*--------------------------------------
| Create JSON-RPC request
|--------------------------------------
|*/
const requestObj = JsonRPC.createRequest(123, 'updateUser', {id: 1, name: 'Alex'});
sendMessageToClient(requestObj);
// {
// jsonrpc: '2.0',
// id: 123,
// method: 'updateUser',
// params: {id: 1, name: 'Alex'}
// }
/*--------------------------------------
| Parse JSON-RPC message
|--------------------------------------
|*/
try {
// Valid message:
const message = JsonRPC.parseMessage('{"jsonrpc": "2.0", "id": 123, "method": "update", "params": [1,2,3]}');
// {
// type: 'request',
// payload: {
// id: 123,
// method: 'update',
// params: [1,2,3]
// }
// }
// Invalid message (ParserError will be thrown):
const failedMessage = JsonRPC.parseMessage('not valid JSON RPC message');
}
catch(e) {
// If parser failed to parse message - send error to client:
if (e instanceof JsonRPC.ParserError) {
sendMessageToClient(e.rpcError);
}
// Otherwise throw error up:
else {
throw e;
}
}
Contains list of JSON-RPC error codes. Map with the following structure:
JsonRPC.ERRORS = {
SOME_ERROR: {
code: 123,
message: 'Some message for error'
}
}
Can be used to manually create response with JSON-RPC error:
// Create "Method not found" error for received request with ID=123
const errorObj = JsonRPC.createError(123, JsonRPC.ERRORS.METHOD_NOT_FOUND);
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: -32601,
// message: 'Method not found'
// }
// }
Some particular implementations of JSON-RPC protocol may want to add additional custom errors to this object (note that errors from -32768 to 32000 are reserved for future use, for more information see specification to error object in JSON-RPC v2.0):
JsonRPC.ERRORS.NEW_ERROR_FOR_SOME_IMPLEMENTATION = {
code: -32000,
message: 'Message of added error'
}
const message = JsonRPC.createError(123, JsonRPC.ERRORS.NEW_ERROR_FOR_SOME_IMPLEMENTATION);
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: -32000,
// message: 'Message of added error'
// }
// }
Contains list of supported message types.
- REQUEST - message with "id" and "method" props (and optional "params")
- INTERNAL_REQUEST - the same as REQUEST, but only if "method" starts with "rpc.". This type of request is only for rpc-internal methods and extensions.
- NOTIFICATION - message without "id", and with "method" prop (and optional "params")
- INTERNAL_NOTIFICATION - the same as NOTIFICATION, but only if "method" starts with "rpc.". This type of notification is only for rpc-internal notifications and extensions.
- RESPONSE - message with "id" and "result" props. Represents response from server.
- ERROR - message with "id" and "error" props. Represents response from server with error.
- BATCH - message that is a group of JSON-RPC messages (array).
This constant should be mainly used to check type of parsed message:
const receivedJSON = '{"jsonrpc": "2.0", "id": 1, "method": "log", "params": ["Some string to log"]}';
const message = JsonRPC.parseMessage(receivedJSON);
switch (message.type) {
case JsonRPC.MESSAGE_TYPES.REQUEST:
// Do something with request
break;
case JsonRPC.MESSAGE_TYPES.NOTIFICATION:
// Do something with notification
break;
// ...etc
}
Contains string ("rpc."), that should be added to start of any message/notification that is intended for internal usage of some particular JSON-RPC implementation. e.g:
// Creates notification with name "rpc.someNotification":
const notificationJson = JsonRPC.createInternalNotification(`${JsonRPC.INTERNAL_MESSAGE_PREFIX}someNotification`);
// Because "createInternalNotification" adds this prefix automatically - the following code will
// produce the same result:
const notificationJson2 = JsonRPC.createInternalNotification('someNotification');
console.log(notificationJson === notificationJson2); // => true
Creates JSON-RPC request
NOTE: If method name starts with "rpc." error will be thrown. To create requests for "rpc." methods use createInternalRequest function instead.
id
{string|number}: request IDmethod
{string}: method name to callparams
{Object|Array} (optional): parameters to pass in method
const requestObj = JsonRPC.createRequest(123, 'refreshAllUsers')
// {
// jsonrpc: '2.0',
// id: 123,
// method: 'refreshAllUsers',
// }
const requestObj = JsonRPC.createRequest(123, 'updateUser', {id: 1, name: 'Alex'})
// {
// jsonrpc: '2.0',
// id: 123,
// method: 'updateUser',
// params: {id: 1, name: 'Alex'}
// }
Creates JSON-RPC notification
NOTE: If notification name starts with "rpc." error will be thrown. To create requests for "rpc." notifications use createInternalNotification function instead.
method
{string}: method name to callparams
{Object|Array} (optional): parameters to pass in method
const notificationObj = JsonRPC.createNotification('allUsersWereRefreshed')
// {
// jsonrpc: '2.0',
// method: 'allUsersWereRefreshed'
// }
const notificationObj = JsonRPC.createNotification('userUpdated', {id: 1, name: 'Alex'})
// {
// jsonrpc: '2.0',
// method: 'userUpdated',
// params: {id: 1, name: 'Alex'}
// }
Creates successfull JSON-RPC response to some request
id
{string|number}: request IDresult
{Mixed}: response data
const responseObj = JsonRPC.createResponse(123, {id: 1, name: 'Alex', age: 23})
// {
// jsonrpc: '2.0',
// id: 123,
// response: {id: 1, name: 'Alex', age: 23}
// }
const responseObj = JsonRPC.createResponse(123, null)
// {
// jsonrpc: '2.0',
// id: 123,
// response: null
// }
Creates JSON-RPC response with error
id
{string|number}: request IDerror
{number|{code: number, message: string?}}: error code (number) or object with "code" and optional "message" propertyadditionalErrorData
{Object|Array}: additional data for error
// All of the following statements will produce same result:
const errorResponseObj = JsonRPC.createError(123, -32602);
const errorResponseObj = JsonRPC.createError(123, JsonRPC.ERRORS.INVALID_PARAMS);
const errorResponseObj = JsonRPC.createError(123, {code: -32602});
const errorResponseObj = JsonRPC.createError(123, {code: -32602, message: 'Invalid params'});
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: -32602,
// message: 'Invalid params'
// }
// }
There is ability to provide additional information for error, passing additionalParams argument, e.g. if invalid user name and age where passed in request:
const errorResponseObj = JsonRPC.createError(123, JsonRPC.ERRORS.INVALID_PARAMS, {
name: "User name can't be less then 6 characters",
age: "User age is not defined"
});
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: -32602,
// message: 'Invalid params',
// data: {
// name: 'User name can't be less then 6 characters',
// age: 'User age is not defined'
// }
// }
// }
If error
passed as object with property "code" but without property "message" this method will
look at JsonRPC.ERRORS to find error with given code, and find appropriate message. If there is no
error with given code in ERRORS - message will be defaulted to "Internal Server Error":
JsonRPC.ERRORS.NEW_ERROR = {
code: 666,
message: 'Number of the Beast'
}
// Message will be taken from ERRORS object:
const errorResponseObj = JsonRPC.createError(123, {code: 666});
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: 666,
// message: 'Number of the Beast'
// }
// Message in ERRORS object will not be used because "message" is provided:
const errorResponseObj = JsonRPC.createError(123, {code: 666, message: 'replaced message'});
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: 666,
// message: 'replaced message'
// }
// Error that is not in ERRORS object will have default "Internal Serve Error" message:
const errorResponseObj = JsonRPC.createError(123, {code: 999});
// {
// jsonrpc: '2.0',
// id: 123,
// error: {
// code: 999,
// message: 'Internal Server Error'
// }
Validates and parses given JSON-RPC message
message
{string|Object|array} - JSON string or message object or batch of messages (array)
Returns object with properties "type" and "payload". Type can be one of the types listed in JsonRPC.MESSAGE_TYPES constant. Payload will contain message body, which depends on message type:
- REQUEST and INTERNAL_REQUEST will contain "id", "method" and optional "params" properties:
const message = JsonRPC.parseMessage('{"jsonrpc": "2.0", "id": 123, "method": "update", "params": [1,2,3]}'); // { // type: 'request', // payload: { // id: 123, // method: 'update', // params: [1,2,3] // } // }
- NOTIFICATION and INTERNAL_NOTIFICATION will contain "method" and optional "params" properties:
const message = JsonRPC.parseMessage('{"jsonrpc": "2.0", "method": "updated", "params": [1,2,3]}'); // { // type: 'notification', // payload: { // method: 'updated', // params: [1,2,3] // } // }
- RESPONSE will contain "id" and "result" properties:
const message = JsonRPC.parseMessage('{"jsonrpc": "2.0", "id": 1, "result": [1,2,3]}'); // { // type: 'response', // payload: { // id: 1, // result: [1,2,3] // } // }
- ERROR will contain "id" and "error" properties:
const message = JsonRPC.parseMessage('{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "Invalid params", "data": [1,2,3]}}'); // { // type: 'error', // payload: { // id: 1, // error: { // code: -32602, // message: 'Invalid params', // data: [1,2,3] // } // } // }
- BATCH will contain array of parsed messages in "payload" property. If some of this messages failed to be parsed - there will be an error in this array instead of parsed message:
const message = JsonRPC.parseMessage('['+ '{"jsonrpc": "2.0", "id": 1, "result": "OK"}' + '{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "Invalid params", "data": [1,2,3]}}]' + 'invalid JSON-RPC message' + ']'); // { // type: 'batch', // payload: [ // { // type: 'response', // payload: { // id: 1, // result: [1,2,3] // } // }, // { // type: 'error', // payload: { // id: 1, // error: { // code: -32602, // message: 'Invalid params', // data: [1,2,3] // } // }, // }, // [ParserError Object] // ] // }
The same as createRequest, but allows to create requests with method name that starts with "rpc." prefix. If this prefix is not presented in method name it will be added automatically.
The same as createNotification, but allows to create notification with name that starts with "rpc." prefix. If this prefix is not presented in name it will be added automatically.