whistle 功能一览

4,948 阅读8分钟

本文主要是让大家对 whistle 功能有个整体认识,详细用法参考帮助文档:wproxy.org/whistle/

如果你还不知道 whistle 是什么,可以访问 GitHub 了解:github.com/avwo/whistl…

目录

  1. 操作方式
  2. 命令行操作
  3. 插件扩展
  4. 集成whistle
  5. 总结

操作方式

whistle 的基本上所有操作都可以通过形如下面的配置方式实现(标准模式):

pattern operation1 operation2 ... [filter1 filter2 ...]

其中:

  1. pattern: 表示匹配请求 URL 的表达式,可以为域名、路径、通配符、正则等(后面会详细说明)
  2. operation: 表示对应的操作,由 protocol://opValue 组成,protocol 表示操作类型,opValue 表示具体操作,如:reqCookies://(x-env=dev)
  3. 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 可以为域名,路径,正则,通配符等:

域名匹配

  1. 匹配指定域名的请求
    ke.qq.com 127.0.0.1:6001
    10.1.1.1:8080 *.url.cn *.alicdn.com
    
  2. 匹配指定域名及端口
    # 只能匹配域名 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
    
  3. 匹配指定协议和域名
    https://ke.qq.com 127.0.0.1:6001
    
    http://ke.qq.com 127.0.0.1:7001
    

路径匹配

路径匹配跟域名匹配差不多,只是多了需要匹配路径片段:

  1. 匹配指定路径的请求
    ke.qq.com/statics file:///User/xxx/test
    
    ke.qq.com/cgi-bin 10.1.1.1:8080
    
  2. 匹配指定路径及端口
    file:///User/xxx/test ke.qq.com:8080/page fudao.qq.com/page/
    
    ke.qq.com:8080/cgi-bin 10.1.1.1
    
  3. 匹配指定协议和域名
    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 获取子匹配的值:

  1. 所有 ke.qq.com/cgi-bin/ 及其子路径 ke.qq.com/cgi-bin/path/to?xxx 的请求忽略所有规则(相当于直接请求现网)
    /^\w+://ke\.qq\.com/cgi-bin\// ignore://*
    
  2. 包含 imweb-test (且忽略大小写)的 URL 请求忽略所有规则
    /imweb-test/i ignore://*
    
  3. 去掉 URL 里面的 md5 后做本替换
    /^\w+://\d\.url\.cn/path/to/(\w+)\.\w+\.\w+/ file:///User/test/xxx/dev/$1.$2
    

通配符匹配

正则表达式涉及转义符及精确匹配,有时写起比较繁琐,为解决这类问题,whistle 提供了通配符匹配解决常用匹配问题:

  1. 精确匹配

    # 只匹配 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
    
    
  2. 通配路径匹配

    # 匹配所有域名下的 /cgi-bin 及其子路径 /cgi-bin/path/to 请求(本地替换会自动补齐后续路径)
    */cgi-bin file:///User/test/
    
  3. 普通通配符匹配(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://*) 等等,大致可分成这几类:

  1. @ 功能
  2. 设置UI样式
  3. 设置hosts
  4. 设代理
  5. 延迟请求
  6. 修改请求URL
  7. 修改请求方法
  8. 修改请求头
  9. 延迟响应
  10. 修改请求内容
  11. 修改响应状态码
  12. 修改响应头
  13. 修改响应内容
  14. 请求替换
  15. 过滤配置
  16. 获取抓包数据
  17. 动态设置规则
  18. 开发调试工具

详细文档参见:wproxy.org/whistle/rul…

opValue

每个具体操作对应一个 opValue,即为一个字符串或对像,opValue 有一下几种写法:

  1. 内联值:

    • 直接内联(不能用空格、换行符等空白字符)
      # 一些支持字符串等规则,可以不用小括号
      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}
      

      用三个及以上等反引号 ` 对 + 键名作为内嵌值的边界

  2. Values

    对一些比较大对值,不适宜直接内嵌到规则里面,可以放在跟 Rules 同级到 Values 里面,用法跟内嵌方式一致。

    image
    image

  3. 文件或目录

    有些内容太大不适合放在 WebUI 里面,或者要本地替换,可以采用文件或目录到方式:

    ke.qq.com/test file:///User/statics resCookies:///User/json/cookies.json
    

    ke.qq.com/test 及其子路径请求会自动到 /Users/statics 通过补齐路径找到对应文件,并会设置 /User/json/cookies.json 里面的 cookies

  4. 模板字符串 方便大家在规则里面获取请求 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、请求头、请求内容,响应状态码,响应头等进行跟灵活精确的匹配,可以采用 filterfilter 包含 includeFilterexcludeFilter 分别用于实现包含及排除匹配规则,一行规则可以用任意多个 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 包含(不区分大小写) javascriptjson,且不能包含 gbk,则会执行 resCors://enableresMerge://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
`

多个 includeFilterexcludeFilter 混合时,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…

除了 filterignore,还可以结合脚本或插件实现更复杂的匹配方式,具体参见:

  1. reqScript:wproxy.org/whistle/rul…
  2. resScript:wproxy.org/whistle/rul…
  3. 插件:wproxy.org/whistle/plu…

命令行操作

  1. w2 add:执行当前目录的 .whistle.js 文件设置项目规则,详细文档参见:wproxy.org/whistle/cli…
  2. w2 i whistle.xxx:安装 whislte 插件(插件也可以用 npm 全局安装)

    也可以指定 registy 安装插件:w2 i whistle.xxx --registry=http://xxx,或直接用内部命令安装如 tnpmw2 ti whistle.xxx

  3. w2 uninstall whistle.xxx:这种卸载方式只支持通过 w2 [x]i whistle.xxx 安装的插件
  4. w2 run xxx:执行通过 w2 i 安装的插件自带命令(不是全局安装,所以不能直接执行)
  5. whistle 还针对一些特殊场景提供了启动参数或命令行参数支持,具体参见:w2 help

插件扩展

whistle 提供了强大且较为完善的操作协议,并支持通过插件定制自己的操作协议,每个插件就是一个 npm 包,不仅拥有 whistle 提供的扩展能力,且具备 node 的所有能力,插件至少可以做以下事情:

  1. 提供UI界面
  2. 作为请求server
  3. 统计请求信息(查看上报/打点数据等)
  4. 设置规则(动态,静态,全局及私有规则)
  5. 获取抓包数据
  6. 编解码请求响应数据流(pipe stream 功能)
  7. 扩展 Network 右键菜单
  8. 同步 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…