代碼閱讀 - BaseHTTPServer.py

1.        BaseHTTPServer.py<?XML:NAMESPACE PREFIX = O />

平平無奇,看過SocketServer之後,只要瞭解HTTP協議就能看明白。

HTTPServer 繼承自 SocketServer.TCPServer

BaseHTTPRequestHandler 繼承自 SocketServer.StreamRequestHandler

1.1     HTTPServer

HTTP協議本身就是在TCP之上建立的應用層協議,所以不需要做太多的工作。這裏的事項方法是將協議的解析等工作放到Handler類中,在Server類中僅僅覆蓋了server_bind函數:

1.         首先調用TCPServer.server_bind

2.         然後通過 socket. socket.getsockname socket.getfqdn得到完整的主機名和端口。

1.2     HTTP協議回顧

HTTP請求數據流中的三個部分:

1.         第一行表示請求的類型路徑,格式爲 <command> <path> [<version>]

2.         可選的HEADERSHEADER之間用CRLFLF分割;

3.         可選的數據部分;數據和HEADER之間由一個空行分割。

HTTP相應數據流中的三個部分:

1.         第一行表示響應代碼,格式爲 <version> <response_code> [<responsestring>]

2.         可選的HEADERS

3.         數據部分;和HEADER之間由一個空行分割。

1.3     BaseHTTPRequestHandler

SocketServer.BaseRequestHandler的構造函數中,調用了三個方法:setup, handle, finish。其中handler用來處理請求,而且被實現爲空函數。

SocketServer.StreamRequestHandler中,並沒有對handle進行覆蓋,而是覆蓋setupsocket構造爲輸入和輸出文件 rfile wfile

所以在BaseHTTPRequestHandler中,只需要覆蓋handle,對客戶端的請求進行處理。

1.3.1              handle方法

self.close_connection = 1

self.handle_one_request()

     while not self.close_connection:

         self.handle_one_request()

這裏的關鍵是close_connection。主要是爲了區分http request header中的 keep-alive

1.3.2              handle_one_request方法

rfile中讀出一行;這一行就是command + path行;

如果讀取成功,調用parse_request解析客戶端的請求;將請求的操作保存在self.command;判斷類是否具有do_command(如do_POST)方法,如果沒有,發送501錯誤;如果有則使用getattr魔法得到方法並調用。

1.3.3              parse_request方法

解析從rfile中得到的那個command + path,沒什麼難度。

需要注意的是如果解析成功的話,會調用mimetools.Message的構造函數,生成一個類實例。這個構造函數需要rfile作爲參數。構造過程其實也就是HEADERS的解析過程。

要具體研究一下這個類。

1.3.4              其他方法

send_response,用來發送HTTP響應的第一行;

send_header,發送一個HEADER

end_headers,發送一個空白行;

以及log函數和其它輔助函數。

1.4     總結

有了TCPServerStreamRequestHandler兩個構造的非常好的基類,處理簡單的HTTP請求並做出響應並不是難事。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章