HTTP代理原理探索
Web 上的代理服務(wù)器是代表客戶端完成事務(wù)處理的中間人。如果沒有 Web 代理, HTTP 客戶端就要直接與 HTTP 服務(wù)器進(jìn)行對(duì)話。有了 Web 代理,客戶端就可以與代理進(jìn)行對(duì)話,然后由代理代表客戶端與服務(wù)器進(jìn)行交流。客戶端仍然會(huì)完成對(duì)事務(wù)的處理,但它是通過代理服務(wù)器提供的優(yōu)質(zhì)服務(wù)來實(shí)現(xiàn)的。
HTTP 代理存在兩種形式,分別簡(jiǎn)單介紹如下:
- 第一種是 RFC 7230 - HTTP/1.1: Message Syntax and Routing(即修訂后的 RFC 2616,HTTP/1.1 協(xié)議的第一部分)描述的普通代理。這種代理扮演的是「中間人」角色,對(duì)于連接到它的客戶端來說,它是服務(wù)端;對(duì)于要連接的服務(wù)端來說,它是客戶端。它就負(fù)責(zé)在兩端之間來回傳送 HTTP 報(bào)文。
- 第二種是 Tunneling TCP based protocols through Web proxy servers(通過 Web 代理服務(wù)器用隧道方式傳輸基于 TCP 的協(xié)議)描述的隧道代理。它通過 HTTP 協(xié)議正文部分(Body)完成通訊,以 HTTP 的方式實(shí)現(xiàn)任意基于 TCP 的應(yīng)用層協(xié)議代理。這種代理使用 HTTP 的 CONNECT 方法建立連接,但 CONNECT 最開始并不是 RFC 2616 - HTTP/1.1 的一部分,直到 2014 年發(fā)布的 HTTP/1.1 修訂版中,才增加了對(duì) CONNECT 及隧道代理的描述,詳見 RFC 7231 - HTTP/1.1: Semantics and Content。實(shí)際上這種代理早就被廣泛實(shí)現(xiàn)。
普通代理
HTTP 客戶端向代理發(fā)送請(qǐng)求報(bào)文,代理服務(wù)器需要正確地處理請(qǐng)求和連接(例如正確處理 Connection: keep-alive),同時(shí)向服務(wù)器發(fā)送請(qǐng)求,并將收到的響應(yīng)轉(zhuǎn)發(fā)給客戶端。
實(shí)驗(yàn)驗(yàn)證
網(wǎng)絡(luò)連接: Tencent-DevWiFi
代理設(shè)置: dev-proxy.oa.com:8080
訪問站點(diǎn): http://www.cnbeta.com/
Wireshark抓包分析:
隧道代理
HTTP 客戶端通過 CONNECT 方法請(qǐng)求隧道代理創(chuàng)建一條到達(dá)任意目的服務(wù)器和端口的 TCP 連接,并對(duì)客戶端和服務(wù)器之間的后繼數(shù)據(jù)進(jìn)行盲轉(zhuǎn)發(fā)。
實(shí)驗(yàn)驗(yàn)證 I
網(wǎng)絡(luò)連接: Tencent-DevWiFi
代理設(shè)置: dev-proxy.oa.com:8080
訪問站點(diǎn): https://www.baidu.com/
Wireshark抓包分析:
可以看到,瀏覽器與代理進(jìn)行 TCP 握手之后,發(fā)起了 CONNECT 請(qǐng)求,報(bào)文起始行如下:
CONNECT www.baidu.com:443 HTTP/1.1
代理收到這樣的請(qǐng)求后,需要與服務(wù)端建立 TCP 連接,并響應(yīng)給瀏覽器這樣一個(gè) HTTP 報(bào)文:
HTTP/1.1 200 Connection established
瀏覽器收到了這個(gè)響應(yīng)報(bào)文,就可以認(rèn)為到服務(wù)端的 TCP 連接已經(jīng)打通,后續(xù)直接往這個(gè) TCP 連接寫協(xié)議數(shù)據(jù)即可。
實(shí)驗(yàn)驗(yàn)證 II
[tcp_echo_server]
網(wǎng)絡(luò)連接:騰訊云主機(jī)(外網(wǎng): 139.199.76.147 內(nèi)網(wǎng): 10.186.8.226)
[tcp_echo_client]
網(wǎng)絡(luò)連接: Tencent-DevWiFi
代理設(shè)置: dev-proxy.oa.com:8080
Wireshark抓包分析:
附源碼如下:
# tcp_echo_server.pyimport sys, sockethost = sys.argv[1] port = int(sys.argv[2])sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((host, port)) sock.listen(1)while True:connection, client_address = sock.accept()try:print >>sys.stderr, 'connection from', client_addresswhile True:data = connection.recv(16)print >>sys.stderr, 'received "%s"' % dataif data:print >>sys.stderr, 'sending data back to the client'connection.sendall(data)else:print >>sys.stderr, 'no more data from', client_addressbreakfinally:connection.close() # tcp_echo_client.pyimport sys, socket, sockshost = sys.argv[1] port = int(sys.argv[2])sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM) sock.set_proxy(socks.HTTP, "dev-proxy.oa.com", 8080)sock.connect((host, port))try:message = 'This is the message. It will be repeated.'print >>sys.stderr, 'sending "%s"' % messagesock.sendall(message)amount_received = 0amount_expected = len(message)while amount_received < amount_expected:data = sock.recv(16)amount_received += len(data)print >>sys.stderr, 'received "%s"' % datafinally:print >>sys.stderr, 'closing socket'sock.close()總結(jié)
以上是生活随笔為你收集整理的HTTP代理原理探索的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 部署项目的问题(二)—— 阿里云服务器
- 下一篇: 部署项目的问题(三)—— node启动服