17.6.2 asynchat 使用例

以下のサンプルは、async_chatでHTTPリクエストを読み込む処理の一部 です。Webサーバは、クライアントからの接続毎に http_request_handlerオブジェクトを作成します。最初はチャネルの終 了条件に空行を指定してHTTPヘッダの末尾までを検出し、その後ヘッダ読み込み 済みを示すフラグを立てています。

ヘッダ読み込んだ後、リクエストの種類がPOSTであればデータが入力ストリーム に流れるため、Content-Length:ヘッダの値を数値として終了条件に指定 し、適切な長さのデータをチャネルから読み込みます。

必要な入力データを全て入手したら、チャネルの終了条件にNoneを指定 して残りのデータを無視するようにしています。この後、 handle_request()が呼び出されます。

class http_request_handler(asynchat.async_chat):

    def __init__(self, conn, addr, sessions, log):
        asynchat.async_chat.__init__(self, conn=conn)
        self.addr = addr
        self.sessions = sessions
        self.ibuffer = []
        self.obuffer = ""
        self.set_terminator("\r\n\r\n")
        self.reading_headers = True
        self.handling = False
        self.cgi_data = None
        self.log = log

    def collect_incoming_data(self, data):
        """Buffer the data"""
        self.ibuffer.append(data)

    def found_terminator(self):
        if self.reading_headers:
            self.reading_headers = False
            self.parse_headers("".join(self.ibuffer))
            self.ibuffer = []
            if self.op.upper() == "POST":
                clen = self.headers.getheader("content-length")
                self.set_terminator(int(clen))
            else:
                self.handling = True
                self.set_terminator(None)
                self.handle_request()
        elif not self.handling:
            self.set_terminator(None) # browsers sometimes over-send
            self.cgi_data = parse(self.headers, "".join(self.ibuffer))
            self.handling = True
            self.ibuffer = []
            self.handle_request()

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。