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

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

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

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

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

⚠️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,直到返回结果

let request = { id: 1, jsonrpc: '2.0', method: 'hello' }

engine.handle(request, function(err, res){
// do something with res.result,res.result即为push中设置的true
})

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()完成请求

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){//就是先压入堆栈中,不进行处理,等到所以push都解决完后再返回处理
insertIntoCache(res, cb)
})
})
 

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

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

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

gotchas陷阱

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

/* INCORRECT */
engine.push(function(req, res, next, end){
next(new Error())
}) /* CORRECT */
engine.push(function(req, res, next, end){
end(new Error())
})

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

举例说明:

/* eslint-env mocha */
'use strict' const assert = require('assert')
const RpcEngine = require('../src/index.js') describe('basic tests', function () { it('basic middleware test', function (done) {
let engine = new RpcEngine() engine.push(function (req, res, next, end) {
req.method = 'banana'
res.result = 42
end()
}) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) {
assert.ifError(err, 'did not error')
assert(res, 'has res')
assert.equal(res.result, 42, 'has expected result')
assert.equal(payload.method, 'hello', 'original request object is not mutated by middleware') //payload.method仍然是'hello',而不会被改成'banana'
done()
})
}) it('interacting middleware test', function (done) { //两个push交互
let engine = new RpcEngine() engine.push(function (req, res, next, end) {
req.resultShouldBe = 42
next()
}) engine.push(function (req, res, next, end) {
res.result = req.resultShouldBe
end()
}) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) {
assert.ifError(err, 'did not error')
assert(res, 'has res')
assert.equal(res.result, 42, 'has expected result')
done()
})
}) it('erroring middleware test', function (done) {
let engine = new RpcEngine() engine.push(function (req, res, next, end) {
end(new Error('no bueno'))//定义一个错误
}) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) {
assert(err, 'did error') //测试发现有错,push中定义的
assert(res, 'does have response')
assert(res.error, 'does have error on response')
done()
})
}) it('empty middleware test', function (done) {
let engine = new RpcEngine() let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } //如果没有push ,handle将报错 engine.handle(payload, function (err, res) {
assert(err, 'did error')
done()
})
}) it('handle batch payloads', function (done) {
let engine = new RpcEngine() engine.push(function (req, res, next, end) {
res.result = req.id
end()
}) let payloadA = { id: 1, jsonrpc: '2.0', method: 'hello' }
let payloadB = { id: 2, jsonrpc: '2.0', method: 'hello' }
let payload = [payloadA, payloadB] //可以一下子handle多个push engine.handle(payload, function (err, res) {
assert.ifError(err, 'did not error')
assert(res, 'has res')
assert(Array.isArray(res), 'res is array')
assert.equal(res[0].result, 1, 'has expected result')
assert.equal(res[1].result, 2, 'has expected result')
done()
})
})

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

/* eslint-env mocha */
'use strict' const assert = require('assert')
const RpcEngine = require('../src/index.js')
const asMiddleware = require('../src/asMiddleware.js') describe('asMiddleware', function () { //嵌套
it('basic', function (done) {
let engine = new RpcEngine()
let subengine = new RpcEngine()
let originalReq subengine.push(function (req, res, next, end) {
originalReq = req
res.result = 'saw subengine'
end()
}) engine.push(asMiddleware(subengine))//将两种嵌套,那么engine就能够使用subengine在push时的定义 let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) {
assert.ifError(err, 'did not error')
assert(res, 'has res')
assert.equal(originalReq.id, res.id, 'id matches')
assert.equal(originalReq.jsonrpc, res.jsonrpc, 'jsonrpc version matches')
assert.equal(res.result, 'saw subengine', 'response was handled by nested engine')
done()
})
})
})

json-rpc-engine/src/idRemapMiddleware.js

const getUniqueId = require('./getUniqueId')

module.exports = createIdRemapMiddleware

function createIdRemapMiddleware() {
return (req, res, next, end) => {
const originalId = req.id
const newId = getUniqueId()
req.id = newId
res.id = newId
next((done) => {
req.id = originalId
res.id = originalId
done()
})
}
}

测试:

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

/* eslint-env mocha */
'use strict' const assert = require('assert')
const RpcEngine = require('../src/index.js')
const createIdRemapMiddleware = require('../src/idRemapMiddleware.js') describe('idRemapMiddleware tests', function () {
it('basic middleware test', function (done) {
let engine = new RpcEngine() const observedIds = {
before: {},
after: {},
} engine.push(function (req, res, next, end) {
observedIds.before.req = req.id
observedIds.before.res = res.id //设置使得handle时 res.id = req.id,两者结果相同
next()
})
engine.push(createIdRemapMiddleware())
engine.push(function (req, res, next, end) {
observedIds.after.req = req.id
observedIds.after.res = res.id
// set result so it doesnt error
res.result = true
end()
}) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
const payloadCopy = Object.assign({}, payload) engine.handle(payload, function (err, res) {
assert.ifError(err, 'did not error')
assert(res, 'has res')
// collected data
assert(observedIds.before.req, 'captured ids')
assert(observedIds.before.res, 'captured ids')
assert(observedIds.after.req, 'captured ids')
assert(observedIds.after.res, 'captured ids')
// data matches expectations
assert.equal(observedIds.before.req, observedIds.before.res, 'ids match') //一开始两个是相同的
assert.equal(observedIds.after.req, observedIds.after.res, 'ids match') //之后两个的结果也是相同的,但是变成了newId
// correct behavior
assert.notEqual(observedIds.before.req, observedIds.after.req, 'ids are different') //前后的req.id不同了
assert.equal(observedIds.before.req, res.id, 'result id matches original') //但是before和最后输出的结果res.id还是一样的
assert.equal(payload.id, res.id, 'result id matches original')
assert.equal(payloadCopy.id, res.id, 'result id matches original')
done()
})
})
})

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

 

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. Jave Web阿里云短信服务发送验证码

    首先得在阿里云根据流程开通短信服务,申请签名和模版,具体看文档 因为这是个web项目,用到了thymeleaf模板,所以在pom.xml中加入如下依赖 <dependency> <g ...

  2. You can Solve a Geometry Problem too (hdu1086)几何,判断两线段相交

    You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3276 ...

  3. Dijkstra和Prim算法的区别

    Dijkstra和Prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的点集合A ...

  4. Liunx下配置网络

    1.首先查看一下自己的网络 ifconfig 我查看之后发现....没有eth0 ok,现在去 /etc/sysconfig/network-scripts 目录中查看是否有 ifcfg-et0 文件 ...

  5. Codeforces445B(SummerTrainingDay06-N 并查集)

    B. DZY Loves Chemistry time limit per test:1 second memory limit per test:256 megabytes input:standa ...

  6. MySQL入门详解(三)---mysql如何进行主从配置

    基本要求 两台服务器(windows,linux,mac) 双方mysql版本需一致,如不一致,只要主节点低于从节点 两台服务器防火墙关闭 双方数据库所用的用户,要具有远程访问的权限 主服务器配置 修 ...

  7. 【js实例】Array类型的9个数组方法,Date类型的41个日期方法,Function类型

    前文提要:[js实例]js中的5种基本数据类型和9种操作符 Array类型的9个数组方法 Array中有9个数组方法: 1.检测数组 2.转换方法 3.栈方法 4.队列方法 5.冲排序方法6.操作方法 ...

  8. Vue + WebPack + Typescript初学者VSCode项目 (按需加载、跨域调试、await/async)

    万事开头难,一个好的Hello World程序可以节省我们好多的学习时间,帮助我们快速入门.Hello World程序之所以是入门必读必会,就是因为其代码量少,简单易懂.但我觉得,还应该做到功能丰富, ...

  9. Android--根据子控件的大小自动换行的ViewGroup

    1.自定义ViewGroup /** * Created by Administrator on 2016/2/26. * * --------自动换行的ViewGroup----------- */ ...

  10. Fusion 360教程合集27部

    Fusion 360教程合集27部 教程格式:MP4和flv 等格式 使用版本:教程不是一年出的教程,各个版本都有 (教程软件为英文版) 教程格式:MP4.FLV等视频格式 清晰度:可以看清软件上的文 ...