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

    Keywords

    none

    Install

    npm i json-rpc-engine

    DownloadsWeekly Downloads

    471,477

    Version

    6.1.0

    License

    ISC

    Unpacked Size

    47.4 kB

    Total Files

    20

    Last publish

    Collaborators

    • sethkfman
    • brad.decker
    • danfinlay
    • kumavis
    • rekmarks
    • metamaskbot
    • gudahtt