Subsections

特別な変数と関数

CherryPyはいくつかの特別な変数と関数を設定と利用をしています。これらはとてもシンプルで使いやすいものですがとても今日強力です。この章では、これらの特別な変数と関数が何であるかをみることにして、次の章でそれらの使い方を学ぶことにします。

特別な変数

request

これはもっとも頻繁に使われる変数です。これはクライアントによって送られたリクエストについての全ての情報が入っているものです。これは各リクエストに対して、CherryPyによって設定されたいくつかのメンバ変数が含まれているクラスのインスタンスです。最も頻繁に使われるメンバ変数は:

response

これは(requestの次に)2番目によく使われる変数です。これはクライアントに送り返される全ての情報を含んでいます。これはCherryPyかあなたのプログラムによって設定されたいくつかのメンバ変数が入っているクラスインスタンスです。

特別な関数

コード内では、あなたはサーバーの振舞いを変える特別な関数を定義することができます。この関数を定義するには、Pythonの通常のシンタックスを使い、全てのCherryClassの外部でそれらを定義します。異なるモジュールを使う時、異なるモジュール内の同じ関数を定義することができます。この場合、ファイルを読み込んだ順番と同じ順番で、CherryPyは全ての関数のボディをつなげます。

initServer

この関数は初期化中にサーバーに呼び出されます。最初に、サーバーはCherryClassの全てのインスタンスを作成し、それからこれをinitServerという特別な関数を呼び出します。これは基本的にいくつかの初期化のタスクを必要であれば実行する場所です。

initRequest, initNonStaticRequest, initResponse, initNonStaticResponse

ここではリクエストを受け取った時にサーバーが使うアルゴリズムを示します:

静的コンテンツ 全てのコンテンツ 動的コンテンツ
  a.リクエストが来ます  
  b.requestのメンバ変数全てがセットされます  
  c.initRequestを呼び出します(これは、request.pathrequest.paramMapを変更するかもしれません)  
  d.このリクエストが静的コンテンツか、それとも動的コンテンツに一致するかを決めます(request.pathと設定ファイルのstaticContentセクションに基づきます)  
    e.initNonStaticRequestを呼び出します(これはrequest.pathrequest.paramMapを変更するかもしれません)
e.静的ファイルを読み込みセットする(response.headerMapの値とresponse.bodyに応じます)   f.CherryClassインスタンスのメソッドを引数つきで呼び出し(request.pathrequest.paramMapに基づきます)、その結果によってresponse.headerMapの値とresponse.bodyをセットする
f.initResponseを呼び出す(これはresponse.headerMapresponse.bodyを変更するかもしれません)   g.initResponseを呼び出す(これはresponse.headerMapresponse.bodyを変更するかもしれません)
g.ブラウザへレスポンスを送る(response.headerMapresponse.bodyに基づきます)   h.ブラウザにレスポンスを送ります(response.headerMapresponse.bodyに基づきます)

見ての通り、クライアントに送り返す直前に、レスポンスヘッダやボディを変更するためにinitResponseinitNonStaticResponseを使うことが可能です。

onError

この関数はページを構築中にエラーが起こった時にCherryPyによって呼び出されます。次の章の例を見てください。

URLを操作する

あなたの顧客のためにウェブサイトをセットアップしたいと思ったとします。あなたは各顧客がURL: http://host/customerNameを使ってもらおうとし、しかしページは各顧客ごとでもほとんど同じであり、よって、あなたは各顧客のためにメソッドを一つ一つ作成はしたくないと思ったとします。

あなたがやるべきことは、initNonStaticRequestを使い、URL http://host/customerNamehttp://host?customer=customerNameに変換するだけです。全てが各ユーザーに透過的になります。

以下のコードを入力します:

def initNonStaticRequest():
    if request.path:
        request.paramMap['customer']=request.path
        request.path=""
CherryClass Root:
mask:
    def index(self, customer=""):
        <html><body>
            Hello, <py-eval="customer">
        </body></html>

ファイルをコンパイルし、サーバーを立ち上げ、http://localhost:8000/customer1http://localhost:8000/worldなどのいくつかのURLを試してください。

リダイレクトを送り返す

redirectをブラウザに送るためにやるべきことは302のコードステータスを(200の代わりに)送り返し、レスポンスヘッダ内のlocation値をセットします。これは特別な変数であるresponse.headerMapを使えば簡単に可能です。
CherryClass Root:
mask:
    def index(self):
        <html><body>
            <a href="loop">Click here to come back to this page</a>
        </body></html>
view:
    def loop(self):
        response.headerMap['status']=302
        response.headerMap['location']=request.base
        return "" # A view should always return a string

各ページに時間情報を追加する

このサンプルでは、サーバーによって表示される各ページの末尾に1行追加することにします。この1行はそのページを作成した時間が入っています。もちろん、動的なHTMLページのためにこの1行が欲しいだけなのです。

やるべきことは、initNonStaticRequestを使ってスタート時間を格納し、initNonStaticResponseを使って作成時間が入っている1行を追加します。

コードは以下の通り:

import time
def initNonStaticRequest():
    request.startTime=time.time()
def initNonStaticResponse():
    if response.headerMap['content-type']=='text/html':
        response.body+='<br>Time: %.04fs'%(time.time()-request.startTime)
CherryClass Root:
mask:
    def index(self):
        <html><body>
            Hello, world
        </body></html>

エラーメッセージのカスタマイズ

これは特別な関数onErrorを通して行います。やりたいことを達成するにはresponse.headerMapresponse.bodyを使うだけです。

以下の例ではセットアップの仕方とエラーが起こったエラー全てにemailを送ります:

use Mail

def onError():
    # Get the error in a string
    import traceback, StringIO
    bodyFile=StringIO.StringIO()
    traceback.print_exc(file=bodyFile)
    errorBody=bodyFile.getvalue()
    bodyFile.close()
    # Send an email with the error
    myMail.sendMail("erreur@site.com", "webmaster@site.com", "", "text/plain", "An error occured on
your site", errorBody)
    # Set the body of the response
    response.body="<html><body><br><br><center>"
    response.body+="Sorry, an error occured<br>"
    response.body+="An email has been sent to the webmaster"
    response.body+="</center></body></html>"


CherryClass MyMail(Mail):
function:
    def __init__(self):
        self.smtpServer='smtp.site.com'

CherryClass Root:
mask:
    def index(self):
        <html><body>
            <a py-attr="request.base+'/generateError'" href="">Click here to generate an error</a>
        </body></html>
    def generateError(self):
        <html><body>
            You'll never see this: <py-eval="1/0">
        </body></html>

この例ではCherryPyに備わっている標準モジュールMailの使い方も示してあります。



Debian User 2003-10-13