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. 可選的HEADERS;HEADER之間用CRLF或LF分割;
3. 可選的數據部分;數據和HEADER之間由一個空行分割。
HTTP相應數據流中的三個部分:
1. 第一行表示響應代碼,格式爲 <version> <response_code> [<responsestring>];
2. 可選的HEADERS;
3. 數據部分;和HEADER之間由一個空行分割。
1.3 BaseHTTPRequestHandler
在SocketServer.BaseRequestHandler的構造函數中,調用了三個方法:setup, handle, finish。其中handler用來處理請求,而且被實現爲空函數。
在 SocketServer.StreamRequestHandler中,並沒有對handle進行覆蓋,而是覆蓋setup將socket構造爲輸入和輸出文件 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 總結
有了TCPServer和StreamRequestHandler兩個構造的非常好的基類,處理簡單的HTTP請求並做出響應並不是難事。