002. HTTP 代理原理及 Python 簡(jiǎn)單實(shí)現(xiàn)
HTTP 代理是一種網(wǎng)絡(luò)代理服務(wù)器(Proxy Server),它能夠作為客戶(hù)端與 HTTP 服務(wù)器之間的中介,它的工作原理是:
當(dāng)客戶(hù)端向 HTTP 代理發(fā)送 HTTP 請(qǐng)求時(shí),HTTP 代理會(huì)收到請(qǐng)求。
HTTP 代理會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給目標(biāo) HTTP 服務(wù)器。
目標(biāo) HTTP 服務(wù)器處理請(qǐng)求并生成響應(yīng)。
HTTP 代理將響應(yīng)轉(zhuǎn)發(fā)給客戶(hù)端。
通過(guò)使用 HTTP 代理,客戶(hù)端可以訪問(wèn)其他服務(wù)器的資源,而不需要直接連接其他服務(wù)器。這樣,客戶(hù)端的真實(shí)地址就被隱藏起來(lái),HTTP 代理也可以提供額外的功能,如緩存網(wǎng)頁(yè)內(nèi)容、過(guò)濾內(nèi)容、保護(hù)隱私等。
HTTP 代理存在兩種形式,分別簡(jiǎn)單介紹如下:
第一種是普通代理,它是最常見(jiàn)的代理服務(wù)器,能夠代理 HTTP?協(xié)議的網(wǎng)絡(luò)流量。這種代理僅扮演「中間人」角色,對(duì)于連接到它的客戶(hù)端來(lái)說(shuō),它是服務(wù)端;對(duì)于要連接的服務(wù)端來(lái)說(shuō),它是客戶(hù)端。它就負(fù)責(zé)在兩端之間來(lái)回傳送 HTTP 報(bào)文,由于 HTTPS 包經(jīng)過(guò)加密,沒(méi)法解析,所以也就沒(méi)法代理 HTTPS 的請(qǐng)求。
第二種是隧道代理,它能夠?qū)⒖蛻?hù)端的請(qǐng)求和響應(yīng)封裝成隧道(Tunnel),并將隧道傳輸?shù)侥繕?biāo)服務(wù)器。隧道代理能夠代理任意基于 TCP 的應(yīng)用層協(xié)議的網(wǎng)絡(luò)流量,包括?HTTP?和 HTTPS 協(xié)議。
普通代理
第二種 Web 代理原理特別簡(jiǎn)單:
HTTP 客戶(hù)端向代理發(fā)送請(qǐng)求報(bào)文,代理服務(wù)器需要正確地處理請(qǐng)求和連接(例如正確處理 Connection: keep-alive),同時(shí)向服務(wù)器發(fā)送請(qǐng)求,并將收到的響應(yīng)轉(zhuǎn)發(fā)給客戶(hù)端。
利用 Python 的 Flask + requests 搭建代理服務(wù)器的基本流程如下:
安裝 Flask 和 requests 庫(kù)。
編寫(xiě) Flask 應(yīng)用,定義一個(gè)路由來(lái)處理客戶(hù)端的請(qǐng)求。
使用 requests 庫(kù)發(fā)送請(qǐng)求給目標(biāo)服務(wù)器,獲取響應(yīng)。
將響應(yīng)返回給客戶(hù)端。
示例代碼如下:
這樣就實(shí)現(xiàn)了?HTTP 協(xié)議的代理?。
隧道代理
第二種 Web 代理的原理也很簡(jiǎn)單:
HTTP 客戶(hù)端通過(guò) CONNECT 方法請(qǐng)求隧道代理創(chuàng)建一條到達(dá)任意目的服務(wù)器和端口的 TCP 連接,并對(duì)客戶(hù)端和服務(wù)器之間的后繼數(shù)據(jù)進(jìn)行盲轉(zhuǎn)發(fā)。
懶得寫(xiě)那么多了,直接上代碼:
上述代碼實(shí)現(xiàn)了一個(gè)?HTTP?隧道代理服務(wù)器。它使用 Python 的 http.server?模塊來(lái)創(chuàng)建 HTTP 服務(wù)器,并使用 socket 庫(kù)來(lái)處理底層的網(wǎng)絡(luò)通信。
首先,通過(guò)調(diào)用 HTTPServer 類(lèi)的構(gòu)造函數(shù),創(chuàng)建了一個(gè) HTTP 服務(wù)器對(duì)象,監(jiān)聽(tīng) 5000 端口,并重寫(xiě)了請(qǐng)求處理程序 。
然后,定義了一個(gè) ProxyHandler 類(lèi),繼承了 BaseHTTPRequestHandler 類(lèi)。ProxyHandler 類(lèi)中可以定義一些方法,用于處理不同的 HTTP 方法,如 GET、POST、PUT 等。
其中,do_CONNECT?方法用于處理客戶(hù)端的 CONNECT 請(qǐng)求,即建立隧道。當(dāng)客戶(hù)端發(fā)送 CONNECT 請(qǐng)求時(shí),服務(wù)器會(huì)調(diào)用這個(gè)方法,并解析出客戶(hù)端要連接的目標(biāo)服務(wù)器的地址和端口。然后,服務(wù)器使用 socket 庫(kù)連接到目標(biāo)服務(wù)器,并告訴客戶(hù)端連接成功(Connection Established)。最后,服務(wù)器調(diào)用 handle_tcp?方法來(lái)轉(zhuǎn)發(fā)客戶(hù)端 socket 和目標(biāo)服務(wù)器 socket 之間的數(shù)據(jù)流。
由于未定義 do_GET?方法,HTTP 協(xié)議暫時(shí)不可用。
延伸閱讀
HTTP 代理原理及實(shí)現(xiàn):https://juejin.cn/post/6998351770871152653
CONNECT - HTTP | MDN:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/CONNECT
HTTP 協(xié)議之 CONNECT 方法:https://blog.csdn.net/qq_23401185/article/details/124528286
由淺入深寫(xiě)代理(7)-https-代理:https://zhuanlan.zhihu.com/p/28767664