npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

whistle.script

v1.2.10

Published

The plugin for the extension script for whistle

Downloads

208

Readme

whistle.script

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

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

安装

  1. 安装Node: 官网下载安装最新版本(LTS和Stable都可以)

  2. 安装最新版的whistle

     npm install -g whistle
    	
     # Mac、Linux用户可能需要加sudo
     sudo npm install -g whistle
  3. 安装script插件:

     w2 i whistle.script

使用

打开script插件的界面,创建一个名字为 test 的脚本:

  1. 可以通过 Plugins->Home->script打开或右键并选择 在新标签页中打开
  2. 直接访问 http://local.whistlejs.com/plugin.script

whistle.script界面

设置规则

  1. 设置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.comhttp://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.' };
     };
  2. 设置WebSocket请求的规则(需要开启HTTPs拦截):

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

    接下来的操作同上。

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

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

    接下来的操作同上。

操作请求

  1. 操作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.comhttp://www.qq.com,可以在script的界面中的Consle看到打印出来的请求的url、响应状态吗和头部。

    具体效果见图:demo2

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

  2. 操作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](https://www.websocket.org/echo.html),点击下面的connect按钮及send按钮,可以如下效果:[demo3](https://user-images.githubusercontent.com/11450939/126302243-26c8b4af-851c-4b00-87b9-3286e9e67251.gif)
  3. 操作Tunnel请求

    exports.handleTunnel = async (socket, connect) => {
    	const svrSocket = await connect();
    	socket.pipe(svrSocket).pipe(socket);
    };

    whistle规则配置同上

  4. 鉴权 插件 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
};
  1. 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);
};

如何引入第三方模块

使用绝对路径引入,如假设你的模块安装路径为 /Users/test/node_modules/xxx,则可以在脚本里面通过 require('/Users/test/node_modules/xxx') 引入。

License

MIT