https://github.com/MetaMask/json-rpc-engine

RpcEngine——MetaMask/json-rpc-engine

https://github.com/MetaMask/json-rpc-engine

a tool for processing JSON RPC

usage

  1. const RpcEngine = require('json-rpc-engine')
  2. let engine = new RpcEngine()

Build a stack of json rpc processors by pushing in RpcEngine middleware.

通过push RpcEngine中间件构建一个json rpc处理器堆栈,处理步骤为先进后出,handle时得到的结果是与push时作出的处理相关的

  1. engine.push(function(req, res, next, end){
  2. res.result = 42
  3. end()
  4. })

⚠️push是能够对之后handle传入的request(即json rpc的值进行处理,(req, res, next, end)中的req就是handle传入的request)的一些状态进行定义或作出一些相关处理,会在handle处理json rpc时对其造成影响。

比如如果在push中设置res.result = req.id,那么就是将json rpc中传进来的(id: 1)的值传出

res:返回的是在push中经过处理后的json rpc的值,如果push中什么都没有做,那么req与res的值是相同的

JSON RPC are handled asynchronously, stepping down the stack until complete.异步处理request,直到返回结果

  1. let request = { id: 1, jsonrpc: '2.0', method: 'hello' }
  2.  
  3. engine.handle(request, function(err, res){
  4. // do something with res.result,res.result即为push中设置的true
  5. })

RpcEngine middleware has direct access to the request and response objects. It can let processing continue down the stack with next() or complete the request with end().RpcEngine中间件可以直接访问请求和响应对象。它可以使用next()继续处理堆栈,也可以使用end()完成请求

  1. engine.push(function(req, res, next, end){
  2. if (req.skipCache) return next()
  3. res.result = getResultFromCache(req)
  4. end()
  5. })

By passing a 'return handler' to the next function, you can get a peek at the result before it returns.

通过将“返回处理程序”传递给下一个函数,您可以在结果返回之前看到它

  1. engine.push(function(req, res, next, end){
  2. next(function(cb){//就是先压入堆栈中,不进行处理,等到所以push都解决完后再返回处理
  3. insertIntoCache(res, cb)
  4. })
  5. })
  1.  

RpcEngines can be nested by converting them to middleware asMiddleware(engine)。rpcengine可以通过将它们转换为中间件(中间件)来嵌套

  1. const asMiddleware = require('json-rpc-engine/lib/asMiddleware')
  2.  
  3. let engine = new RpcEngine()
  4. let subengine = new RpcEngine()
  5. engine.push(asMiddleware(subengine))

gotchas陷阱

Handle errors via end(err)NOT next(err).解决error使用的是end(),而不是next()

  1. /* INCORRECT */
  2. engine.push(function(req, res, next, end){
  3. next(new Error())
  4. })
  5.  
  6. /* CORRECT */
  7. engine.push(function(req, res, next, end){
  8. end(new Error())
  9. })

json-rpc-engine/test/basic.spec.js

举例说明:

  1. /* eslint-env mocha */
  2. 'use strict'
  3.  
  4. const assert = require('assert')
  5. const RpcEngine = require('../src/index.js')
  6.  
  7. describe('basic tests', function () {
  8.  
  9. it('basic middleware test', function (done) {
  10. let engine = new RpcEngine()
  11.  
  12. engine.push(function (req, res, next, end) {
  13. req.method = 'banana'
  14. res.result = 42
  15. end()
  16. })
  17.  
  18. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
  19.  
  20. engine.handle(payload, function (err, res) {
  21. assert.ifError(err, 'did not error')
  22. assert(res, 'has res')
  23. assert.equal(res.result, 42, 'has expected result')
  24. assert.equal(payload.method, 'hello', 'original request object is not mutated by middleware') //payload.method仍然是'hello',而不会被改成'banana'
  25. done()
  26. })
  27. })
  28.  
  29. it('interacting middleware test', function (done) { //两个push交互
  30. let engine = new RpcEngine()
  31.  
  32. engine.push(function (req, res, next, end) {
  33. req.resultShouldBe = 42
  34. next()
  35. })
  36.  
  37. engine.push(function (req, res, next, end) {
  38. res.result = req.resultShouldBe
  39. end()
  40. })
  41.  
  42. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
  43.  
  44. engine.handle(payload, function (err, res) {
  45. assert.ifError(err, 'did not error')
  46. assert(res, 'has res')
  47. assert.equal(res.result, 42, 'has expected result')
  48. done()
  49. })
  50. })
  51.  
  52. it('erroring middleware test', function (done) {
  53. let engine = new RpcEngine()
  54.  
  55. engine.push(function (req, res, next, end) {
  56. end(new Error('no bueno'))//定义一个错误
  57. })
  58.  
  59. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
  60.  
  61. engine.handle(payload, function (err, res) {
  62. assert(err, 'did error') //测试发现有错,push中定义的
  63. assert(res, 'does have response')
  64. assert(res.error, 'does have error on response')
  65. done()
  66. })
  67. })
  68.  
  69. it('empty middleware test', function (done) {
  70. let engine = new RpcEngine()
  71.  
  72. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } //如果没有push ,handle将报错
  73.  
  74. engine.handle(payload, function (err, res) {
  75. assert(err, 'did error')
  76. done()
  77. })
  78. })
  79.  
  80. it('handle batch payloads', function (done) {
  81. let engine = new RpcEngine()
  82.  
  83. engine.push(function (req, res, next, end) {
  84. res.result = req.id
  85. end()
  86. })
  87.  
  88. let payloadA = { id: 1, jsonrpc: '2.0', method: 'hello' }
  89. let payloadB = { id: 2, jsonrpc: '2.0', method: 'hello' }
  90. let payload = [payloadA, payloadB] //可以一下子handle多个push
  91.  
  92. engine.handle(payload, function (err, res) {
  93. assert.ifError(err, 'did not error')
  94. assert(res, 'has res')
  95. assert(Array.isArray(res), 'res is array')
  96. assert.equal(res[0].result, 1, 'has expected result')
  97. assert.equal(res[1].result, 2, 'has expected result')
  98. done()
  99. })
  100. })

json-rpc-engine/test/asMiddleware.spec.js

  1. /* eslint-env mocha */
  2. 'use strict'
  3.  
  4. const assert = require('assert')
  5. const RpcEngine = require('../src/index.js')
  6. const asMiddleware = require('../src/asMiddleware.js')
  7.  
  8. describe('asMiddleware', function () { //嵌套
  9. it('basic', function (done) {
  10. let engine = new RpcEngine()
  11. let subengine = new RpcEngine()
  12. let originalReq
  13.  
  14. subengine.push(function (req, res, next, end) {
  15. originalReq = req
  16. res.result = 'saw subengine'
  17. end()
  18. })
  19.  
  20. engine.push(asMiddleware(subengine))//将两种嵌套,那么engine就能够使用subengine在push时的定义
  21.  
  22. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
  23.  
  24. engine.handle(payload, function (err, res) {
  25. assert.ifError(err, 'did not error')
  26. assert(res, 'has res')
  27. assert.equal(originalReq.id, res.id, 'id matches')
  28. assert.equal(originalReq.jsonrpc, res.jsonrpc, 'jsonrpc version matches')
  29. assert.equal(res.result, 'saw subengine', 'response was handled by nested engine')
  30. done()
  31. })
  32. })
  33. })

json-rpc-engine/src/idRemapMiddleware.js

  1. const getUniqueId = require('./getUniqueId')
  2.  
  3. module.exports = createIdRemapMiddleware
  4.  
  5. function createIdRemapMiddleware() {
  6. return (req, res, next, end) => {
  7. const originalId = req.id
  8. const newId = getUniqueId()
  9. req.id = newId
  10. res.id = newId
  11. next((done) => {
  12. req.id = originalId
  13. res.id = originalId
  14. done()
  15. })
  16. }
  17. }

测试:

json-rpc-engine/test/idRemapMiddleware.spec.js

  1. /* eslint-env mocha */
  2. 'use strict'
  3.  
  4. const assert = require('assert')
  5. const RpcEngine = require('../src/index.js')
  6. const createIdRemapMiddleware = require('../src/idRemapMiddleware.js')
  7.  
  8. describe('idRemapMiddleware tests', function () {
  9. it('basic middleware test', function (done) {
  10. let engine = new RpcEngine()
  11.  
  12. const observedIds = {
  13. before: {},
  14. after: {},
  15. }
  16.  
  17. engine.push(function (req, res, next, end) {
  18. observedIds.before.req = req.id
  19. observedIds.before.res = res.id //设置使得handle时 res.id = req.id,两者结果相同
  20. next()
  21. })
  22. engine.push(createIdRemapMiddleware())
  23. engine.push(function (req, res, next, end) {
  24. observedIds.after.req = req.id
  25. observedIds.after.res = res.id
  26. // set result so it doesnt error
  27. res.result = true
  28. end()
  29. })
  30.  
  31. let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
  32. const payloadCopy = Object.assign({}, payload)
  33.  
  34. engine.handle(payload, function (err, res) {
  35. assert.ifError(err, 'did not error')
  36. assert(res, 'has res')
  37. // collected data
  38. assert(observedIds.before.req, 'captured ids')
  39. assert(observedIds.before.res, 'captured ids')
  40. assert(observedIds.after.req, 'captured ids')
  41. assert(observedIds.after.res, 'captured ids')
  42. // data matches expectations
  43. assert.equal(observedIds.before.req, observedIds.before.res, 'ids match') //一开始两个是相同的
  44. assert.equal(observedIds.after.req, observedIds.after.res, 'ids match') //之后两个的结果也是相同的,但是变成了newId
  45. // correct behavior
  46. assert.notEqual(observedIds.before.req, observedIds.after.req, 'ids are different') //前后的req.id不同了
  47. assert.equal(observedIds.before.req, res.id, 'result id matches original') //但是before和最后输出的结果res.id还是一样的
  48. assert.equal(payload.id, res.id, 'result id matches original')
  49. assert.equal(payloadCopy.id, res.id, 'result id matches original')
  50. done()
  51. })
  52. })
  53. })

这里可以知道idRemapMiddleware的作用是在过程中间得到一个新的、比较复杂的Id进行一系列处理,但是最后输出的给用户看的表示结果还是一样的

  1.  

MetaMask/json-rpc-engine的更多相关文章

  1. 測试JSON RPC远程调用(JSONclient)

    #include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...

  2. metamask源码学习-metamask-controller.js

    The MetaMask Controller——The central metamask controller. Aggregates other controllers and exports a ...

  3. Guide to Porting MetaMask to a New Environment

    https://github.com/MetaMask/metamask-extension/blob/develop/docs/porting_to_new_environment.md MetaM ...

  4. MetaMask/json-rpc-middleware-stream

    https://github.com/MetaMask/json-rpc-middleware-stream/blob/master/test/index.js#L20 A small toolset ...

  5. MetaMask/metamask-inpage-provider

    https://github.com/MetaMask/metamask-inpage-provider Used to initialize the inpage ethereum provider ...

  6. mascara-2(MetaMask/mascara本地实现)-连接线上钱包

    https://github.com/MetaMask/mascara (beta) Add MetaMask to your dapp even if the user doesn't have t ...

  7. metamask源码学习-inpage.js

    The most confusing part about porting MetaMask to a new platform is the way we provide the Web3 API ...

  8. MetaMask/provider-engine-1

    https://github.com/MetaMask/provider-engine 在学习这个之前应该先看一下什么是zero-client,MetaMask/zero-client Web3 Pr ...

  9. metamask源码学习-contentscript.js

    When a new site is visited, the WebExtension creates a new ContentScript in that page's context, whi ...

随机推荐

  1. Java并发编程-闭锁

    闭锁是一种同步器 ( Synchronizer ),它可以延迟线程的进度直到线程到达终止状态,CountDownLatch是一个灵活的闭锁实现:1)允许一个或多个线程等待一个事件集的发生,闭锁的状态包 ...

  2. 自己写一个java的mvc框架吧(三)

    自己写一个mvc框架吧(三) 根据Method获取参数并转换参数类型 上一篇我们将url与Method的映射创建完毕,并成功的将映射关系创建起来了.这一篇我们将根据Method的入参参数名称.参数类型 ...

  3. 【Dubbo&&Zookeeper】1、Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)

    转自:http://blog.csdn.net/congcong68/article/details/41113239 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架 ...

  4. 【Linux】安装openssh-server依赖openssh-client版本错误的解决办法

    这是因为,openssh-server是依赖于openssh-clien的,ubuntu自带了openssh-client,自带的openssh-clien与所要安装的openssh-server所依 ...

  5. 深入理解Java虚拟机--阅读笔记二

    垃圾收集器与内存分配策略 一.判断对象是否已死 1.垃圾收集器在对堆进行回收前,要先判断对象是否已死.而判断的算法有引用计数算法和可达性分析算法: 2.引用计数算法是给对象添加引用计数器,有地方引用就 ...

  6. 【13】享元模式(FlyWeight Pattern)

    一.引言 在软件开发过程,如果我们需要重复使用某个对象的时候,若重复地使用new创建这个对象的话,就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非常严重.享元模式可以 ...

  7. DNS协议详解

    DNS协议详解 简介 DNS(Domain Name System)域名系统,主要实现的功能是将域名转换成ip地址的一个服务.它是由一个分层的DNS服务器实现的分布式数据库,同时.他也是一个使得主机能 ...

  8. url override and HttpSession implements session for form

    url 重写结合HttpSession实现会话管理之 form 提交 package com.test; import javax.servlet.ServletException; import j ...

  9. Oracle EBS INV创建保留

    CREATE or REPPLACE PROCEDURE CreateReservation AS -- Common Declarations l_api_version NUMBER := 1.0 ...

  10. MySQL-死锁查询

    1.查询是否锁表 show OPEN TABLES where In_use > 0; 查询到相对应的进程 === 然后 kill    id 2.查询进程 show processlist 补 ...