JSPM

  • Created
  • Published
  • Downloads 412520
  • Score
    100M100P100Q181545F
  • License ISC

a tool for processing JSON RPC

Package Exports

  • json-rpc-engine
  • json-rpc-engine/src/asMiddleware
  • json-rpc-engine/src/createAsyncMiddleware
  • json-rpc-engine/src/createScaffoldMiddleware
  • json-rpc-engine/src/idRemapMiddleware
  • json-rpc-engine/src/mergeMiddleware

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (json-rpc-engine) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

json-rpc-engine

A tool for processing JSON-RPC requests and responses.

Usage

const RpcEngine = require('json-rpc-engine')

let engine = new RpcEngine()

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
})

// 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)
  })
})

RpcEngines can be nested by converting them to middleware using asMiddleware(engine):

const asMiddleware = require('json-rpc-engine/src/asMiddleware')

let engine = new RpcEngine()
let subengine = new RpcEngine()
engine.push(asMiddleware(subengine))

async Middleware

If you require your middleware function to be async, use createAsyncMiddleware:

const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')

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. */
})