Fiddler助力微信開發調試

Fiddler是一個很是強大的代理工具,可讓你的前端開發調試更加方便。下面介紹在微信開發調試方面的應用。css

微信網頁開發中,因爲有js接口安全域名和受權域名等的限制,致使部分功能須要部署到線上才能測試。經過代理能夠實現本地調試網站的全部功能。html

配置代理規則

全站轉發能夠這樣設置:Tools -> HOSTS 前端

圖片中表示your.domain.com的請求所有轉發到127.0.0.1:8000。第二個參數的限制是:不能加協議、路徑或參數。node

若是你的網站域名和接口域名是同一個,那就不能使用全站轉發了,須要html、css、js、websocket請求轉發到本地,接口調用請求則直接發送到遠程服務器。web

可使用自定義規則實現 正則表達式

上面圖片中的正則表達式和目標地址以下:小程序

regex:^http://your.domain.com(?!/api|/swagger|/webjars|/configuration/ui)(.*)


http://localhost:8000$1

本條規則表示:將your.domain.com下的http請求轉發到localhost:8000,其中/api/swagger/webjarsconfiguration/ui開頭的路徑不轉發。windows

目標地址表達式中的$1表明原始請求URL域名後面的字符串,包括pathsearch後端

設置代理服務器

打開微信開發者工具,設置 -> 代理設置 -> 選擇手動設置代理 Fiddler默認運行在127.0.0.1:8888微信小程序

在真機上測試

在真機上測試本地微信網頁項目的步驟以下:

  1. 手機和電腦鏈接同一個局域網。

  2. 設置Fiddler容許遠程鏈接,Tools -> Options -> Connections -> 勾選Allow remote computers to connect

  1. 查看電腦在局域網中的IP地址,命令行輸入ipconfig(windows)。

  1. 手機網絡配置代理服務器。

到這裏,本篇文章的主要內容就結束了,若是你想了解更多關於Fiddler和代理工具的使用,能夠參考我同事的文章代理工具Fiddler -調試與替換接口狀態 代理工具作微信項目的調試配置 若是你想了解使用nodejs如何實現上述以及更多自定義的功能,敬請往下閱讀。

nodejs實現代理服務器

下文中,client表示客戶端(瀏覽器),proxy表示代理服務器,server表示目標服務器

HTTP

實現HTTP代理服務器是很是簡單的,由於HTTP爲明文傳輸,因此proxy只須要解析client的HTTP報文,再向server發送相同的請求,server響應時,proxy將HTTP響應狀態,響應首部字段和響應主體返回給client便可。

這裏可使用nodejs的http模塊實現

const http = require('http');
const { URL } = require('url');

let server = http.createServer((req, res) => {
 let {
   pathname,
   search,
   hostname,
   port
} = new URL(req.url);

 console.log('http ', req.url);

 // 後端api調用請求直接發送給遠程服務器,除此以外的HTTP請求發送給本地運行的端口
 if (!pathname.startsWith('/api')) {
   hostname = 'localhost';
   port = 8000; // 項目運行的端口
}

 req.pipe(http.request({
   hostname,
   port,
   path: `${pathname}${search}`,
   method: req.method,
   headers: req.headers
}, (response) => {
   res.writeHead(response.statusCode, response.statusMessage, response.headers);
   response.pipe(res);
}));
});

server.listen(8888);

HTTPS

只有HTTP代理服務器是不夠的,由於不論是微信開發工具,仍是瀏覽器,都有可能發送HTTPS請求。好比微信開發者工具的登陸和域名校驗就是使用的HTTPS與微信服務器通訊的,若是不代理這部分流量是沒法正常運行微信開發者工具的。

HTTPS由於報文加密的緣由,proxy不能解析報文後假裝client發送請求。最多見的解決方案是web隧道,proxy創建和client、server的TCP鏈接,以後盲轉發兩端的數據。

創建web隧道的方式之一是使用HTTP的CONNECT方法,實際上客戶端(瀏覽器)設置了代理服務器後,client發出的HTTPS請求是不一樣的,它首先會使用CONNECT方法發送HTTP請求,請求proxy創建鏈接,這是proxy能代理HTTPS的關鍵。

client請求proxy與server創建TCP鏈接的HTTP報文以下:

CONNECT your.domain:443 HTTP/1.1
Host: your.domain:443
Connection: keep-alive
User-Agent: M....

proxy在與server創建TCP鏈接後,按照約定,須要200 Connection Established響應,響應首部字段可自定義:

HTTP/1.1 200 Connection Established
Connection: close

因此http服務器就能夠代理https請求。實際上,按照上面的原理http服務器可以代理不少其餘協議的流量。

https代理服務器須要使用http和net模塊,對上面的http代理的代碼擴展便可

server.on('connect', (req, clientSocket) => {
 let {
   port,
   hostname
} = new URL(`http://${req.url}`);

 console.log('https', req.url);

 let serverSocket = net.connect(port || 80, hostname, () => {
   clientSocket.write(
     `HTTP/1.1 200 Connection Established
Connection: close

`
  );

   clientSocket.pipe(serverSocket);
   serverSocket.pipe(clientSocket);
});
});

從實現方式能夠看出來,這種代理服務器是沒法正常獲取和更改通訊雙方的數據的。若是要實現能監聽和更改通訊數據的HTTPS代理服務器,可使用自簽名證書實現,這裏不作探究。

websocket

本地開發的項目每每有熱更新功能,而熱更新的通訊依靠websocket,因此websocket代理也是必不可少的。websocket的鏈接也是用HTTP創建起來的。 若是根據咱們以前瞭解的websocket知識,client會向服務器發送協議升級請求(請求報文中包含特殊的請求首部字段),服務器響應101 Switching Protocols,以後的數據則轉爲websocket協議發送。根據以上流程,一樣只須要對http服務器代碼擴充便可,咱們很容易寫出以下代碼:

server.on('upgrade', (req, clientSocket) => {
 let {
   pathname,
   search,
   hostname,
   port
} = new URL(req.url);

 console.log('websocket', req.url);

 let request = http.request({
   pathname: 'localhost',
   port: 8000, // 項目運行的端口
   method: req.method,
   headers: req.headers
});

 req.pipe(request);

 request.on('upgrade', (response, serverSocket) => {
   let resStr = 'HTTP/1.1 101 Switching Protocols\r\n';

   for (let [key, value] of Object.entries(response.headers)) {
     resStr += `${key}: ${value}\r\n`;
  }

   resStr += '\r\n';

   clientSocket.write(resStr);
   clientSocket.pipe(serverSocket);
   serverSocket.pipe(clientSocket);
});
});

server.listen(8888)

上面的寫法其實是反向代理服務器的寫法。即,瀏覽器直接創建到ws://localhost:8888的請求,該代理服務器是可以將請求轉發到8000端口的,但當瀏覽器設置了代理服務器後,發送websocket請求和沒設置前是不一樣的,它一樣會先向proxy請求創建鏈接,因此代理websocket請求和代理https請求代碼是同樣的,咱們在connect事件中作好區分便可。

server.on('connect', (req, clientSocket) => {
 let {
   port,
   hostname
} = new URL(`http://${req.url}`);

 console.log('https', req.url);

 // websocket請求發送到本地8000端口
 if (req.url === 'your.domain.com:80') {
   port = 8000; // 項目運行的端口
   hostname = 'localhost';
}

 let serverSocket = net.connect(port || 80, hostname, () => {
   clientSocket.write(
     `HTTP/1.1 200 Connection Established
Connection: close

`
  );

   console.log(req.url, 'connect');

   clientSocket.pipe(serverSocket);
   serverSocket.pipe(clientSocket);
});
});

通過以上三步,一個帶有完整功能的代理服務器就寫好了,想要實現自定義功能,無非是在請求報文識別和server響應報文篡改上作文章,盡情發揮你的創造力吧。

 

做者簡介:葉茂,蘆葦科技web前端開發工程師,表明做品:口紅挑戰網紅小遊戲、服務端渲染官網、微信小程序粒子系統。擅長網站建設、公衆號開發、微信小程序開發、小遊戲、公衆號開發,專一於前端領域框架、交互設計、圖像繪製、數據分析等研究。 一塊兒並肩做戰: yemao@talkmoney.cn 訪問 www.talkmoney.cn 瞭解更多

相關文章
相關標籤/搜索