tonado:web.pyのRequest Handler

7642 ワード

Request Handlerという種類は1000行を超えています。十一個の巨大なもののように見えますが、多くは注釈と空の方法で、全体的に読みやすいです。
 
このクラスもblogプロジェクトの中のすべてのhandlerの父親類です。多くのtonadoプロジェクトもそうです。もちろん名前の通りにこの種類とその派生類はtonado web serverが受け取ったhttprequestを処理します。今までhttpsperverのコードを見たことがありません。適当に推測してください。httprequestの処理の大まかな流れ:
  • Httpsperver受信要求
  • Applicationのインスタンスに投げて処理します。
  • Applicationの例は、初期化時(または後でaddhandlerによって追加された)ルーティングテーブルに従って、対応するhandlerのインスタンスを生成し、requestを投げ込んで処理する。
    現在のデフォルトのtonadoは以下のようないくつかの方法をサポートしています。
    SUPPORTED_METHODS = ("GET", "HEAD", "POST", "DELETE", "PATCH", "PUT",
                             "OPTIONS")
     何年前よりRESTをたくさん見たようです。。head、patch、optionsはどうですか?
     
    このクラスは基礎クラスですので、空き方法を定義しています。ここに単独で並べられる方法がいくつかあります。
        def prepare(self):
            """Called at the beginning of a request before `get`/`post`/etc.
    
            Override this method to perform common initialization regardless
            of the request method.
            """
            pass
    
        def on_finish(self):
            """Called after the end of a request.
    
            Override this method to perform cleanup, logging, etc.
            This method is a counterpart to `prepare`.  ``on_finish`` may
            not produce any output, as it is called after the response
            has been sent to the client.
            """
            pass
    
        def on_connection_close(self):
            """Called in async handlers if the client closed the connection.
    
            Override this to clean up resources associated with
            long-lived connections.  Note that this method is called only if
            the connection was closed during asynchronous processing; if you
            need to do cleanup after every request override `on_finish`
            instead.
    
            Proxies may keep a connection open for a time (perhaps
            indefinitely) after the client has gone away, so this method
            may not be called promptly after the end user closes their
            connection.
            """
            pass
    
     基本的にはある程度のcalbackを提供していますが、私はtonadoの経験がありません。どれぐらいの項目が本当に使われているのか分かりません。
     
     奇妙なのは、このクラスの中にいくつかの繰り返しに見える変数が定義されています。
     
            # UIModules are available as both `modules` and `_modules` in the
            # template namespace.  Historically only `modules` was available
            # but could be clobbered by user additions to the namespace.
            # The template {% module %} directive looks in `_modules` to avoid
            # possible conflicts.
            self.ui["_modules"] = ObjectDict((n, self._ui_module(n, m)) for n, m in
                                     application.ui_modules.iteritems())
            self.ui["modules"] = self.ui["_modules"]
     
     
    また、この2つの方法で使用される2つのメンバー変数があります。
     
        def set_header(self, name, value):
            """Sets the given response header name and value.
    
            If a datetime is given, we automatically format it according to the
            HTTP specification. If the value is not a string, we convert it to
            a string. All header values are then encoded as UTF-8.
            """
            self._headers[name] = self._convert_header_value(value)
    
        def add_header(self, name, value):
            """Adds the given response header and value.
    
            Unlike `set_header`, `add_header` may be called multiple times
            to return multiple values for the same header.
            """
            self._list_headers.append((name, self._convert_header_value(value)))
      
     
    何の意味がありますか?後ろがまだ見えません。まだ分かりません。
     
    次にいくつかのすでに実現した方法で、その中の比較的に重要なのはひとつひとつ取り出して言います。
  • sets ucookieは、handleにおいて、_newuucookieというSimpleCookieのインスタンスを初期化し、その後、導入されたパラメータに基づいてdomainを設定し、 expires パス、 max-age、および他のユーザーがカスタマイズしたクッキーpair
  • clear Cookieという方法は面白いです。clearの意味は「clear」ではなく、cookieを設定するexpire timeを通じてクライアントブラウザからクッキーを削除させます。server端ではなくて、
  • です。
  • sets ucookieこの方法は、Apple.Settingsに設定されたsecretを用いて、暗号化されたクッキー
  • を生成します。
  • get-ucookieこれは上記の方法の対になる方法です。
  • redirectは、reponse headerの中のlocationを設定し、http statusを3 xxとして設定します。このようなreponseが一旦戻りますと、ブラウザはデフォルトでlocationで指定されたurlにリダイレクトすることをトリガします。
  • writeこの方法の注釈ははっきりしています。
            """Writes the given chunk to the output buffer.
    
            To write the output to the network, use the flush() method below.
    
            If the given chunk is a dictionary, we write it as JSON and set
            the Content-Type of the response to be application/json.
            (if you want to send JSON as a different Content-Type, call
            set_header *after* calling write()).
    
            Note that lists are not converted to JSON because of a potential
            cross-site security vulnerability.  All JSON output should be
            wrapped in a dictionary.  More details at
            http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
            """
  • renderこれはとても重要な関数です。指定されたテンプレートから最終的なレンダリングページを生成します。長すぎるので、ジャンプしてしまいました。後で振り返ってみます。
  • renders ustringこれも重要な関数です。あまり長くないですが、見ました。分かりませんでした。主にtemplateの神名が分かりませんでした。一つのtermはtemplateというnamespaceです。どう見てもnamespaceとは呼べないです。contextというのがもっと適当です。信じません。どうぞ。 
  • flushは基本的にこの方法でブザーの中のものを呼び出して登録のtranformをdata chunkに変えて、headerを生成して、最後にhttprequestのwrite方法を呼び出してクライアント
  • に書き込みます。
  • finish flush方法は本当にデータをrequestに書き込むのです。(全体的には単独のrespnseを使うと比較的に混乱しないと思いますか?)ただし、requestのfinishメソッドは呼び出されません。これらはfinishメソッドで呼び出されます。だから、一つのrequestの最後の呼び出しはきっとfinishメソッドで要求を終了します。finishメソッドの内部でflushを呼び出しますが、finishの前にflushを呼び出したら、行は不確定かもしれません。flushメソッドに入ってきたcalback方法によってどのように実現しますか?コードから見て、flashをコードの中で呼び出さないでください。このような粗い重労働はfinishでできます。注意したいのは、handlerの中のいくつかの方法のデフォルトの実現はfinishを呼んでくれるので、2回目を呼び出さないでください。そうでないと、exceptionを抛り出します。これらの方法は以下の通りです。
  • sendauerrorこの方法は主にwriteauerrorに依存してエラーページを生成してユーザー
  • に戻る。
  • writegauerrorはコードを見て、handlerの中でユーザー定義のgetuerroru方法のやり方がより信頼できると思います。
  • localeというpropertyは、内部で2つの異なる方法を呼び出すかもしれない。1.self.getsuusero 2.self.getubrowsteraulocaleのうち、最初の方法はデフォルトでは実現されていないが、プログラマによって重載されてもよい。2つの方法を提供する主な目的は、例えば、ブラウザの中のlangggageから他のパラメータを無視することである。ユーザー設定の言語プリファレンスをデータベースから読み出し(一般的なプロキシの学生は、より深い理解を得るべきである)、第二の方法は名前の通り、ユーザrequestのheaderからAccept-laggageを読み取り、ユーザーのlocaleを決定する。最初の方法が失敗またはNoneに戻った場合にのみ、第二の方法を呼び出すことができる。
  • currentuuserは現在のユーザ情報を取得します。デフォルトで提供するとお尻が乾いていませんので、この方法でユーザ識別認証を行う必要があります。ユーザ情報を取得するには、self.getcuurrentuuser方法を再ロードする必要があります。
  • getgingurl取得Aplication.Settingsに定義されているgetgingsアドレス
  • get emplateuptathは、Appplication.Settingsに定義されているgetmutemplateuplathを取得します。このパスは絶対パスであり、templateファイルを格納するディレクトリを指すべきです。またはNoneに戻って、現在のファイルの相対パスから検索を開始します。
  • xsrft propertyは、forgery攻撃を防止するためにxsrft kenを獲得しました。このxsrft tokenはユーザブラウザのクッキーに同時に保存されます。また、現在handlerの_xsrft ken属性は、ユーザーpostメッセージの検証に使用されます。この実現はちょっと分かりません。もしユーザがクッキーを盗まれたら、どうすればいいですか?cure ucookieでしょう?
  • chockksrfucookieはパラメータの中に_xsrfを携帯しているか、またはheaderの中にX-Xsrftokenが含まれているかを確認し、 X-CSSrftoken。存在する場合は、handleに保存されている値と比較します。
  • xsrfthelper方法で、hiddenのform itemコードのセグメントを生成します。formに従ってpostにserverを与えられます。つまりchocksrfucookieで検査されるものです。
  • _executeはhttpタイプによって、handleのget、post、delete、editなどの方法をそれぞれ呼び出します。