【无标题】whistle关于调试websocket的一些补充

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

之前看到一篇whistle调试websocket的文章,有些地方困惑了我许久,今天找到了答案。

一、初入whistle,关于调试websocket的文章

https://juejin.cn/post/6844903592625700871
这篇文中使用了whistle.script,不了解的人可能连语法参数都看不懂,其实再github上有这个插件的说明与例子。

二、github原地址

https://github.com/whistle-plugins/whistle.script

三、github原文

纯复制,以便需要的时候翻看
whistle.script
whistle.script为whistle的一个扩展脚本插件,可以直接在界面上引用全局安装的Node模块及Node的内容模块编写脚本操作请求及其响应,所有正常Node程序可以实现的功能,都可以通过该插件实现,包括:

HTTP[s]:
动态设置whistle规则
拦截请求响应
控制请求响应速度
修改请求url、请求方法、请求头、请求内容
修改响应状态码、响应头、响应内容
在插件界面的Console上显示脚本程序 console.xxx 的内容,如果可以打印响应的内容或调试信息等
WebSocket:
动态设置whistle规则
拦截请求响应
修改发送或收到的数据
直接向WebSocket客户端或服务端发送数据
在插件界面的Console上显示脚本程序 console.xxx 的内容,如果可以打印发送和接收到的数据或调试信息等,从而通过该插件可以直接查看WebSocket的数据
Tunnel: 基本功能同WebSocket,可以用来直接操作Socket请求,如Protobuf协议的请求等
安装
安装Node: 官网下载安装最新版本(LTS和Stable都可以)

安装最新版的whistle。

npm install -g whistle

Mac、Linux用户可能需要加sudo

sudo npm install -g whistle
安装script插件:

w2 i whistle.script
使用
打开script插件的界面,创建一个名字为 test 的脚本:

可以通过 Plugins->Home->script打开或右键并选择 在新标签页中打开
直接访问 http://local.whistlejs.com/plugin.script
whistle.script界面
在这里插入图片描述

设置规则
设置HTTP或HTTPs请求的whistle规则(操作HTTPs需要开启HTTPs拦截)

在界面中的test 脚本输入(也可以在其它编辑器编辑后再copy进来):

exports.handleRequestRules = (ctx) => {
// ctx.fullUrl 可以获取请求url
// ctx.headers 可以获取请求头
// ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请求方法、设置的规则等
ctx.rules = [‘www.qq.com file://{test.html}’];
ctx.values = { ‘test.html’: ‘Hello world.’ };
};
Note: 如果里面包含一些异步方法可以采用 async 函数,即:exports.handleRequestRules = async () => {}

在whistle的Rules配置界面上输入规则:

whistle.script://test www.ifeng.com www.qq.com www.baidu.com echo.websocket.org
分别访问http://www.ifeng.com和http://www.qq.com,前者可以正常访问,后者输出 Hello world.。

具体效果见图:demo1

如果需要通过配置给脚本传递一些额外参数,可以如下配置(注意中间不能有空格):

whistle.script://test(a,b,c) www.ifeng.com www.qq.com www.baidu.com echo.websocket.org
可以在脚本中通过 process.args 获取:

exports.handleRequestRules = (ctx) => {
console.log(process.args); // output: [“a”, “b”, “c”]
ctx.rules = [‘www.qq.com file://{test.html}’];
ctx.values = { ‘test.html’: ‘Hello world.’ };
};
设置WebSocket请求的规则(需要开启HTTPs拦截):

exports.handleWebSocketRules = (ctx) => {
// ctx.fullUrl 可以获取请求url
// ctx.headers 可以获取请求头
// ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请求方法、设置的规则等
this.rules = ‘127.0.0.1 echo.websocket.org’;
};
接下来的操作同上。

设置Tunnel请求的规则(要测试可以暂时关闭HTTPs拦截):

exports.handleTunnel = (ctx) => {
// ctx.fullUrl 可以获取请求url
// ctx.headers 可以获取请求头
// ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请求方法、设置的规则等
this.rules = ‘127.0.0.1 www.baidu.com’;
};
接下来的操作同上。

操作请求
操作HTTP或HTTPs请求(操作HTTPs需要开启HTTPs拦截)

exports.handleRequest = async (ctx, request) => {
// ctx.fullUrl 可以获取请求url
// ctx.headers 可以获取请求头
// ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请设置的规则等
// ctx.method 获取和设置请求方法
// ctx.req
// ctx.res
const { req, res } = ctx;
const client = request((svrRes) => {
res.writeHead(svrRes.statusCode, svrRes.headers);
svrRes.pipe(res);
// try {
// const body = await ctx.getStreamBuffer(svrRes);
// delete svrRes.headers[‘content-encoding’];
// res.writeHead(svrRes.statusCode, svrRes.headers);
// res.end(body);
// } catch (err) {}
});
req.pipe(client);
};
在whistle的Rules配置界面上输入规则:

这里不能用whistle.script,否则请求不会转发到handleRequest

whistle.script只会执行handleXxxRules

你也可以通过在handleXxxRules里面设置 script://test(a,b,c),实现转发

script://test www.ifeng.com www.qq.com www.baidu.com echo.websocket.org
分别访问http://www.ifeng.com和http://www.qq.com,可以在script的界面中的Consle看到打印出来的请求的url、响应状态吗和头部。

具体效果见图:demo2

需要在配置中带上参数,可以参考上面的规则设置

操作WebSocket请求(需要开启HTTPs拦截)

exports.handleWebSocket = async (socket, connect) => {
// 与服务器建立连接
const svrSocket = await connect();
// 客户端 pong 服务端
socket.on(‘pong’, (data) => {
svrSocket.pong(data);
});
// 客户端 ping 服务pong 端
socket.on(‘ping’, (data) => {
svrSocket.ping(data);
});
// 服务端 ping 客户端
svrSocket.on(‘ping’, (data) => {
socket.ping(data);
});
// 服务端 pong 客户端
svrSocket.on(‘pong’, (data) => {
socket.pong(data);
});
// 正常断开 WebSocket 连接
socket.on(‘disconnect’, (code, message, opts) => {
console.log(code, ‘client disconnect’);
svrSocket.disconnect(code, opts);
});
// 正常断开 WebSocket 连接
svrSocket.on(‘disconnect’, (code, message, opts) => {
console.log(code, ‘server disconnect’);
socket.disconnect(code, opts);
});
// 获取客户端解析后的帧数据
socket.on(‘message’, (data, opts) => {
console.log(data, ‘client data’);
svrSocket.send(data, opts);
});
// 获取服务端解析后的帧数据
svrSocket.on(‘message’, (data, opts) => {
console.log(data, ‘server data’);
socket.send(data, opts);
});
};
whistle规则配置同上,访问https://www.websocket.org/echo.html,点击下面的connect按钮及send按钮,可以如下效果:demo3
操作Tunnel请求

exports.handleTunnel = async (socket, connect) => {
const svrSocket = await connect();
socket.pipe(svrSocket).pipe(socket);
};
whistle规则配置同上

鉴权 插件 v1.2.0 版本开始支持自定义鉴权方法(要求 Whistle 版本 >= v2.7.16):

exports.auth = async (req, options) => {
// 给请求添加自定义头,必须与 x-whistle- 开头
// 这样可以在插件的其他 hook 里面获取到该请求头(除了 http 请求的 reqRead 钩子)
req.setHeader(‘x-whistle-test’, ‘1111111111’);
// return false; // 直接返回 403
};
pipe 插件 v1.2.1 版本开始支持自定义 pipe 方法:
exports.handleReqRead = (req, res, options) => {
req.pipe(res);
};

exports.handleReqWrite = (req, res, options) => {
req.pipe(res);
};

exports.handleResRead = (req, res, options) => {
req.pipe(res);
};

exports.handleResWrite = (req, res, options) => {
req.pipe(res);
};

exports.handleWsReqRead = (req, res, options) => {
req.pipe(res);
};

exports.handleWsReqWrite = (req, res, options) => {
req.pipe(res);
};

exports.handleWsResRead = (req, res, options) => {
req.pipe(res);
};

exports.handleWsResWrite = (req, res, options) => {
req.pipe(res);
};

exports.handleTunnelReqRead = (req, res, options) => {
req.pipe(res);
};

exports.handleTunnelReqWrite = (req, res, options) => {
req.pipe(res);
};

exports.handleTunnelResRead = (req, res, options) => {
req.pipe(res);
};

exports.handleTunnelResWrite = (req, res, options) => {
req.pipe(res);
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值