4.3 フィルタハンドラの概要

フィルタハンドラ (filter handler) とは、サーバへの入力やサーバからの 出力をフィルタする関数です。 フィルタには二つの種類、入力 (input) および出力 (output)があり、それぞれサーバへの入力とサーバからの出力 に適用されます。

現時点では、mod_python はリクエストレベルのフィルタしかサポート していません。つまり、フィルタできるのは HTTP リクエストか、レスポンスの本体 だけです。 Apache は接続レベルのフィルタをサポートしており、mod_python ではこの機能を将来サポートする予定です。

フィルタハンドラは フィルタ (filter) オブジェクトを引数にとります。 リクエストオブジェクトは filter.req から利用できますが、全ての読み書きは フィルタオブジェクトのread および write メソッドで 行わねばなりません。

フィルタはread 操作が None を返した (ストリームの 終端、EOF に到達したことを示します) 時点で閉じねばなりません。

フィルタの戻り値は無視されます。フィルタはハンドラと違って処理を拒否できませんが、 filter.pass_on() メソッドを使えば同様の効果を引き起こせます。

フィルタはまずPythonIInputFilter またはPythonOutputFilter ディレクティブを使って登録し、その後で、Apache の Add/SetInputFilter または Add/SetOutputFilter ディレクティブで登録せねばなりません。

出力フィルタの指定方法を以下に示します。この例では、 .py ファイルは 全て CAPITALIZE フィルタで処理するようサーバに指示します:

  PythonOutputFilter capitalize CAPITALIZE
  AddOutputFilter CAPITALIZE .py

そして、capitalize.py のコードは以下のようになります:

from mod_python import apache
  
def outputfilter(filter):

    s = filter.read()
    while s:
        filter.write(s.upper())
        s = filter.read()

    if s is None:
        filter.close()

フィルタを書くときには、フィルタの上流にあるものが IO 操作を行うたびに フィルタが呼び出されること、そしてフィルタは流し込まれるデータの量を コントロールできず、リクエスト処理のどこでフィルタが呼び出されるかを 知る術もないということを心に留めておきましょう。

例えば、単一のリクエストの中でフィルタが呼び出される回数は一回だけかも しれないし、五回かもしれません。また、リクエストの完了や、あるリクエスト に対してどれが最初あるいは最後のフィルタ呼び出しであるかを前もって 知る術もありません。ただ EOS (read 操作が None を 返す) だけが、リクエストの末端を強く示唆しているだけにすぎません。

また、サブリクエストを行うと、フィルタが再帰的に呼び出されっぱなしになりうる ことにも注意しておきましょう。データを複数回フィルタさせないためには、 req.main の値を調べ、常にサブリクエストの処理ではないことを確かめ るようにしてください。

フィルタの詳細については http://httpd.apache.org/docs-2.0/developer/filters.html を参照してください。