本文主要是让大家对 whistle 功能有个整体认识,详细用法参考帮助文档:wproxy.org/whistle/
如果你还不知道 whistle 是什么,可以访问 GitHub 了解:github.com/avwo/whistl…
目录
操作方式
whistle 的基本上所有操作都可以通过形如下面的配置方式实现(标准模式):
pattern operation1 operation2 ... [filter1 filter2 ...]
其中:
- pattern: 表示匹配请求 URL 的表达式,可以为域名、路径、通配符、正则等(后面会详细说明)
- operation: 表示对应的操作,由 protocol://opValue 组成,protocol 表示操作类型,opValue 表示具体操作,如:reqCookies://(x-env=dev)
- filter(可选): pattern 只能匹配请求的 URL,如果需要根据请求(响应)url、方法、IP、状态码、头、内容等进行更精确的匹配,可以采用 filter,filter 包含 excludeFilter 和 includeFilter 两种过滤方式
如:
ke.qq.com 127.0.0.1:6001 reqCookies://(x-env=test) includeFilter://reqH:user-agent=chrome excludeFilter://m:post
上述表示所有 ke.qq.com
的请求,如果请求头 user-agent
包含 chrome
(不区分大小写)字符串且不是 post
请求,则设置host(127.0.0.1:6001
),并添加请求Cookie(x-env=test
)。
由于本地没有开启
6001
端口的服务,所以请求被拒绝了
如果规则的前两个不同时为 URL,还可以用如下配置方式:
operation pattern1 pattern2 … [filter1 filter2 …]
operation 和 pattern1 不同时为 URL
也可以支持兼容模式:
operation1 operation2 … pattern1 pattern2 … [filter1 filter2 …]
operation1 ... operationN 不能为 URL
如:
127.0.0.1:6001 ke.qq.com fudao.qq.com includeFilter://reqH:user-agent=chrome excludeFilter://m:post
resCors://* *.url.cn *.alicdn.com
127.0.0.1:6001 reqCookies://(x-env=test) ke.qq.com fudao.qq.com includeFilter://reqH:user-agent=chrome excludeFilter://m:post
pattern
pattern 可以为域名,路径,正则,通配符等:
域名匹配
- 匹配指定域名的请求
ke.qq.com 127.0.0.1:6001 10.1.1.1:8080 *.url.cn *.alicdn.com
- 匹配指定域名及端口
# 只能匹配域名 ke.qq.com 且端口 5566 的请求 ke.qq.com:5566 127.0.0.1:6001 # 匹配 http 的 80 端口或 https 的 443 端口 ke.qq.com/ 127.0.0.1:6001
- 匹配指定协议和域名
https://ke.qq.com 127.0.0.1:6001 http://ke.qq.com 127.0.0.1:7001
路径匹配
路径匹配跟域名匹配差不多,只是多了需要匹配路径片段:
- 匹配指定路径的请求
ke.qq.com/statics file:///User/xxx/test ke.qq.com/cgi-bin 10.1.1.1:8080
- 匹配指定路径及端口
file:///User/xxx/test ke.qq.com:8080/page fudao.qq.com/page/ ke.qq.com:8080/cgi-bin 10.1.1.1
- 匹配指定协议和域名
file:///User/xxx/test https://ke.qq.com:8080/page fudao.qq.com/page/ https://ke.qq.com:8080/cgi-bin 10.1.1.1
正则匹配
跟普通 js 的正则表达式一致,支持 /regexp/
和 /regexp/i
两种模式,且支持子匹配,可以在 opValue
获取子匹配的值:
- 所有
ke.qq.com/cgi-bin/
及其子路径ke.qq.com/cgi-bin/path/to?xxx
的请求忽略所有规则(相当于直接请求现网)/^\w+://ke\.qq\.com/cgi-bin\// ignore://*
- 包含
imweb-test
(且忽略大小写)的 URL 请求忽略所有规则/imweb-test/i ignore://*
- 去掉 URL 里面的 md5 后做本替换
/^\w+://\d\.url\.cn/path/to/(\w+)\.\w+\.\w+/ file:///User/test/xxx/dev/$1.$2
通配符匹配
正则表达式涉及转义符及精确匹配,有时写起比较繁琐,为解决这类问题,whistle 提供了通配符匹配解决常用匹配问题:
-
精确匹配
# 只匹配 protocol://ke.qq.com 请求,可以带端口及请求参数,但不包含子路径 $ke.qq.com file:///User/test/index.html # 只匹配 http://ke.qq.com/test.html 请求,可以包含请求参数,但不包含子路径 $http://ke.qq.com file:///User/test/index.html
-
通配路径匹配
# 匹配所有域名下的 /cgi-bin 及其子路径 /cgi-bin/path/to 请求(本地替换会自动补齐后续路径) */cgi-bin file:///User/test/
-
普通通配符匹配(1个或连续几个 * 表示通配符,且可以作为一个子匹配)
^*.url.cn/path/to/*.*.* file:///User/test/xxx/dev/$2.$3
域名匹配、路径匹配、通配路径匹配有一个好处是会自动补齐路径,即:
*/cgi-bin file:///User/test/
请求 https://ke.qq.com/cgi-bin/test.json
会自动匹配本地文件 /User/test/test.json
,而其它匹配方式需要通过子匹配把路径自己补齐,详细匹配规则参见文档:wproxy.org/whistle/pat…
operation
whistle 将每类操作抽象成一个协议,每个具体操作对应一个值,即:operation=protocol://opValue
,protocol 表示操作类型,opValue 表示具体操作。
protocol
whistle 把每类操作抽象成一个 protocol
,如果修改请求方法(method://post
),修改请求头(reqHeaders://x-client=test&x-id=123
),修改响应 cors(resCors://*
) 等等,大致可分成这几类:
@
功能- 设置UI样式
- 设置hosts
- 设代理
- 延迟请求
- 修改请求URL
- 修改请求方法
- 修改请求头
- 延迟响应
- 修改请求内容
- 修改响应状态码
- 修改响应头
- 修改响应内容
- 请求替换
- 过滤配置
- 获取抓包数据
- 动态设置规则
- 开发调试工具
详细文档参见:wproxy.org/whistle/rul…
opValue
每个具体操作对应一个 opValue
,即为一个字符串或对像,opValue
有一下几种写法:
-
内联值:
- 直接内联(不能用空格、换行符等空白字符)
# 一些支持字符串等规则,可以不用小括号 ke.qq.com proxy://127.0.0.1:8888 # 一般需要设置小括号 fudao.qq.com file://(hello) reqCookies://(x-env=test&x-id=abc)
- 内嵌方式(支持任意字符)
``` keyName1 Hello world! -- 2020-1-1 ``` ``` keyName2 x-env: test x-id: abc ``` fudao.qq.com file://{keyName1} reqCookies://{keyName2}
用三个及以上等反引号 ` 对 + 键名作为内嵌值的边界
- 直接内联(不能用空格、换行符等空白字符)
-
Values
对一些比较大对值,不适宜直接内嵌到规则里面,可以放在跟
Rules
同级到Values
里面,用法跟内嵌方式一致。 -
文件或目录
有些内容太大不适合放在 WebUI 里面,或者要本地替换,可以采用文件或目录到方式:
ke.qq.com/test file:///User/statics resCookies:///User/json/cookies.json
ke.qq.com/test 及其子路径请求会自动到 /Users/statics 通过补齐路径找到对应文件,并会设置
/User/json/cookies.json
里面的 cookies -
模板字符串 方便大家在规则里面获取请求 URL、方法、请求参数、请求头、请求Cookie 以及响应等相关内容,whistle 提供了类似 es6 等模板字符串功能,该功能只支持 内联值 或 Values 里面设置的值,不支持文件及目录:
ke.qq.com file://`(${query.test})`
访问
https://ke.qq.com?test=hello
返回hello
``` test.html url: ${url} ``` ke.qq.com file://`{test.html}`
访问
https://ke.qq.com?test=hello
返回url: https://ke.qq.com?test=hello
,也可以放 Values 里面
详细内容参见:wproxy.org/whistle/dat…
filter
pattern
只能匹配请求的 URL,如果根据请求方法、客户端IP、请求头、请求内容,响应状态码,响应头等进行跟灵活精确的匹配,可以采用 filter
,filter
包含 includeFilter
和 excludeFilter
分别用于实现包含及排除匹配规则,一行规则可以用任意多个 filter
:
ke.qq.com/cgi-bin resCors://enable resMerge://retcode=10000 includeFilter://resH:content-type=javascript includeFilter://resH:content-type=json excludeFilter://resH:content-type=gbk
上述配置表示所以 ke.qq.com/cgi-bin
及其子路径 ke.qq.com/cgi-bin/path/to
的请求,如果响应的 content-type
包含(不区分大小写) javascript
或 json
,且不能包含 gbk,则会执行 resCors://enable
和 resMerge://retcode=10000
操作。
如果你觉这一行太长了,也可以写成:
line`
ke.qq.com/cgi-bin resCors://enable resMerge://retcode=10000
includeFilter://resH:content-type=javascript
includeFilter://resH:content-type=json
excludeFilter://resH:content-type=gbk
`
多个 includeFilter
或 excludeFilter
混合时,includeFilter
表示 或
的关系,excludeFilter
表示 且
的关系,即:
pattern operation1 ... excludeFilter://p1 includeFilter://p2 excludeFilter://p3 includeFilter://p4 includeFilter://p5
上述表示 URL 匹配 pattern 的请求,还要匹配 p2 或 p4 或 p5 中的一个,且不能匹配 p1 及 p3。
filter 还支持正则表达式,详细文档参见:wproxy.org/whistle/rul…
其它过滤方式
上面提到的 filter
只能针对单行进行过滤,有时需要在其它行或配置文件里面过滤可能存在的规则,这时可以用 pattern ignore://protocol1|protocol2|...
的方式来过滤指定协议:
^**/cgi-* ignore://*
^**/cgi-proxy ignore://!host
ke.qq.com/index.html ignore://file|host
www.baidu.com ignore://proxy|jsAppend
上述表示所有形如 protocol://xxx/cgi-yyy
及其子路径的请求都忽略所有配置规则,相当于不配任何规则(但 protocol://xxx/cgi-proxy
及其子路径保留 host 规则);ke.qq.com/index.html
的请求忽略本地替换及host规则;www.baidu.com
的所有请求忽略代理及追加jsAppend的规则。
有关 ignore
的内容参见:wproxy.org/whistle/rul…
除了 filter
和 ignore
,还可以结合脚本或插件实现更复杂的匹配方式,具体参见:
- reqScript:wproxy.org/whistle/rul…
- resScript:wproxy.org/whistle/rul…
- 插件:wproxy.org/whistle/plu…
命令行操作
w2 add
:执行当前目录的.whistle.js
文件设置项目规则,详细文档参见:wproxy.org/whistle/cli…w2 i whistle.xxx
:安装 whislte 插件(插件也可以用 npm 全局安装)也可以指定 registy 安装插件:
w2 i whistle.xxx --registry=http://xxx
,或直接用内部命令安装如tnpm
:w2 ti whistle.xxx
w2 uninstall whistle.xxx
:这种卸载方式只支持通过w2 [x]i whistle.xxx
安装的插件w2 run xxx
:执行通过w2 i
安装的插件自带命令(不是全局安装,所以不能直接执行)- whistle 还针对一些特殊场景提供了启动参数或命令行参数支持,具体参见:
w2 help
插件扩展
whistle 提供了强大且较为完善的操作协议,并支持通过插件定制自己的操作协议,每个插件就是一个 npm 包,不仅拥有 whistle 提供的扩展能力,且具备 node 的所有能力,插件至少可以做以下事情:
- 提供UI界面
- 作为请求server
- 统计请求信息(查看上报/打点数据等)
- 设置规则(动态,静态,全局及私有规则)
- 获取抓包数据
- 编解码请求响应数据流(pipe stream 功能)
- 扩展 Network 右键菜单
- 同步 Rules 和 Values 的数据
如何开发、调试、发布、使用插件,这里不赘述,参见文档即可:wproxy.org/whistle/plu…
集成whistle
whistle 不仅支持插件扩展,也可以作为普通 npm 包和插件一起打包到第三方应用,具体实现参考: github.com/nohosts/noh…
总结
本文简单说明了 whistle 的操作方式(pattern operation filter
,其中 operation=protocol://opValue
)、命令行操作、插件扩展、以及如何在应用里面集成 whistle,除此之外 whistle 还有很多功能,很难在一篇文章里面详细罗列清楚,大家结合自身业务不断挖掘其功能,期间有什么问题或建议可以通过 GitHub 的 issue 反馈:github.com/avwo/whistl…