HTTP CONNECT 方法
阿新 • • 發佈:2019-01-24
HTTP request有常用的5種方法:
HTTP request 方法 | 描述 |
---|---|
GET | 從指定的資源請求資料 |
POST | 向指定的資源提交要被處理的資料 |
PUT | 上傳指定的 URI 表示 |
DELETE | 移除指定的資源 |
HEAD | 與 GET 方法相同,但只返回 HTTP 報頭,不返回文件主體 |
但從HTTP 1.1以來,有一種新的方法無詳細說明,卻被廣泛使用,這就是CONNECT。
它並非使用在網頁開發方面,而是在閘道器這個看似透明的地方。
借用HTTP權威指南中的圖:
如上圖所示,它的原理也很簡單:
通常由客戶端發起到閘道器,閘道器接受後建立對目標伺服器的連線,成功後告知客戶端。
然後客戶端就可以傳送任意資料到目標伺服器了。
這裡我借用一個proxy的程式碼來說明一下CONNECT方法的實現:
import BaseHTTPServer, select, socket, SocketServer, urlparse class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler): def _connect_to(self, netloc, soc): i = netloc.find(':') if i >= 0: host_port = netloc[:i], int(netloc[i+1:]) else: host_port = netloc, 80 print "\t" "connect to %s:%d" % host_port try: soc.connect(host_port) except socket.error, arg: try: msg = arg[1] except: msg = arg self.send_error(404, msg) return 0 return 1 def do_CONNECT(self): print "In do_CONNECT, self.path: %s" % self.path soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: if self._connect_to(self.path, soc): self.log_request(200) self.wfile.write(self.protocol_version + " 200 Connection established\r\n") self.wfile.write("Proxy-agent: %s\r\n" % self.version_string()) self.wfile.write("\r\n") self._read_write(soc, 300) finally: print "\t" "bye" soc.close() self.connection.close() def _read_write(self, soc, max_idling=20): iw = [self.connection, soc] ow = [] count = 0 while 1: count += 1 (ins, _, exs) = select.select(iw, ow, iw, 3) if exs: break if ins: for i in ins: if i is soc: out = self.connection else: out = soc data = i.recv(8192) if data: out.send(data) count = 0 else: print "\t" "idle", count if count == max_idling: break
這裡省略了一些其他部分的程式碼,比如正常的HTTP方法的處理函式。
通過BaseHTTPServer的處理,程式執行的時候在收到HTTP CONNECT方法後呼叫do_CONNECT()函式。
do_CONNECT()中呼叫_connect_to()函式建立對目標地址的socket連線,成功後通過self.wfile.write()向客戶端返回建立成功的資訊,然後通過_read_write()方法來實現資料的通訊。
值得說明的是,一個proxy server收到的path並非普通Server收到的URL path資訊,而是帶有URL scheme,URL host的完整URL資訊。所以在_connect_to()函式中會通過判斷冒號的位置來解析URL host和URL port資訊。