whistle 是一款用 Node 實現的跨平臺的 Web 除錯代理工具,支援檢視修改 http(s)、Websocket 連線的請求和響應內容。簡而言之就是 Node 版的 Fiddler、Charles,不過這個工具能遠比後兩者更加適合 Web 開發者、使用更簡單、功能也更加實用,而筆者使用了 1 個月後發現完全可以代替 Fiddler、Charles。
安裝&執行
whistle 執行時會監聽一個埠,把 Chrome(或其他程式)轉發到該埠的資料處理後再返回,而在 Chrome 裡則通過一個代理層把請求轉發到相應埠。
- Chrome 外掛:whistle for Chrome
- Node 端的 CI 工具
1234# 安裝sudo npm i -g whistle# 執行w2 start
詳見:安裝方法
最後,開啟 http://local.whistlejs.com/#network 即可進入控制檯介面
常用功能一覽
- 繫結host
12# 說明:相當於瀏覽器層的host檔案,如果找不到再去查詢本機的host檔案192.168.0.1 mydomain.com - 替換請求
12# 說明:請求百度的時候會返回京東的頁面內容https://m.baidu.com https://wq.jd.com/ - 修改返回碼
12# 說明:使 http 返回 404https://m.baidu.com statusCode://404 - 往 html 插入指令碼
123# 說明:會在網頁最後以 script 標籤的形式插入,花括號的值是內建編輯器儲存的檔案,在主選單 “Value” 下可找到https://wq.jd.com js://{test.js}https://wq.jd.com js:///Users/myname/test/test.js - 往 html 插入樣式
12# 說明:在網頁裡以 style 標籤的形式插入https://wq.jd.com css://{test.css} - 文字類請求 append 內容、替換返回內容
1234# 說明:會把內容 append 到請求後面http://mydomain.com/style.css resAppend://{myAppend.css}# 說明:完全替換請求內容http://mydomain.com/style.css resBody://{myResBody.css} - weinre 除錯頁面
12# 說明:為 https://wq.jd.com 頁面快速新增一個 weinre 除錯指令碼,點選 http://local.whistlejs.com/weinre/client/#debug_mypage 或介面主選單 “Weinre” 可開啟 inspect 介面除錯該頁面https://wq.jd.com weinre://debug_mypage
更多的使用方法可以參考 whistle 協議列表
小結
從上面可以看出 whistle 的大致工作流程:
- 配置需要修改的 url 地址
- 編寫 URI 協議,如 statusCode://
- 編寫協議對應的引數,如 statusCode://404
可以看出 whistle 的操作都是通過文字配置去實現,比較符合程式設計師的思維。
whistle 可操作的資源的 request 、respond 的 header、 body, 其中 header 裡面的 query 、ua 、 cookie、status Code 等資料對前端來說非常熟悉, 也都有相應的協議去操作這些資料。
另外, whistle 很多操作協議都是針對前端開發友好的,比如 html、 js 、css 等型別的請求的修改協議對於前端程式猿來說都非常親切。
使用建議
1. 代替本地的 host 檔案
由於 whistle 相容作業系統的 host 語法格式,所以在瀏覽器層面的 host 配置可輕鬆代替本地的 host 檔案。這樣做的主要好處是無快取,切換時生效更快。
有一個技巧就是在 “Rules” 介面下,可配多套 host 配置,比如 dev、gamma 等滿足開發需求。
2. 多終端代理
- 手機的 wifi 設定裡,開啟代理,連線本機 ip 和 8899 埠即可檢視手機的網頁請求
- 電腦其餘程式的代理設定,也可通過本機 ip 和 8899 埠的形式使用 whistle 檢視請求,比如微信 web 開發者工具
注意以上操作均需要在同一個區域網內
3. 轉換 http 協議
轉發協議+域名轉發,輕鬆本地模擬 https ,訪問線上的 https 域名實際上指向的是本地的 http 除錯地址。
1 |
https://wq.jd.com http://localhost:9000 |
注意,涉及到 https 的請求都需要您的電腦和手機等都安裝 whistle 提供的證照,詳情可看文件。
4. mock 資料
whistle 提供了一個強大的 mock 資料的外掛,強大之處是可以結合 js 語句 + mock 語法去生成資料。舉一個簡單的例子說明用法:
先安裝外掛:
1 |
npm i -g whistle.vase |
在 “Plugins” 選單開啟 vase 的介面,新建一個名字為 “mock_json_demo” 的配置,並選擇模板為 mock 。輸入如下內容:
1 2 3 4 5 6 7 |
{ "list|5": [{ "name": "@string", "avatar": "http://lorempixel.com/100/100/", "id|+1": 10000 }] } |
不熟悉 mock 語法的朋友可以到這裡瞭解一下
在 “Rules” 下配置一條 vase 的規則:
1 |
http://mock.local/data.json vase://mock_json_demo |
開啟測試地址 http://mock.local/data.json ,即可看到模擬的資料。
有讀者可能會問,如果想更自由度更高一點,用 js 去生成資料是否可行?
當然可行,vase 提供了一種 “script” 模板可實現這種需求,裡面可以寫一些簡單的 javascript API,還提供了 req(request)等內建資料物件,可以獲取如請求的 headers、method、body、query、url 等資料。
既然這些資料都有了,是不是可以搞事情了?我有一個大膽的想法,請看下面的例子:
在 vase 介面新建一個名為 “json_engine_script” 資料模板,並選擇 “script” 模板引擎。
1 2 3 4 5 6 7 8 9 10 11 12 |
var json = merge({ page: req.query.pi, // 取url查詢引數的分頁欄位,加到要返回的資料裡,達到模擬分頁資料的效果 total: 60 }, render('mock_json_demo', null, 'mock')); // render 可以渲染上文提到名為“mock_json_demo”的資料模板,返回一個json if (req.query.callback) { // 如果查詢引數帶了callback,則返回jsonp out(header('content-type', 'application/javascript; charset=utf8')); var json_text = join([req.query.callback+'(', json, ')']); // join是內建方法,可合併一組資料 out(json_text); // 向body輸出資料 } else { // 沒有callback則返回json out(header('content-type', 'application/json; charset=utf8')); out(json); } |
在 “Rules” 輸入以下配置:
1 2 3 |
http://mock.local/data.json vase://json_engine_script # 註釋掉上一條配置 # http://mock.local/data.json vase://mock_json_demo |
開啟 http://mock.local/data.json?callback=cb&pi=1 ,可嘗試改變、刪除 callback、pi 引數,會發現返回的資料會隨之改變。
至此就完成了一個簡單的、有一定擴充套件性的 restful 資料介面模擬。
5. mock & more
在現有的開發工作流裡,在需求開發完畢進入測試後,相信有不少團隊都是需要測試人員單獨模擬資料去測試頁面功能。所以在開發階段的 mock 資料、whistle rules 是不是可以直接共享給測試去使用了呢?因為純文字配置的資料共享起來畢竟比較方便。
如果專案迭代比較快,覺得共享多份 mock 配置資料不方便,是否可以單獨搞個 mock server(市面上已有類似服務比如 easy mock,我們團隊也有一個好用的文件管理 & mock server),whistle 只進行請求轉發,而開發與測試人員只需要共享 whistle rules 即可?
結語
總體來說 whistle 的玩法還是蠻多的,入門也比較簡單,不過也是依然缺少一些功能,比如除錯 websocket、圖片 等的能力,也缺少一些賬戶系統 & 共享配置的能力,希望作者以後能夠考慮完善一下這些功能吧,使這個工具更加好玩。
參考資料:
whistle 文件 https://avwo.github.io/whistle/