BaseHTTPServerの仕組み
つぎはいよいよBaseHTTPServerです。ここがとても参考になります。
TCPServerで、ソケット周りの基本的な機能はすでに実装がなされています。そのためHTTPServer自体はTCPServerを継承してserver_bindをオーバライドしたのみの、シンプルなクラスです。
class HTTPServer(SocketServer.TCPServer): allow_reuse_address = 1 # Seems to make sense in testing environment def server_bind(self): """Override server_bind to store the server name.""" SocketServer.TCPServer.server_bind(self) host, port = self.socket.getsockname() self.server_name = socket.getfqdn(host) self.server_port = port
ご覧のとおり、ここではユーザからのhttpリクエストに関する処理は一切おこなっていません。ユーザからのHTTPリクエストを処理するのはハンドラーのBaseHTTPRequestHandlerクラスになります。そのため、このクラスで実質的なHTTPサーバの処理を行います。
BaseHTTPRequestHandlerの中身
このクラスはSocketServerのStreamRequestHandlerを継承したクラスです。BaseHTTPServerモジュールは、実質的にはこの実装がメインとなっています。StreamRequestHandlerクラスのsetupメソッドにて、ですでにrfileとwfileは作成済みの状態で始まります。以下の一部抜粋したソースコードをご覧下さい。
def handle(self): self.raw_requestline = self.rfile.readline() if not self.parse_request(): # An error code has been sent, just exit return mname = 'do_' + self.command if not hasattr(self, mname): self.send_error(501, "Unsupported method (%s)" % `self.command`) return method = getattr(self, mname) method()
commandにはHTTPリクエストのメソッドを指しています。メソッドがGETの場合はmnameがdo_GETとなり、do_GETメソッドが実装されていれば呼び出されます。BaseHTTPRequestHandlerクラスは、HTTPリクエストを処理するクラスのインタフェースであり、それらは実装されていません。そのためユーザがBaseHTTPServerを継承したクラスを作成し、HTTPの各メソッドに対する処理を実装することになります。