Skip to content

Commit 3e6d41e

Browse files
committed
Squashed 'vendor/whistle/' changes from ce0b2be01d..c646ec6560
c646ec6560 Release v2.9.56 98fd6f4cbe refactor: remove node-native-zip e438fedcc0 docs: w2 add --client b98c4184ac chore: ignore bin/import 0b13eba49d feat: support ipv6-only network 7efa8828fe feat: support esmodule 1fae083bfe docs: client 812dd3ccb6 Release v2.9.55 8bd7b9c018 refactor: update plugins 1d7a20a63d style: refine ui 9ee9ff87f4 Release v2.9.54 b9de59e821 Release v2.9.54 9e542adb9e feat: refine json tree 5975051f80 refactor: refine code 32ce2934ed fix: 暗色模式下,图片受滤镜影响,颜色不正确 4b1c5c0d96 Release v2.9.53 b098b871ac Release v2.9.53 13ab1b0777 feat: darm mode 2c7aff82dd feat: enable://forHttp|forHttps 0ab0004336 docs: update aeabb07810 Update expired link in README.md 5f7f3b3976 Release v2.9.52 d9628fe581 refactor: refine code f87496e4ff refactor: refine file://path ef77eeb064 Release v2.9.51 050a70fd03 Release v2.9.51 9be635db41 fix: avwo/whistle#912 d361eda074 Release v2.9.50 b83f7d11b6 Release v2.9.50 bf0dd13b03 feat: --uiport ip:port 5610a5b046 feat: --uiport ip:port d5d1bcb224 fix: http.request of Node v20.1.0 ef99f187b3 style: refine ui 5f6cd6a3ae refactor: refine ui 8e9fe8aba9 refactor: show the tunnel request of CAPTURE TUNNEL CONNECTS error b2e6e09f71 Release v2.9.49 5273d631be feat: refine editor history f158c7e5cf feat: add sharedStorage 9ac793ac4f fix: command line flags '--cluster' and '--config' 6b93f52608 refactor: refine code c4d939aea1 style: clear cache 9321baabd2 style: clear cache d64487f1a1 refactor: refine code 30ec22f25d refactor: refine code edcc53df53 feat:make the component——editor's history independent 99139f1e2a fix: conflict c73af9c1e6 refactor: refine code e305e8721e fix: headerReplace://req.host 335f8d8354 refactor: headerReplace://reqH.xxx === headerReplace://req.xxx e1c625ddbf Release v2.9.48 66fd5419b0 Release v2.9.48 bbaa81ad6f fix: socksv5 proxy f00e3565ab style: Compose -> Edit b79d6a347e style: exportSessions(sessions, type, name) 98d6244c68 refactor: refine code d9504761ae Release v2.9.47 4e397f001e feat: add activeList 42b40c3479 feat: add customData f4d0cc2a0a feat: add updateUI 3a069a61a5 Release v2.9.46 ef1ebfc87f refactor: refine tpl protocol 897ba0b001 feat: add copyText git-subtree-dir: vendor/whistle git-subtree-split: c646ec6560610b63ee0acaf614ae33fd8c46d848
1 parent d9fb5dd commit 3e6d41e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+3384
-9251
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ node_modules
33
/biz/webui/htdocs/src/js/components
44
/test/assets/values
55
/test/plugins/whistle.test/assets
6+
/bin/import.js

CHANGELOG.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,49 @@
1+
2+
# v2.9.56
3+
1. feat: 支持通过 `Online / IPv6-only network` 强制 dns 获取 ipv6(命令行版本还可以通过 `-M ipv6Only` 开启)
4+
2. feat: `w2 add` 命令支持 `type: module`
5+
# v2.9.55
6+
1. feat: 显示 `captureError`,且可以通过插件获取到这类型错误的抓包数据
7+
2. fix: 完善 `refreshPlugins` 方法(内部方法)
8+
9+
# v2.9.54
10+
1. fix: 修复 Dark Mode 模式下图片显示问题
11+
2. fix: JSON 过滤搜索时保留数组的 index
12+
13+
# v2.9.53
14+
1. feat: 支持通过 `enable://forHttp|forHttps` 设置 `enable://capture` 只对 http 或 https 生效
15+
2. feat: 支持通过请求参数设置登录态
16+
3. feat: 支持 `Dark Mode`,且可以通过界面 `Online -> 打开对话框 -> Disable dark mode` 关闭自动切换 `Dark Mode`
17+
18+
# v2.9.52
19+
1. feat: 跨域请求本地替换自动设置 cors,可以通过 `disable://autoCors``lineProps://disableAutoCors` 关闭
20+
21+
# v2.9.51
22+
1. fix: https://github.com/avwo/whistle/issues/912
23+
# v2.9.50
24+
1. fix: Node 20.1.0 版本 `http.request` 只支持通过 `options.search` 设置参数问题
25+
2. feat: 支持通过 `--uiport "127.0.0.1:8080"` 限制 WebUI 只能通过指定网卡和端口访问
26+
27+
# v2.9.49
28+
1. fix: `headerReplace://req.host:pattern=value` 无效问题
29+
2. feat: 插件添加 `sharedStorage` 方便插件在不同实例中共享存储数据
30+
3. style: https://github.com/avwo/whistle/pull/898
31+
32+
# v2.9.48
33+
1. feat: 插件扩展的右键菜单和 Tab 添加 `exportSessions(sessions, type, name)` 方法
34+
2. feat: 插件 server 的 options 添加 `generateSaz(sessions): Buffer``extract(saz: Buffer, cb(sessions))` 方法
35+
3. refactor: 兼容 saz 的 comment,需要配合插件使用:https://github.com/whistle-plugins/whistle.comment.git
36+
4. fix: 修复访问 socks 代理可能出现 pending 的问题
37+
5. style: 界面优化
38+
39+
# v2.9.47
40+
1. refactor: 解决安装时依赖包安全警告问题
41+
2. feat: 支持自定义右键菜单获取树结点下的所有抓包数据
42+
43+
# v2.9.46
44+
1. feat: 扩展 Tab 支持 `copyText` 方法
45+
2. feat: `tpl` 协议支持模板字符串语法
46+
147
# v2.9.45
248
1. feat: 插件界面提供 `copyText` 方法
349
2. feat: 支持 `lineProps://strictHtml``lineProsy://safeHtml` 只对当前行的规则生效

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
[![NPM count](https://img.shields.io/npm/dt/whistle.svg?style=flat-square)](https://www.npmjs.com/package/whistle)
1313
[![License](https://img.shields.io/npm/l/whistle.svg?style=flat-square)](https://www.npmjs.com/package/whistle)
1414

15+
**Mac 或 Windows 系统推荐使用客户端版本:https://github.com/avwo/whistle-client**
16+
1517
Whistle 是基于 Node 实现的跨平台抓包调试工具,其主要特点:
1618
1. **完全跨平台**:支持 Mac、Windows 等桌面系统,且支持服务端等命令行系统
1719
2. **功能强大(理论上可以对请求做任意修改)**

assets/fiddler/meta.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818
<SessionFlag N="x-hostip" V="${hostip}" />
1919
<SessionFlag N="x-clientport" V="${clientport}" />
2020
<SessionFlag N="x-serverport" V="${serverport}" />
21+
<SessionFlag N="ui-comments" V="${ui-comments}" />
2122
</SessionFlags>
2223
</Session>

assets/launcher/windows/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Windows上配置开机重启whistle
2-
首先,下载Windows上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/raw/avenwu/assets/launcher/windows/whistle.zip)
2+
首先,下载Windows上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/raw/master/assets/launcher/windows/whistle.zip)
33

4-
1. 解压whistle.zip获取whistle.bat的脚本文件,把该脚本文件拷贝一份到Windows的桌面,这样可以直接在Mac的桌面上刊登whistle的启动脚本,双击即可重启whistle(会先弹出一个命令行窗口,等3秒左右就会自动消失);
4+
1. 解压whistle.zip获取whistle.bat的脚本文件,把该脚本文件拷贝一份到Windows的桌面,这样可以直接在Windows的桌面上看到whistle的启动脚本,双击即可重启whistle(会先弹出一个命令行窗口,等3秒左右就会自动消失);
55

66
2. 把桌面上的whistle.bat文件拖到桌面左下角的系统**开始菜单 --> 所有程序 --> 启动**目录下面,或者直接拷贝到系统目录`C:\Users\{yourAccount}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`(可以直接在开始菜单或者文件管理器中的输入框输入`%appData%\Microsoft\Windows\Start Menu\Programs\Startup`快速定位到启动菜单目录),这样就配置好了开机自动重启whistle。
77

8-
![设置Windows开机重启whistle](whistle.gif)
8+
![设置Windows开机重启whistle](whistle.gif)

assets/menu.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,13 @@
157157
Object.keys(options.msgBox).forEach(function(name) {
158158
toast[name] = options.msgBox[name];
159159
});
160+
whistleBridge.updateUI = options.updateUI;
160161
whistleBridge.copyText = options.copyText;
161162
whistleBridge.pageId = options.pageId;
162163
whistleBridge.compose = options.compose;
163164
whistleBridge.decodeBase64 = options.decodeBase64;
164165
whistleBridge.importSessions = options.importSessions;
166+
whistleBridge.exportSessions = options.exportSessions;
165167
whistleBridge.request = options.request;
166168
whistleBridge.createRequest = options.createRequest;
167169
whistleBridge.showModal = options.showModal;

assets/tab.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,13 @@
282282
});
283283
getActiveSession = options.getActiveSession;
284284
getSelectedSessionList = options.getSelectedSessionList;
285+
whistleBridge.updateUI = options.updateUI;
286+
whistleBridge.copyText = options.copyText;
285287
whistleBridge.pageId = options.pageId;
286288
whistleBridge.compose = options.compose;
287289
whistleBridge.decodeBase64 = options.decodeBase64;
288290
whistleBridge.importSessions = options.importSessions;
291+
whistleBridge.exportSessions = options.exportSessions;
289292
whistleBridge.request = options.request;
290293
whistleBridge.createRequest = options.createRequest;
291294
whistleBridge.showModal = options.showModal;

bin/import.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
var fs = require('fs');
2+
3+
function importModle(filepath, callback) {
4+
return import(filepath).then(callback);
5+
}
6+
7+
module.exports = function(filepath, callback) {
8+
try {
9+
return callback(require(filepath));
10+
} catch (e) {
11+
var code =e && e.code;
12+
if (code === 'ERR_REQUIRE_ESM') {
13+
// ignore eslint & fix type=module
14+
return importModle(filepath, callback);
15+
} else if (code === 'MODULE_NOT_FOUND' && /\.js$/i.test(filepath)) {
16+
filepath = filepath.slice(0, -3) + '.mjs';
17+
if (fs.existsSync(filepath)) {
18+
return importModle(filepath, callback);
19+
}
20+
}
21+
throw e;
22+
}
23+
};

bin/plugin.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,21 @@ var commonUtil = require('../lib/util/common');
88

99
var getWhistlePath = commonUtil.getWhistlePath;
1010
var REMOTE_URL_RE = commonUtil.REMOTE_URL_RE;
11+
var WHISTLE_PLUGIN_RE = commonUtil.WHISTLE_PLUGIN_RE;
12+
const getPlugins = commonUtil.getPlugins;
1113
var CMD_SUFFIX = process.platform === 'win32' ? '.cmd' : '';
1214
var CUSTOM_PLUGIN_PATH = path.join(getWhistlePath(), 'custom_plugins');
1315
var DEFAULT_PATH = commonUtil.getDefaultWhistlePath();
1416
var REGISTRY_LIST = path.join(DEFAULT_PATH, '.registry.list');
1517
var PACKAGE_JSON = '{"repository":"https://github.com/avwo/whistle","license":"MIT"}';
1618
var LICENSE = 'Copyright (c) 2019 avwo';
1719
var RESP_URL = 'https://github.com/avwo/whistle';
18-
var WHISTLE_PLUGIN_RE = /^((?:@[\w-]+\/)?whistle\.[a-z\d_-]+)(?:\@([\w.^~*-]*))?$/;
1920
var MAX_REG_COUNT = 100;
2021

2122
function getInstallPath(name, dir) {
2223
return path.join(dir || CUSTOM_PLUGIN_PATH, name);
2324
}
2425

25-
function getPlugins(argv, isInstall) {
26-
return argv.filter(function(name, i) {
27-
if (WHISTLE_PLUGIN_RE.test(name)) {
28-
return true;
29-
}
30-
if (argv[i - 1] === '--registry') {
31-
return false;
32-
}
33-
return isInstall && REMOTE_URL_RE.test(name);
34-
});
35-
}
36-
3726
function removeDir(installPath) {
3827
if (fs.existsSync(installPath)) {
3928
fse.removeSync(installPath);

bin/use.js

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ var path = require('path');
22
var fs = require('fs');
33
var http = require('http');
44
var url = require('url');
5+
var Buffer = require('safe-buffer').Buffer;
56
var util = require('./util');
7+
var importModule = require('./import');
68
var pkg = require('../package.json');
9+
var getHomedir = require('../lib/util/common').getHomedir;
710

811
var isRunning = util.isRunning;
912
var error = util.error;
@@ -14,24 +17,28 @@ var MAX_RULES_LEN = 1024 * 256;
1417
var DEFAULT_OPTIONS = { host: '127.0.0.1', port: 8899 };
1518
var options;
1619

17-
function showStartWhistleTips(storage) {
18-
error('No running whistle, execute `w2 start' + (storage ? ' -S ' + storage : '')
19-
+ '` to start whistle on the cli.');
20+
function showStartWhistleTips(storage, isClient) {
21+
if (isClient) {
22+
error('No running whistle client, please install and start the latest whistle client: https://github.com/avwo/whistle-client');
23+
} else {
24+
error('No running whistle, execute `w2 start' + (storage ? ' -S ' + storage : '') + '` to start whistle on the cli.');
25+
}
2026
}
2127

2228
function handleRules(filepath, callback, port) {
23-
var getRules = require(filepath);
24-
if (typeof getRules !== 'function') {
25-
return callback(getRules);
26-
}
27-
var opts = {
28-
port: port,
29-
existsPlugin: existsPlugin
30-
};
31-
if (options && options.host) {
32-
opts.host = options.host;
33-
}
34-
getRules(callback, opts);
29+
importModule(filepath, function(getRules) {
30+
if (typeof getRules !== 'function') {
31+
return callback(getRules);
32+
}
33+
var opts = {
34+
port: port,
35+
existsPlugin: existsPlugin
36+
};
37+
if (options && options.host) {
38+
opts.host = options.host;
39+
}
40+
getRules(callback, opts);
41+
});
3542
}
3643

3744
function getString(str) {
@@ -75,10 +82,13 @@ function request(body, callback) {
7582
reqOptions.headers = {
7683
'content-type': 'application/x-www-form-urlencoded'
7784
};
85+
if (options.specialAuth) {
86+
reqOptions.headers['x-whistle-special-auth'] = options.specialAuth;
87+
}
7888
reqOptions.method = 'POST';
7989
if (options.username || options.password) {
8090
var auth = [options.username || '', options.password || ''].join(':');
81-
reqOptions.headers.authorization = 'Basic ' + new Buffer(auth).toString('base64');
91+
reqOptions.headers.authorization = 'Basic ' + new Buffer.from(auth).toString('base64');
8292
}
8393
}
8494
var req = http.request(reqOptions, function(res) {
@@ -93,10 +103,13 @@ function request(body, callback) {
93103
req.end(body);
94104
}
95105

96-
function checkDefault(running, storage, callback) {
106+
function checkDefault(running, storage, isClient, callback) {
97107
if (running) {
98108
return callback();
99109
}
110+
if (isClient) {
111+
return callback(true);
112+
}
100113
var execCallback = function(err) {
101114
callback && callback(err);
102115
callback = null;
@@ -114,20 +127,42 @@ function checkDefault(running, storage, callback) {
114127
req.end();
115128
}
116129

117-
module.exports = function(filepath, storage, force) {
118-
storage = storage || '';
119-
var dir = encodeURIComponent(storage);
120-
var config = readConfig(dir) || '';
130+
function readClientConfig() {
131+
var procPath = path.join(getHomedir(), '.whistle_client.pid');
132+
try {
133+
var info = fs.readFileSync(procPath, { encoding: 'utf-8' }).split(',');
134+
if (info.length === 4) {
135+
return {
136+
pid: info[0],
137+
options: {
138+
host: info[1],
139+
port: info[2],
140+
specialAuth: info[3]
141+
}
142+
};
143+
}
144+
} catch (e) {}
145+
}
146+
147+
module.exports = function(filepath, storage, force, isClient) {
148+
var config;
149+
var dir = '';
150+
if (isClient) {
151+
storage = '';
152+
config = readClientConfig() || '';
153+
} else {
154+
storage = storage || '';
155+
dir = encodeURIComponent(storage);
156+
config = readConfig(dir) || '';
157+
if (config.options) {
158+
delete config.options.specialAuth;
159+
}
160+
}
121161
options = config.options || '';
122-
var pid = options && config.pid;
123-
var addon = options && options.addon;
124-
var conf = require('../lib/config');
125-
conf.addon = addon && typeof addon === 'string' ? addon.split(/[|,]/) : null;
126-
conf.noGlobalPlugins = options && options.noGlobalPlugins;
127-
isRunning(pid, function(running) {
128-
checkDefault(running, dir, function(err, port) {
162+
isRunning(options && config.pid, function(running) {
163+
checkDefault(running, dir, isClient, function(err, port) {
129164
if (err) {
130-
return showStartWhistleTips(storage);
165+
return showStartWhistleTips(storage, isClient);
131166
}
132167
filepath = path.resolve(filepath || '.whistle.js');
133168
if (port) {
@@ -158,7 +193,7 @@ module.exports = function(filepath, storage, force) {
158193
'groupName=' + encodeURIComponent(groupName.trim())
159194
].join('&');
160195
request(body, function() {
161-
info('Setting whistle (' + (options.host || '127.0.0.1') + ':' + port + ') rules successful.');
196+
info('Setting whistle' + (isClient ? ' client' : '') + ' (' + (options.host || '127.0.0.1') + ':' + port + ') rules successful.');
162197
});
163198
};
164199
if (force) {

0 commit comments

Comments
 (0)