json-rpc-engine
TypeScript icon, indicating that this package has built-in type declarations

6.1.0 • Public • Published

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){
  // Do something with response.result, or handle response.error
})
 
// There is also a Promise signature
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 request will end when this returns */
}))

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()
  /* Your return handler logic goes here */
  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).

/* INCORRECT */
engine.push(function(req, res, next, end){
  next(new Error())
})
 
/* CORRECT */
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() /* This will cause end(res.error) to be called. */
})

Dependencies (2)

Dev Dependencies (13)

Package Sidebar

Install

npm i json-rpc-engine

Weekly Downloads

369,061

Version

6.1.0

License

ISC

Unpacked Size

47.4 kB

Total Files

20

Last publish

Collaborators

  • mcmire
  • nicholasellul
  • lgbot
  • naugtur
  • ritave
  • danfinlay
  • kumavis
  • rekmarks
  • metamaskbot
  • gudahtt
  • brad.decker
  • sethkfman