利用whistle調試websocket和socket請求

whistle v1.6.0 (Github地址:github.com/avwo/whistl…) 開始支持WebSocket和通常Socket的抓包、構造請求、以及修改發送或接收的數據。git

請求抓包

打開whistle的Network,選中左側請求列表中的WebSocket(Socket)請求,點擊右側的 Response -> Framesgithub

WebSocket抓包:web

WebSocket

Socket(TCP)請求,須要通過Tunnel代理鏈接whistle,再經過whistle轉發,未避免whistle把普通Socket請求當成https或websocket請求,須要代理請求頭添加個字段 x-whistle-policy: tunnel,下面以Node爲例說明如何經過whistle轉發Socket(TCP)請求(其它語言同理:先發一個http請求給whistle代理把請求信息帶給whistle,whistle請求目標服務器成功後把鏈接返回):npm

模擬後臺Socket Server代碼:服務器

const net = require('net');

const server = net.createServer();
server.on('connection', (client) => {
  client.on('error', () => {});
  client.on('data', (data) => {
    client.write(`Response: ${data}`);
  })
});
server.listen(9999);
複製代碼

客戶端代碼:websocket

const http = require('http');
const net = require('net');

// whistle監聽端口,根據實際狀況設定
const PROXY_PORT = 8899;
// whistle所在服務器IP
const PROXY_HOST = '127.0.0.1';
// 鏈接whistle代理
const connect = (options) => {
  options = {
    method: 'CONNECT',
    host: PROXY_HOST,
    port: PROXY_PORT,
    path: `${options.host}:${options.port}`,
    agent: false,
    headers: {
      'x-whistle-policy': 'tunnel', // 必填,不然沒法查看抓包數據
    }
  };
  return new Promise((resolve, reject) => {
    const client = http.request(options);
    client.once('connect', (req, socket) => resolve(socket));
    client.once('error', reject);
    client.end();
  });
};

const init = async () => {
  const options = { host: '127.0.0.1', port: 9999 };
  const socket = await connect(options);
  let index = 0;
  const send = () => {
    ++index;
    socket.write(`${index}. This is a JSON Object: {"test": "index=${index}"}`);
  };
  socket.on('data', (data) => {
    setTimeout(send, 3000);
  });
  send();
};

init().catch(err => {
  throw err;
});
複製代碼

Socket

構造請求

在Network的右側Composer能夠構造各類請求,包括http、https、WebSocket、Socket請求,能夠直接填寫要請求的url、方法、請求頭、請求內容等,也能夠直接從左側列表把對應的數據拖過來。併發

以WebSocket Demo網站爲例(demos.kaazing.com/echo/),創建以下鏈接,併發送數據(用Composer構造的WebSocket在Frames下面會出現一個Composer選項,用於向Server發送數據,也能夠經過直接上傳文件發送):socket

GET /echo HTTP/1.1
WebSocket-Protocol: 
Sec-WebSocket-Protocol: 
Sec-WebSocket-Extensions: x-kaazing-idle-timeout,x-kaazing-ping-pong,x-kaazing-http-revalidate

1
複製代碼

後面經過Frames裏面的Composer發送什麼數據後臺就返回什麼:async

Build WebSocket

通常Socket請求只需把請求方法改成 CONNECT,或者用這些協議的url conn://connect://socket://、、tunnel://工具

Build Socket

修改數據

從上面的插圖能夠發現,若是請求不是經過whistle的Composer發送的,WebSocket和Socket請求都沒法添加或修改接收及發送數據(Composer創建的鏈接能夠發送數據到服務端),要修改WebSocket或Socket的發送或接收數據,須要藉助whistle的插件whistle.script,其原理是經過配置whistle規則把請求轉發到whistle.script裏面的WebSocket或Socket服務器,再經過whistle.script攔截或發送到指定後臺。

安裝whistle.script

npm i -g whistle.script
# 或
npm i -g whistle.script --registry=https://registry.npm.taobao.org
複製代碼

調試WebSocket請求,打開插件script的界面local.whistlejs.com/whistle.scr…,新建名爲handleWebSocket的script:

exports.handleWebSocket  = async (ws, connect) => {
  	// 將請求繼續轉發到目標後臺,若是不加則直接響應
    const res = await connect();
  	// 獲取客戶端的請求數據
    ws.on('message', (data) => {
      // 在script的Console打印出客戶端發送的數據
      console.log(`Client: ${data}`);
       // 能夠修改後再發送到Server
       res.send(data);
    });
  	res.on('message', (data) => {
    	// 在script的Console打印出服務端發送的數據
        console.log(`Server: ${data}`);
         // 能夠修改後再發送到Server
         ws.send(data);
    });
	// 接收經過whistle.script頁面Console的dataSource.emit('toSocketClient', {name: 'toSocketClient'})的數據
    ws.dataSource.on('toSocketClient', (data) => {
      ws.send(data);
    });
   // 接收經過whistle.script頁面Console的dataSource.emit('toSocketServer', {name: 'toSocketClient'})的數據
  	ws.dataSource.on('toSocketServer', (data) => {
      res.send(data);
    });
};
複製代碼

在whistle上配置規則:

ws://demos.kaazing.com/echo script://handleWebSocket
複製代碼

打開demos.kaazing.com/echo/,點擊 Connect 按鈕:

Handle WebSocket

調試Socket請求,同上操做在whistle.script插件上新建一個名爲 handleSocket 的腳本:

exports.handleTunnel  = async (client, next) => {
  	// 將請求繼續轉發到目標後臺,若是不加則直接響應
 	const res = await next();
  	// 獲取客戶端的請求數據
    client.on('data', (data) => {
      // 在script的Console打印出客戶端發送的數據
      console.log(`Client: ${data}`);
       // 修改後再發送到Server
       res.write(`Client>>>Server: ${data}+client`);
    });
  	res.on('data', (data) => {
    	// 在script的Console打印出服務端發送的數據
        console.log(`Server: ${data}`);
         // 修改後再發送到Server
         client.write(`Server>>>Client: ${data}`);
    });
	// 接收經過whistle.script頁面Console的dataSource.emit('toSocketClient', {name: 'toSocketClient'})的數據
    client.dataSource.on('toSocketClient', (data) => {
      client.write(JSON.stringify(data));
    });
   // 接收經過whistle.script頁面Console的dataSource.emit('toSocketServer', {name: 'toSocketClient'})的數據
  	client.dataSource.on('toSocketServer', (data) => {
      res.write(JSON.stringify(data));
    });
};
複製代碼

在whistle上配置規則:

127.0.0.1:9999 script://handleSocket
複製代碼

啓動文章剛開始的Socket鏈接的例子,打開whistle.script界面的Console,在裏面分別執行下面兩個語句:

dataSource.emit('toSocketClient', 'Mock Server');
dataSource.emit('toSocketServer', 'Mock Client');
複製代碼

whistle.script會把對應的事件名稱及參數值傳給後臺 ctx.dataSource 的對應監聽方法。

Handle Socket

相關文章

  1. whistle工具全程入門
  2. 利用whistle調試移動端頁面
  3. Github地址
相關文章
相關標籤/搜索