What is json-rpc-engine?
The json-rpc-engine npm package is a JavaScript library that provides a framework for building JSON-RPC 2.0 servers and clients. It allows you to create middleware stacks to handle JSON-RPC requests and responses, making it easier to manage and extend your JSON-RPC services.
What are json-rpc-engine's main functionalities?
Creating a JSON-RPC Engine
This feature allows you to create a new JSON-RPC engine instance, which serves as the core component for handling JSON-RPC requests and responses.
const { JsonRpcEngine } = require('json-rpc-engine');
const engine = new JsonRpcEngine();
Adding Middleware
You can add middleware to the JSON-RPC engine to handle specific methods or perform actions before passing the request to the next middleware. In this example, a middleware is added to handle the 'hello' method.
engine.push((req, res, next, end) => {
if (req.method === 'hello') {
res.result = 'world';
return end();
}
next();
});
Handling Requests
This feature demonstrates how to handle a JSON-RPC request using the engine. The request is processed through the middleware stack, and the response is returned via a callback function.
const request = { jsonrpc: '2.0', method: 'hello', id: 1 };
engine.handle(request, (err, res) => {
if (err) {
console.error(err);
} else {
console.log(res);
}
});
Other packages similar to json-rpc-engine
jayson
Jayson is a full-featured JSON-RPC 2.0/1.0 server and client for Node.js. It provides a more comprehensive set of features for building JSON-RPC services, including support for both HTTP and TCP transports, batch requests, and more. Compared to json-rpc-engine, Jayson offers a more extensive set of tools for different transport layers and use cases.
jsonrpc-lite
Jsonrpc-lite is a lightweight JSON-RPC 2.0 library for Node.js. It focuses on providing a simple and minimalistic approach to handling JSON-RPC requests and responses. While json-rpc-engine provides a middleware-based architecture, jsonrpc-lite is more straightforward and easier to use for basic JSON-RPC implementations.
node-json-rpc
Node-json-rpc is another JSON-RPC 2.0 server and client library for Node.js. It offers a simple API for creating JSON-RPC servers and clients, with support for both HTTP and WebSocket transports. Compared to json-rpc-engine, node-json-rpc provides a more traditional approach to building JSON-RPC services without the middleware stack.
json-rpc-engine
A tool for processing JSON-RPC requests and responses.
Usage
const { JsonRpcEngine } = require('json-rpc-engine')
let engine = new JsonRpcEngine()
Build a stack of JSON-RPC processors by pushing middleware to the engine.
engine.push(function(req, res, next, end){
res.result = 42
end()
})
Requests are handled asynchronously, stepping down the stack until complete.
let request = { id: 1, jsonrpc: '2.0', method: 'hello' }
engine.handle(request, function(err, response){
})
const response = await engine.handle(request)
Middleware have direct access to the request and response objects.
They can let processing continue down the stack with next()
, or complete the request with end()
.
engine.push(function(req, res, next, end){
if (req.skipCache) return next()
res.result = getResultFromCache(req)
end()
})
By passing a return handler to the next
function, you can get a peek at the result before it returns.
engine.push(function(req, res, next, end){
next(function(cb){
insertIntoCache(res, cb)
})
})
Engines can be nested by converting them to middleware using JsonRpcEngine.asMiddleware()
:
const engine = new JsonRpcEngine()
const subengine = new JsonRpcEngine()
engine.push(subengine.asMiddleware())
async
Middleware
If you require your middleware function to be async
, use createAsyncMiddleware
:
const { createAsyncMiddleware } = require('json-rpc-engine')
let engine = new RpcEngine()
engine.push(createAsyncMiddleware(async (req, res, next) => {
res.result = 42
next()
}))
async
middleware do not take an end
callback.
Instead, the request ends if the middleware returns without calling next()
:
engine.push(createAsyncMiddleware(async (req, res, next) => {
res.result = 42
}))
The next
callback of async
middleware also don't take return handlers.
Instead, you can await next()
.
When the execution of the middleware resumes, you can work with the response again.
engine.push(createAsyncMiddleware(async (req, res, next) => {
res.result = 42
await next()
addToMetrics(res)
}))
You can freely mix callback-based and async
middleware:
engine.push(function(req, res, next, end){
if (!isCached(req)) {
return next((cb) => {
insertIntoCache(res, cb)
})
}
res.result = getResultFromCache(req)
end()
})
engine.push(createAsyncMiddleware(async (req, res, next) => {
res.result = 42
await next()
addToMetrics(res)
}))
Gotchas
Handle errors via end(err)
, NOT next(err)
.
engine.push(function(req, res, next, end){
next(new Error())
})
engine.push(function(req, res, next, end){
end(new Error())
})
However, next()
will detect errors on the response object, and cause
end(res.error)
to be called.
engine.push(function(req, res, next, end){
res.error = new Error()
next()
})