ISAPI フィルタ概要
ISAPI フィルタ
ISAPI フィルタ (Filter) は ISAPI エクステンション (Extension, 拡張) と並び、IIS の早期のバージョンから実装されている API のひとつです。ISAPI エクステンションが Script Handler エンジン的あるいは CGI 的に使用されるのに対して、 ISAPI フィルタは IIS の内部処理を横取りしてIISをカスタマイズすることを可能とするための API です。
- 例: http://hostname/vdir/foo.htm に対応する物理ファイルを C:\wwwroot\foo.htm から D:\myfolder\bar.htm に差し替える
- HTTP 圧縮 ・ SSL 等の機能は ISAPI フィルタで実装されている
例: スタティックコンテンツの HTTP 圧縮
例として IIS 6 の HTTP 圧縮実装例をあげます。
- compfilt.dll に実装されている
- URL と物理ファイルのマッピングを変更(SF_NOTIFY_URL_MAP)
ISAPI フィルタ DLL の構成
ISAPI フィルタは DLL として実装されており、次の関数をエクスポートしなければなりません。
三つの関数をエクスポートする
- GetFilterVersion: DLLのロード時に呼び出される
- HttpFilterProc: 通知ごとにそれぞれ特有のデータを受け取る。戻り値に特定の値を返すことでフィルターの動作を細かく制御できる。
- TerminateFilter: DLLのアンロード時に呼び出される
通知の種類
IIS の内部処理の様々な段階それぞれについて、ISAPI が通知を受けることができます。 以下がそれぞれの通知です。自己記述的な通知名なのでおよそその内容の見当がつくのではないでしょうか。
- SF_NOTIFY_READ_RAW_DATA
- SF_NOTIFY_PREPROC_HEADERS
- SF_NOTIFY_URL_MAP
- SF_NOTIFY_AUTHENTICATION
- SF_NOTIFY_AUTH_COMPLETE
- SF_NOTIFY_SEND_RESPONSE
- SF_NOTIFY_SEND_RAW_DATA
- SF_NOTIFY_END_OF_REQUEST
- SF_NOTIFY_END_OF_NET_SESSION
戻り値
ISAPI は戻り値によって、通知のチェーンを断ち切ることも処理を終わらせることも、もちろん継続することも可能です。
- SF_STATUS_REQ_FINISHED
- SF_STATUS_REQ_FINISHED_KEEP_CONN
- SF_STATUS_REQ_NEXT_NOTIFICATION
- SF_STATUS_REQ_HANDLED_NOTIFICATION
- SF_STATUS_REQ_ERROR
- SF_STATUS_REQ_READ_NEXT
戻り値は次の図のように使われます。
ISAPI Filter 開発のヒント
知っていると便利(というか知らないときつい)点を三つだけあげてみました。
- フィルタで使うメモリの割り当て - AllocMem
- pFilterContext の使い方
- SF_STATUS_REQ_READ_NEXT
それぞれみていきましょう。
AllocMem
- フィルタ内でメモリを割り当てるときは AllocMem を使う
- AllocMem で割り当てたメモリは自動的に解放される
pFilterContext
- フィルターコンテキストを通して使えるユーザーデータの格納場所
- 初期値は NULL を仮定してよい
2番目の点は意外と重要で、pFilterContext が NULL の場合が初期化されていない状態と考えて大丈夫です。 過去に MS の Redmond の開発者からコードレビュー等も受けたことがありますので、ドキュメントされていないのですが大丈夫と考えてよいでしょう。
SF_STATUS_REQ_READ_NEXT
- HttpFilterProc で SF_STATUS_REQ_READ_NEXT を返すと、Raw データの読み込みを連続したデータ領域として扱うことが可能になる
- HTTP ヘッダーの改変時に必須
IIS 5 が HTTP のヘッダの折り返しをサポートしないので、その回避方法として HTTP ヘッダを 改変したことがあるのですが、その時にこの通知を利用したことで大変楽に実装できました。