docs: update

This commit is contained in:
avwo
2025-06-28 08:27:08 +08:00
parent 9c51b42b5c
commit becb8d84a4
188 changed files with 493 additions and 673 deletions
+120 -119
View File
@@ -32,185 +32,186 @@ export default defineConfig({
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: '首页', link: '/' },
{ text: '帮助文档', link: '/zh-hans/installation' },
{ text: '帮助文档', link: '/docs/installation' },
],
sidebar: [
{ text: '安装', link: '/zh-hans/installation' },
{ text: '快速上手', link: '/zh-hans/getting-started' },
{ text: '移动端抓包', link: '/zh-hans/mobile' },
{ text: '安装', link: '/docs/installation' },
{ text: '快速上手', link: '/docs/getting-started' },
{ text: '移动端抓包', link: '/docs/mobile' },
{
text: '界面功能',
collapsed: false,
items: [
{ text: 'Network', link: '/zh-hans/gui/network' },
{ text: 'HTTPS', link: '/zh-hans/gui/https' },
{ text: 'Weinre', link: '/zh-hans/gui/weinre' },
{ text: 'Log', link: '/zh-hans/gui/log' },
{ text: 'Composer', link: '/zh-hans/gui/composer' },
{ text: 'Rules', link: '/zh-hans/gui/rules' },
{ text: 'Values', link: '/zh-hans/gui/values' },
{ text: 'Plugins', link: '/zh-hans/gui/plugins' },
{ text: 'Network', link: '/docs/gui/network' },
{ text: 'HTTPS', link: '/docs/gui/https' },
{ text: 'Console', link: '/docs/gui/console' },
{ text: 'Online', link: '/docs/gui/online' },
{ text: 'Composer', link: '/docs/gui/composer' },
{ text: 'Rules', link: '/docs/gui/rules' },
{ text: 'Weinre', link: '/docs/gui/weinre' },
{ text: 'Values', link: '/docs/gui/values' },
{ text: 'Plugins', link: '/docs/gui/plugins' },
]
},
{
text: '规则配置',
collapsed: false,
items: [
{ text: '匹配模式(pattern)', link: '/zh-hans/rules/pattern' },
{ text: '操作指令(operation)', link: '/zh-hans/rules/operation' },
{ text: '@', link: '/zh-hans/rules/@' },
{ text: '匹配模式(pattern)', link: '/docs/rules/pattern' },
{ text: '操作指令(operation)', link: '/docs/rules/operation' },
{ text: '@', link: '/docs/rules/@' },
{
text: 'Map Local',
collapsed: true,
items: [
{ text: 'file', link: '/zh-hans/rules/file' },
{ text: 'xfile', link: '/zh-hans/rules/xfile' },
{ text: 'tpl', link: '/zh-hans/rules/tpl' },
{ text: 'xtpl', link: '/zh-hans/rules/xtpl' },
{ text: 'rawfile', link: '/zh-hans/rules/rawfile' },
{ text: 'xrawfile', link: '/zh-hans/rules/xrawfile' },
{ text: 'file', link: '/docs/rules/file' },
{ text: 'xfile', link: '/docs/rules/xfile' },
{ text: 'tpl', link: '/docs/rules/tpl' },
{ text: 'xtpl', link: '/docs/rules/xtpl' },
{ text: 'rawfile', link: '/docs/rules/rawfile' },
{ text: 'xrawfile', link: '/docs/rules/xrawfile' },
]
},
{
text: 'Map Remote',
collapsed: true,
items: [
{ text: 'https', link: '/zh-hans/rules/https' },
{ text: 'http', link: '/zh-hans/rules/http' },
{ text: 'wss', link: '/zh-hans/rules/wss' },
{ text: 'ws', link: '/zh-hans/rules/ws' },
{ text: 'tunnel', link: '/zh-hans/rules/tunnel' },
{ text: 'https', link: '/docs/rules/https' },
{ text: 'http', link: '/docs/rules/http' },
{ text: 'wss', link: '/docs/rules/wss' },
{ text: 'ws', link: '/docs/rules/ws' },
{ text: 'tunnel', link: '/docs/rules/tunnel' },
]
},
{
text: 'DNS Spoofing',
collapsed: true,
items: [
{ text: 'host', link: '/zh-hans/rules/host' },
{ text: 'xhost', link: '/zh-hans/rules/xhost' },
{ text: 'proxy', link: '/zh-hans/rules/proxy' },
{ text: 'xproxy', link: '/zh-hans/rules/xproxy' },
{ text: 'http-proxy', link: '/zh-hans/rules/http-proxy' },
{ text: 'xhttp-proxy', link: '/zh-hans/rules/xhttp-proxy' },
{ text: 'https-proxy', link: '/zh-hans/rules/https-proxy' },
{ text: 'xhttps-proxy', link: '/zh-hans/rules/xhttps-proxy' },
{ text: 'socks', link: '/zh-hans/rules/socks' },
{ text: 'xsocks', link: '/zh-hans/rules/xsocks' },
{ text: 'pac', link: '/zh-hans/rules/pac' },
{ text: 'host', link: '/docs/rules/host' },
{ text: 'xhost', link: '/docs/rules/xhost' },
{ text: 'proxy', link: '/docs/rules/proxy' },
{ text: 'xproxy', link: '/docs/rules/xproxy' },
{ text: 'http-proxy', link: '/docs/rules/http-proxy' },
{ text: 'xhttp-proxy', link: '/docs/rules/xhttp-proxy' },
{ text: 'https-proxy', link: '/docs/rules/https-proxy' },
{ text: 'xhttps-proxy', link: '/docs/rules/xhttps-proxy' },
{ text: 'socks', link: '/docs/rules/socks' },
{ text: 'xsocks', link: '/docs/rules/xsocks' },
{ text: 'pac', link: '/docs/rules/pac' },
]
},
{
text: 'Rewrite Request',
collapsed: true,
items: [
{ text: 'urlParams', link: '/zh-hans/rules/urlParams' },
{ text: 'pathReplace', link: '/zh-hans/rules/pathReplace' },
{ text: 'sniCallback', link: '/zh-hans/rules/sniCallback' },
{ text: 'method', link: '/zh-hans/rules/method' },
{ text: 'cipher', link: '/zh-hans/rules/cipher' },
{ text: 'reqHeaders', link: '/zh-hans/rules/reqHeaders' },
{ text: 'forwardedFor', link: '/zh-hans/rules/forwardedFor' },
{ text: 'ua', link: '/zh-hans/rules/ua' },
{ text: 'auth', link: '/zh-hans/rules/auth' },
{ text: 'cache', link: '/zh-hans/rules/cache' },
{ text: 'referer', link: '/zh-hans/rules/referer' },
{ text: 'attachment', link: '/zh-hans/rules/attachment' },
{ text: 'reqCharset', link: '/zh-hans/rules/reqCharset' },
{ text: 'reqCookies', link: '/zh-hans/rules/reqCookies' },
{ text: 'reqCors', link: '/zh-hans/rules/reqCors' },
{ text: 'reqType', link: '/zh-hans/rules/reqType' },
{ text: 'reqBody', link: '/zh-hans/rules/reqBody' },
{ text: 'reqMerge', link: '/zh-hans/rules/reqMerge' },
{ text: 'reqPrepend', link: '/zh-hans/rules/reqPrepend' },
{ text: 'reqAppend', link: '/zh-hans/rules/reqAppend' },
{ text: 'reqReplace', link: '/zh-hans/rules/reqReplace' },
{ text: 'reqWrite', link: '/zh-hans/rules/reqWrite' },
{ text: 'reqWriteRaw', link: '/zh-hans/rules/reqWriteRaw' },
{ text: 'trailers', link: '/zh-hans/rules/trailers' },
{ text: 'urlParams', link: '/docs/rules/urlParams' },
{ text: 'pathReplace', link: '/docs/rules/pathReplace' },
{ text: 'sniCallback', link: '/docs/rules/sniCallback' },
{ text: 'method', link: '/docs/rules/method' },
{ text: 'cipher', link: '/docs/rules/cipher' },
{ text: 'reqHeaders', link: '/docs/rules/reqHeaders' },
{ text: 'forwardedFor', link: '/docs/rules/forwardedFor' },
{ text: 'ua', link: '/docs/rules/ua' },
{ text: 'auth', link: '/docs/rules/auth' },
{ text: 'cache', link: '/docs/rules/cache' },
{ text: 'referer', link: '/docs/rules/referer' },
{ text: 'attachment', link: '/docs/rules/attachment' },
{ text: 'reqCharset', link: '/docs/rules/reqCharset' },
{ text: 'reqCookies', link: '/docs/rules/reqCookies' },
{ text: 'reqCors', link: '/docs/rules/reqCors' },
{ text: 'reqType', link: '/docs/rules/reqType' },
{ text: 'reqBody', link: '/docs/rules/reqBody' },
{ text: 'reqMerge', link: '/docs/rules/reqMerge' },
{ text: 'reqPrepend', link: '/docs/rules/reqPrepend' },
{ text: 'reqAppend', link: '/docs/rules/reqAppend' },
{ text: 'reqReplace', link: '/docs/rules/reqReplace' },
{ text: 'reqWrite', link: '/docs/rules/reqWrite' },
{ text: 'reqWriteRaw', link: '/docs/rules/reqWriteRaw' },
{ text: 'reqRules', link: '/docs/rules/reqRules' },
{ text: 'reqScript', link: '/docs/rules/reqScript' },
]
},
{
text: 'Rewrite Reponse',
collapsed: true,
items: [
{ text: 'statusCode', link: '/zh-hans/rules/statusCode' },
{ text: 'replaceStatus', link: '/zh-hans/rules/replaceStatus' },
{ text: 'redirect', link: '/zh-hans/rules/redirect' },
{ text: 'locationHref', link: '/zh-hans/rules/locationHref' },
{ text: 'resHeaders', link: '/zh-hans/rules/resHeaders' },
{ text: 'responseFor', link: '/zh-hans/rules/responseFor' },
{ text: 'resCharset', link: '/zh-hans/rules/resCharset' },
{ text: 'resCookies', link: '/zh-hans/rules/resCookies' },
{ text: 'resCors', link: '/zh-hans/rules/resCors' },
{ text: 'resType', link: '/zh-hans/rules/resType' },
{ text: 'resBody', link: '/zh-hans/rules/resBody' },
{ text: 'resMerge', link: '/zh-hans/rules/resMerge' },
{ text: 'resPrepend', link: '/zh-hans/rules/resPrepend' },
{ text: 'resAppend', link: '/zh-hans/rules/resAppend' },
{ text: 'resReplace', link: '/zh-hans/rules/resReplace' },
{ text: 'htmlPrepend', link: '/zh-hans/rules/htmlPrepend' },
{ text: 'htmlBody', link: '/zh-hans/rules/htmlBody' },
{ text: 'htmlAppend', link: '/zh-hans/rules/htmlAppend' },
{ text: 'cssPrepend', link: '/zh-hans/rules/cssPrepend' },
{ text: 'cssBody', link: '/zh-hans/rules/cssBody' },
{ text: 'cssAppend', link: '/zh-hans/rules/cssAppend' },
{ text: 'jsPrepend', link: '/zh-hans/rules/jsPrepend' },
{ text: 'jsBody', link: '/zh-hans/rules/jsBody' },
{ text: 'jsAppend', link: '/zh-hans/rules/jsAppend' },
{ text: 'resWrite', link: '/zh-hans/rules/resWrite' },
{ text: 'resWriteRaw', link: '/zh-hans/rules/resWriteRaw' },
{ text: 'statusCode', link: '/docs/rules/statusCode' },
{ text: 'replaceStatus', link: '/docs/rules/replaceStatus' },
{ text: 'redirect', link: '/docs/rules/redirect' },
{ text: 'locationHref', link: '/docs/rules/locationHref' },
{ text: 'resHeaders', link: '/docs/rules/resHeaders' },
{ text: 'responseFor', link: '/docs/rules/responseFor' },
{ text: 'resCharset', link: '/docs/rules/resCharset' },
{ text: 'resCookies', link: '/docs/rules/resCookies' },
{ text: 'resCors', link: '/docs/rules/resCors' },
{ text: 'resType', link: '/docs/rules/resType' },
{ text: 'resBody', link: '/docs/rules/resBody' },
{ text: 'resMerge', link: '/docs/rules/resMerge' },
{ text: 'resPrepend', link: '/docs/rules/resPrepend' },
{ text: 'resAppend', link: '/docs/rules/resAppend' },
{ text: 'resReplace', link: '/docs/rules/resReplace' },
{ text: 'htmlPrepend', link: '/docs/rules/htmlPrepend' },
{ text: 'htmlBody', link: '/docs/rules/htmlBody' },
{ text: 'htmlAppend', link: '/docs/rules/htmlAppend' },
{ text: 'cssPrepend', link: '/docs/rules/cssPrepend' },
{ text: 'cssBody', link: '/docs/rules/cssBody' },
{ text: 'cssAppend', link: '/docs/rules/cssAppend' },
{ text: 'jsPrepend', link: '/docs/rules/jsPrepend' },
{ text: 'jsBody', link: '/docs/rules/jsBody' },
{ text: 'jsAppend', link: '/docs/rules/jsAppend' },
{ text: 'trailers', link: '/docs/rules/trailers' },
{ text: 'resWrite', link: '/docs/rules/resWrite' },
{ text: 'resWriteRaw', link: '/docs/rules/resWriteRaw' },
{ text: 'resRules', link: '/docs/rules/resRules' },
{ text: 'resScript', link: '/docs/rules/resScript' },
]
},
{
text: 'General',
collapsed: true,
items: [
{ text: 'pipe', link: '/docs/rules/pipe' },
{ text: 'delete', link: '/docs/rules/delete' },
{ text: 'headerReplace', link: '/docs/rules/headerReplace' },
]
},
{
text: 'Throttle',
collapsed: true,
items: [
{ text: 'reqDelay', link: '/zh-hans/rules/reqDelay' },
{ text: 'resDelay', link: '/zh-hans/rules/resDelay' },
{ text: 'reqSpeed', link: '/zh-hans/rules/reqSpeed' },
{ text: 'resSpeed', link: '/zh-hans/rules/resSpeed' },
{ text: 'reqDelay', link: '/docs/rules/reqDelay' },
{ text: 'resDelay', link: '/docs/rules/resDelay' },
{ text: 'reqSpeed', link: '/docs/rules/reqSpeed' },
{ text: 'resSpeed', link: '/docs/rules/resSpeed' },
]
},
{
text: 'Tools',
collapsed: true,
items: [
{ text: 'weinre', link: '/zh-hans/rules/weinre' },
{ text: 'log', link: '/zh-hans/rules/log' },
{ text: 'weinre', link: '/docs/rules/weinre' },
{ text: 'log', link: '/docs/rules/log' },
]
},
{
text: 'Settings',
collapsed: true,
items: [
{ text: 'style', link: '/zh-hans/rules/style' },
{ text: 'lineProps', link: '/zh-hans/rules/lineProps' },
{ text: 'enable', link: '/zh-hans/rules/enable' },
{ text: 'disable', link: '/zh-hans/rules/disable' },
{ text: 'style', link: '/docs/rules/style' },
{ text: 'lineProps', link: '/docs/rules/lineProps' },
{ text: 'enable', link: '/docs/rules/enable' },
{ text: 'disable', link: '/docs/rules/disable' },
]
},
{
text: 'Filters',
collapsed: true,
items: [
{ text: 'ignore', link: '/zh-hans/rules/ignore' },
{ text: 'skip', link: '/zh-hans/rules/skip' },
{ text: 'excludeFilter', link: '/zh-hans/rules/excludeFilter' },
{ text: 'includeFilter', link: '/zh-hans/rules/includeFilter' },
]
},
{
text: 'Others',
collapsed: true,
items: [
{ text: 'pipe', link: '/zh-hans/rules/pipe' },
{ text: 'delete', link: '/zh-hans/rules/delete' },
{ text: 'headerReplace', link: '/zh-hans/rules/headerReplace' },
{ text: 'reqScript', link: '/zh-hans/rules/reqScript' },
{ text: 'resScript', link: '/zh-hans/rules/resScript' },
{ text: 'reqRules', link: '/zh-hans/rules/reqRules' },
{ text: 'resRules', link: '/zh-hans/rules/resRules' },
{ text: 'ignore', link: '/docs/rules/ignore' },
{ text: 'skip', link: '/docs/rules/skip' },
{ text: 'excludeFilter', link: '/docs/rules/excludeFilter' },
{ text: 'includeFilter', link: '/docs/rules/includeFilter' },
]
},
]
@@ -219,13 +220,13 @@ export default defineConfig({
text: '功能扩展',
collapsed: false,
items: [
{ text: '使用插件', link: '/zh-hans/extensions/usage' },
{ text: '开发插件', link: '/zh-hans/extensions/dev' },
{ text: 'NPM 模块', link: '/zh-hans/extensions/npm' }
{ text: '插件使用', link: '/docs/extensions/usage' },
{ text: '插件开发', link: '/docs/extensions/dev' },
{ text: 'NPM 模块', link: '/docs/extensions/npm' }
]
},
{ text: '命令行操作', link: '/zh-hans/cli' },
{ text: '常见问题', link: '/zh-hans/qa' },
{ text: '命令行操作', link: '/docs/cli' },
{ text: '常见问题', link: '/docs/faq' },
],
socialLinks: [
+3 -3
View File
@@ -185,18 +185,18 @@ Whistle 会检查是否存在同名规则:
1. `w2 install whistle.script`:安装插件
2. `w2 install whistle.script --registry=https://npm-registry`:安装插件,并指定 npm registry
推荐使用界面安装:[使用插件](/zh-hans/extensions/usage)
推荐使用界面安装:[使用插件](/docs/extensions/usage)
## w2 uninstall
`w2 uninstall whistle.script`:卸载指定插件
推荐使用界面卸载:[使用插件](/zh-hans/extensions/usage)
推荐使用界面卸载:[使用插件](/docs/extensions/usage)
## w2 exec
`w2 exec xxx`:执行插件在 package.json 中配置的 bin 命令(即插件提供的可执行脚本)
> 适用于插件开发者或需要调用插件 CLI 功能的场景
## w2 run
`w2 run`:以开发调试模式启动 Whistle,实时输出插件和系统的日志信息到控制台,支持所有 `w2 start` 的参数配置
`w2 run`:以开发调试模式启动 Whistle,实时输出插件和系统的日志信息到控制台,修改界面代码刷新自动生效等,并支持所有 `w2 start` 的参数配置
## 其它参数
1. `-D, --baseDir [baseDir]`:自定义 Whistle 存储根目录(默认为 `$WWHISTLE_PATH/.whistle`)
+57
View File
@@ -0,0 +1,57 @@
# 开发插件
通过查阅[插件使用文档](/docs/extensions/usage),您已经了解插件可实现的各种功能,接下来我们看下如何实现这些功能,为了方便讲解每个核心功能均以独立插件形式演示,实际开发中开发者可以按需自由组合。
## 准备事项
## rules.txt
## reqRules.txt
## resRules.txt
## reqRulesServer
## resRulesServer
## reqStatsServer
## server
## pipe
## 插件操作界面
## Network 上下文菜单
## Network 右侧一级 Tab
## Network / Inspectors 二级 Tab
## Network / Inspectors 三级 Tab
## Network / Composer 二级 Tab
## Network / Tools 二级 Tab
## Rules 上下文菜单
## Values 上下文菜单
所有功能示例的完整实现代码已托管至 GitHub 仓库:
https://github.com/whistle-plugins/examples
+117
View File
@@ -0,0 +1,117 @@
# 使用插件
## 安装插件
1. 点击左侧导航栏的 Plugins 标签页
2. 点击顶部的 Install 按钮
3. 在弹出窗口中输入插件名称(支持同时安装多个插件):
- 多个插件用空格或换行符分隔
- 可指定自定义 npm 镜像源:
- 直接在插件名后添加 --registry=镜像地址
- 或从下拉列表选择历史使用过的镜像源
<img width="1000" alt="install plugins" src="/img/install-plugins.png" />
> 文本框中的冗余文本不会影响结果,Whistle 会自动过滤文本框中的冗余文本,仅提取插件名称及 registry 安装信息
安装成功后,稍等片刻即可在插件列表中查看新安装的插件:
<img width="1000" alt="plugins" src="/img/plugin-list.png" />
## 插件自定义协议
每个插件可注册两种协议类型,配置方式跟普通协议一样:
``` txt
# 长协议
pattern whistle.plugin-name://value [inludeFilter://pattern1 ... excludeFilter://pattern2 ...]
# 短协议
pattern plugin-name://value [inludeFilter://pattern1 ... excludeFilter://pattern2 ...]
```
Whistle 将匹配插件规则的请求与插件对应 Hook 进行交互,可实现以下功能:
> 插件协议的具体功能看各个插件的帮助文档,插件也可以选择隐藏这些协议
1. 实时获取请求头、响应状态码等元数据
2. 对请求动态设置规则
3. 将请求转发给插件,由插件完全控制请求处理流程(需要匹配短协议才能实现)
## pipe 功能
有些请求/响应内容可能被加密或 protobuf 序列化无法看到明文,可通过以下两种方式实现内容查看与修改:
1. **插件全权处理**
- 将请求直接转发至插件
- 插件完全控制处理流程
- 注意事项:
- Whistle 内置规则将失效
- 需插件自行实现所有处理逻辑
- 如需在抓包界面显示解密内容,插件必须调用 Whistle API 回传数据
2. **管道流式处理(推荐)**
- 通过 pipe 协议建立处理管道
- 请求/响应流程:
- 进入 Whistle 时:插件解密
- 离开 Whistle 时:插件加密
- 优势:
- 保持明文请求特性
- 完整支持 Whistle 内置规则
- 抓包界面可直接查看明文
**技术说明:**
- pipe 流功能为可选实现,各插件支持情况请查阅具体文档
- 方案二处理后的请求完全等同于普通明文请求
## 插件操作界面
#### 访问插件操作界面
在 Whistle 插件管理面板中,您可以通过以下任一方式访问插件功能:
1. 点击插件条目右侧的 `Option` 按钮
2. 在插件列表直接单击插件名称
#### 界面特性
**呈现形式:** 模态对话框或独立标签页
**核心能力:**
1. 提供可视化配置和管理功能
2. 支持与 Whistle 核心的实时交互
3. 显示插件运行状态、请求统计数据、日志信息等
#### 技术说明
1. 插件本质上是与 Whistle 直接交互的 HTTP Server
2. 操作界面的具体功能由各插件自行实现
3. 插件可选择不提供操作界面(仅提供后台服务或[命令行操作](/docs/cli#w2-exec))
## 扩展 Whistle 界面功能
插件可通过以下方式增强 Whistle 的用户界面功能:
#### Network 扩展
1. 抓包列表上下文菜单
> 在抓包列表项右键菜单中添加自定义操作
2. 主视图标签页
> 在右侧主面板区创建一级功能标签页
2. Inspectors 分析工具扩展
> 在 Inspectors 面板下添加:
> - 二级功能标签页
> - 三级详细视图标签页
3. Composer 请求构造器扩展
> 在 Composer 工具区添加二级功能标签页
4. Tools 工具集扩展
> 在 Tools 功能区添加二级功能标签页
#### Rules 扩展
左侧列表上下文菜单
> 在左侧规则文件列表的右键菜单中添加功能项
#### Values 扩展
左侧列表上下文菜单
> 在左侧变量文件列表的右键菜单中添加功能项
**实现说明:**
- 各插件可根据功能需求选择适当的扩展位置
- 具体扩展功能和实现方式请参阅各插件的开发文档
- 未使用的扩展点不会影响插件基础功能
## 插件内置规则
## 更新卸载插件
Whistle 会
+61 -7
View File
@@ -1,11 +1,11 @@
# 常见问题
问题或建议请提 [issue](https://github.com/avwo/whistle/issues/new)
遇到问题或建议请提 [issue](https://github.com/avwo/whistle/issues/new)
## Q:抓包列表中出现 `captureError` 的原因?
1. 发出请求的客户端没有安装根证书,安装方法参考:
- PC 端:[安装根证书](/zh-hans/installation)
- 移动端:[安装根证书](/zh-hans/mobile)
- PC 端:[安装根证书](/docs/installation)
- 移动端:[安装根证书](/docs/mobile)
2. `ssl pinning` 问题
- 对该域名的 HTTPS 请求不解密:`域名 disable://capture` 或只针对指定客户端的请求 `域名 disable://capture includeFilter://reqH.user-agent=/xiaomi/i`
- 使用可以规避 `ssl pinning` 的系统或模拟器运行客户端
@@ -25,6 +25,10 @@
> - 将值改为 true
> - 重启浏览器生效
## Q:如何配置双向认证(mTLS)的 HTTPS 请求?
客户端证书设置参考:[@clientCert://](/docs/rules/@)
## Q:如何查看 Whistle 运行过程中的日志?
1. 界面 Network > Tools > Server 查看错误日志
2. 导致进程 Crash 的异常日志文件:`~/.WhistleAppData/whistle.log`
@@ -53,8 +57,8 @@ Whistle 默认会将所有发往代理端口(如 127.0.0.1:8899)的请求视
## Q:如何根据请求内容匹配规则?
利用过滤器:
- [includeFilter](/zh-hans/rules/includeFilter)
- [excludeFilter](/zh-hans/rules/excludeFilter)
- [includeFilter](/docs/rules/includeFilter)
- [excludeFilter](/docs/rules/excludeFilter)
## Q:iOS 安装完根证书还是无法打开 HTTPS 页面的可能原因?
@@ -68,8 +72,8 @@ Whistle 默认会将所有发往代理端口(如 127.0.0.1:8899)的请求视
2. 如果是自己公司的 APP,可以参考[Android 开发文档](https://developer.android.com/training/articles/security-config#base-config) 开启信任用户自定义根证书
## Q:如何对 Whistle 转发的请求设置用户名和密码?
1. Whistle 内部请求认证:`w2 start -n 用户名 -w 密码` 或自己[开发插件](/zh-hans/extensions/dev),防止未授权操作规则和配置
2. 代理请求的权限控制:需要借助插件 [whistle.proxyauth](https://github.com/whistle-plugins/whistle.proxyauth) 或自己[开发插件](/zh-hans/extensions/dev)
1. Whistle 内部请求认证:`w2 start -n 用户名 -w 密码` 或自己[开发插件](/docs/extensions/dev),防止未授权操作规则和配置
2. 代理请求的权限控制:需要借助插件 [whistle.proxyauth](https://github.com/whistle-plugins/whistle.proxyauth) 或自己[开发插件](/docs/extensions/dev)
## Q:如何添加自定义证书?
@@ -87,3 +91,53 @@ Whistle 默认会将所有发往代理端口(如 127.0.0.1:8899)的请求视
> 根证书(必须严格命名)
>
> `root.crt` ↔ `root.key`
## Q:版本更新问题
> 客户端版本只需重新下载最新版本并安装即可:https://github.com/avwo/whistle-client
**命令行版本更新:**
``` sh
npm i -g whistle && w2 restart
```
> 遇到安装慢或安装失败的问题可以尝试改镜像:`npm i -g whistle --registry=https://registry.npmmirror.com && w2 restart`
>
> 遇到权限问题可以加 `sudo`:
>
> ``` sh
> sudo npm i -g whistle
> w2 restart
> ```
重启后命令行显示的 Whistle 版本与当前安装版本不符,可能是 Node.js 版本更新导致 PATH 路径变更。
**解决方法:**
1. 确认版本是否有问题:
``` sh
w2 -V
```
2. 找命令路径(所有系统通用)
``` sh
which w2 # Linux/Mac
where w2 # Windows
```
3. 清理冲突
``` sh
# 删除旧版本(根据上一步找到的路径)
rm -f /usr/local/bin/w2 # 示例路径
# Windows示例(需管理员权限)
del "C:\Program Files\nodejs\w2.cmd"
```
4. 恢复运行,操作完成后执行 `w2 -V` 查看版本是否更新:
- 如果输出的版本还有问题重复上述操作
- 如果命令 `w2` 找不到,请手动配置 PATH
## Q:如何修改 Whistle 文档?
Whistle 文档源文件地址:https://github.com/avwo/whistle/tree/master/docs
本地启动文档服务:
``` sh
npm run docs:dev
```
@@ -26,7 +26,7 @@
<img width="1000" alt="edit request" src="/img/edit-req.png" />
完整功能参见:[界面功能](/zh-hans/gui/network)
完整功能参见:[界面功能](/docs/gui/network)
## 规则配置示例
@@ -102,7 +102,7 @@ pattern operation [includeFilter://pattern1 ... excludeFilter://patternN ...]
^https://**.test.com/*/path/to 127.0.0.1:8080
```
> `*`、`**`、`***` 匹配的范围不同,参见文档:[pattern](/zh-hans/rules/pattern)
> `*`、`**`、`***` 匹配的范围不同,参见文档:[pattern](/docs/rules/pattern)
4. 正则匹配
@@ -163,4 +163,4 @@ pattern resCors://enable
```
> Whistle 会自动将代码块里面的换行符自动替换成空格
完整功能参见:[规则配置](/zh-hans/rules/pattern)
完整功能参见:[规则配置](/docs/rules/pattern)
+5
View File
@@ -0,0 +1,5 @@
# Composer 界面
阿斯顿发撒地方
<img src="/img/composer.png" alt="Composer 界面" width="360" />
+5
View File
@@ -0,0 +1,5 @@
# Console 界面
水电费水电费水电费
<img src="/img/console.png" alt="Console 界面" width="360" />
+5
View File
@@ -0,0 +1,5 @@
# HTTPS 对话框
水电费水电费水电费
<img src="/img/https.png" alt="HTTPS 对话框" width="1000" />
+45
View File
@@ -0,0 +1,45 @@
# Network 界面
查看、管理抓包数据的界面
<img src="/img/network.png" alt="Network 界面" width="1000" />
**顶部菜单:**
1. Record:是否开启、暂停或停止抓包功能,左边图标红色时表示开启(默认开启)
2. Import:导入抓包数据,支持 HAR、SAZ 及 Whistle(`.txt`)自定义的抓包数据格式
3. Export:导出抓包数据,支持 HAR、SAZ 及 Whistle(`.txt`)自定义的抓包数据格式
4. Clear:清空当前界面的抓包数据
5. Replay:重新请求选中的抓包数据
6. Edit:编辑选中的抓包数据
7. Settings:Network 设置对话框
- Exclude Filter:
- Include Filter:
- Network Columns:
- Maximum Rows:
- Viewing only your computer's network requests:
- ViewAll in new window:
- Show Tree View:
8. Weinre:[Weinre 菜单](/docs/gui/https)
9. HTTPS:[HTTPS 对话框](/docs/gui/https)
**左侧列表右键菜单:**
1. Open:
2. Copy:
3. Remove:
4. Settings:
5. Actions:
6. Mock:
7. Import:
8. Export:
9. Others:
**左侧列表底部搜索框:**
1.
**右侧面板功能:**
1. Overview:
2. Inspectors:
3. Timeline:
4. Composer:[Componser 界面](/docs/gui/https)
5. Tools:
+5
View File
@@ -0,0 +1,5 @@
# Online 对话框
水电费水电费水电费
<img src="/img/online.png" alt="Online 对话框" width="1000" />
+5
View File
@@ -0,0 +1,5 @@
# Plugins 界面
水电费水电费水电费
<img src="/img/plugins.png" alt="Plugins 界面" width="1000" />
+5
View File
@@ -0,0 +1,5 @@
# Rules 界面
水电费水电费水电费
<img src="/img/rules.png" alt="Rules 界面" width="1000" />
+5
View File
@@ -0,0 +1,5 @@
# Values 界面
水电费水电费水电费
<img src="/img/values.png" alt="Values 界面" width="1000" />
+5
View File
@@ -0,0 +1,5 @@
# Weinre 菜单
水电费水电费水电费
<img src="/img/weinre.png" alt="Weinre 菜单" width="1000" />
+44
View File
@@ -0,0 +1,44 @@
# @
Whistle 规则中 `@` 符号使用指南
## 规则文件引入 (@path)
**功能:** 动态加载外部规则文件内容(支持自动刷新)
**使用格式:** `@文件路径或URL`
**支持类型:**
- 远程 URL:`@https://example.com/rules.txt`
- 本地文件:`@~/projects/rules.txt`(支持所有操作系统路径)
- 插件接口:`@whistle.nohost/api/rules`(需插件实现接口)
> Windows 路径可混用 / 和 \:
> ``` txt
> @C:/whistle/rules.txt
> @D:\config\proxy.rules
> ```
## 客户端证书配置 (`@clientCert://`)
**功能:** 为双向认证(mTLS)请求指定客户端证书
**使用格式:**
``` txt
@clientCert://key=私钥路径&cert=cert或pem证书路径
或
@clientCert://pwd=passphrase&cert=pfx或p12证书路径
```
**支持类型:**
``` txt
# cert 格式证书
pattern @clientCert://key=/User/xxx/test.key&cert=/User/xxx/test.crt
# pem 格式证书
pattern @clientCert://key=E:\test.pem&cert=E:\test.pem
# pfx 格式证书
pattern @clientCert://pwd=passphrase&pfx=/User/xxx/test.pfx
# p12 格式证书
pattern @clientCert://pwd=passphrase&pfx=E:/test.p12
```
> Windows 路径可混用 `/` 和 `\`

Some files were not shown because too many files have changed in this diff Show More