教你开发whistle插件
- 2019 年 12 月 4 日
- 筆記
whistle介绍
whistle是一款用Node实现的跨平台的Web调试代理工具,支持查看修改http(s)、Websocket连接的请求和响应内容。IMWEB团队avenwu作品。github地址:https://github.com/avwo/whistle
whistle安装启动
1、安装whistle
npm install -g whistle
2、 启动whistle
w2 start // 启动whistle w2 restart // 重启whsitle w2 run // 调试模式启动whistle
3、 在浏览器中访问
(1)域名访问 http://local.whistlejs.com/ (2)通过ip+端口来访问,例如: http://127.0.0.1:8899
whistle插件开发
现在想做一个基于whistle的查看请求参数的插件,并将参数以表格的形式展示在页面上
插件命名规范
whistle插件本身就是一个普通的Node模块,只是名字要按照whistle.xxx的形式命名,其中xxx指插件的名称且只能包含小写字母、数字、_、-四种字符,如:whistle.tdw,而xxx就是扩展的协议,可以直接在Rules里面配置使用
插件目录结构
whistle.tdw |__ package.json |__ rules.txt |__ index.js |__ lib |__ ui-server.js |__ plugin-server.js
index.js提供whistle暴露给开发者的接口
// index.js var initPluginServer = require('./lib/plugin-server'); var initUIServer = require('./lib/ui-server'); exports.statsServer = function(server, options) { initPluginServer(server, options); }; exports.uiServer = function(server, options) { initUIServer(server, options); };
statsServer : 处理请求的server,可以做请求合并等,返回的数据就是请求的响应数据, 如上: options 包含一些自定义的头部字段名称及配置信息
{ name: // 插件的名称, RULE_VALUE_HEADER: // 存储配置的规则值的请求头字段, SSL_FLAG_HEADER: // 判断是否为HTTPS请求的请求头字段, FULL_URL_HEADER: // 存储请求完整url的请求头字段, REAL_URL_HEADER: // 存储配置映射到url的请求头字段, NEXT_RULE_HEADER: // 存储配置的下个规则(第一规则为插件)的请求头字段, REQ_ID_HEADER: // 请求的id,可以用于区分响应和请求是否同一个, DATA_ID_HEADER: // 数据包对应的id,不一定存在, STATUS_CODE_HEADER: // 配置的响应状态码, LOCAL_HOST_HEADER: // 配置的hosts, HOST_PORT_HEADER: // 配置的端口, METHOD_HEADER: // 请求方法, debugMode: // 是否是通过w2 run启动的, config: // 包括whistle的端口号port等一系列whistle的配置, storage: //提供本地存储的接口,用法参 考:https://github.com/avwo/whistle/blob/master/lib/rules/util.js }
server是是whistle传给插件的http.Server对象,开发者通过监听server的相关事件处理whistle转发过来的请求
uiServer: local.whistlejs.com/whistle.xxx下的请求都会直接访问该server,可用于后台管理界面
插件调试
把本地node模块link到全局目录:
npm link 开启whistle的调试模式 $ w2 run 这样whistle会自动加载改插件,如果插件有代码更新,需要触发修改package.json这个文件,比如加个空格,或者直接加个字段,每次修改下这个字段,whistle会检查package.json是否有更改,如果更改的话会自动重启。
具体实现
// lib/plugin-server.js module.exports = function(server, options) { FULL_URL_HEADER = options.FULL_URL_HEADER; SSL_FLAG_HEADER = options.SSL_FLAG_HEADER; server.on('request', app); initHttpServer(app); }; function initHttpServer(app) { app.use(function(req, res, next) { dataEvent.emit('data', {query: req.headers}); res.end(''); }); }
打开whistle,访问https://ke.qq.com , 在network界面上能看到很多的请求

通过statsServer接口,我们能获取这些请求。这里通过事件将获取到的请求传递到uiserver中
// ui-server.js module.exports = function(server, options) { FULL_URL_HEADER = options.FULL_URL_HEADER; server.on('request', app); var io = require('socket.io')(server); initHttpServer(app); initWSServer(io); }; function initHttpServer(app) { app.get('/', function(req, res) { res.sendFile(path.join(htdocs, 'index.html')); }); app.get('/js/*', function(req, res) { res.sendFile(path.join(htdocs, 'js/index.js')); }); } function initWSServer(io) { io.on('connection', function (socket) { dataEvent.on('data', function(data) { socket.emit('data', getUrl(data)); }); }); }
在浏览器中访问http://local.whistlejs.com/whistle.tdw ,请求会直接访问uiServer ,如上, uiServer处理请求,返回给浏览器相关的资源文件,展示界面。现在想实时的在页面上展示请求的链接参数,选择socket.io来实现 。 服务端与客户端建立链接,将statsServer传输过来的数据,推给浏览器展示。
客户端js:
// js/index.js var io = require('socket.io-client'); var socket = io({ path: '/whistle.tdw/socket.io' }); socket.on('data', function(data) { var list = self.state.list; list.unshift(decodeReport(data)); self.setState({ list: list }); });
结果页面展示

插件发布
同发布正常的node模块,模块编写完毕, 通过 npm publish 发布