実行ハンドラ
目次- 1.0.0 設定の方法
- 2.0.0 Apche の CGI との関係
- 3.0.0 CGI を書く言語
- 4.0.0 URI との関係
- 5.0.0 CGI の名前空間(ハンドラの名前空間)
- 6.0.0 CGI の環境変数(ハンドラの環境変数)
- 7.0.0 POST データのハンドリング
- 8.0.0 CGI timeout(ハンドラのタイムアウト)
2002/08/30
実行ハンドラと言うのは多分 Pegasus 独自の機能で、特定のパスパターンのファイルに対して、それを処理するプログラムをユーザが指定あるいは組み込める機能です。
Pegasus ではこれを、CGI プログラムの定義や SSI (server side include) の機能の実現、さらにある特定のディレクトリに対して index.html が存在しない場合にファイルの一覧を表示する機能の実現のために使用されています。
設定の方法
サービス空間の中の/etc/handlerに、パスパターンとコマンドを結びつける行を書く。筆者のサーバ(http://plan9.aichi-u.ac.jp)のファイルの内容は次のようなものです。
# path mimetype ramfs execpath arg ... /netlib/*/index.html text/html 0 /bin/ftp2html *.http - 0 $target *.html text/html 1 $target *.dx_html text/html 0 /bin/dx $targetこの表は、パスパターン(第1項)によって、そのファイルを処理するプログラム(第4項)と処理の方法(第2項と第3項)を表しています。パスパターンの比較は上の行から行われ、マッチすればそこで終ります。第5項目以降でプログラムの引数を指定する事もできます。
パスパターンの指定において `/
' は基本的に他の文字と同じ扱いですが(従ってシェルのパスパターンの扱いと同じではありません)、1つの例外があります。
/netlib/*/index.html</pre>のように、
/*/
のパターンは /
にマッチすると言うルールが追加されています。(このルールは Pegasus が ftp ディレクトリを扱うのに都合の良い様にできている訳です。)
第2項は HTTP ヘッダの ContentType を表しています。これが `-
' の場合にはプログラムは HTTP ヘッダを自ら出力する必要があります。
第3項はプログラムの実行に伴って ramfs がサービスされるか否かを表しています。
第4項は実行プログラムが指定されます。第4項以降に現れる $target
はリクエストされたドキュメントの絶対パスを表しています。第4項が $target
になっていると言う事は、要求されたドキュメントが実行プログラムである事を意味しています。
第5項目以降に実行プログラムの引数を書くことができます。(Pegasus 1.1 では引数の最後が $target
で終る場合には、$target
を省略できました。この省略形は廃止します。)
なおこの例に現れた
/bin/ftp2html
はftp のディレクトリを
扱うために筆者が使用しているツールです。他のサーバでは、index.html がない場合にディレクトリの内容を表示するオプションがあったりしますが、それと類似の機能を持っていますが、それだけではなく README があった場合にはそれも表示するとか、INDEX があった場合には、ディレクトリの内容ではなく INDEX の内容を気のきいたやり方で表示するとかします。
また/bin/dx
は筆者が作成して使用している SSI の機能を実行する(もっと一般的な、そしてシンプルな)ツールです。
Apche の CGI との関係
Pegasus 1.0 では、いわゆる CGI ファイルは実行ハンドラの単なる1つの形式として扱われています。/etc/handler
で mimetype として -
を指定した場合にはハンドラは HTTP ヘッダの全てを(標準出力に)出力する必要があります。例えばHTTP/1.1 200 OK Server: Pegasus/1.2 (Plan9) Date: Tue, 27 Aug 2002 03:35:12 GMT Content-Type: text/html Connection: Keep-Alive Content-length: 1234
<html> ... </html>のようなものです。mimetype として
text/html
を指定した場合には単に HTML 形式、即ち<html> ... </html>だけを書き出します。Apche の CGI は
Content-Type: text/html
<html> ... </html>従って Pegasus の
*.html
ファイルの方が幾分簡単になっています。しかも Pegasus の *.html
はそれ以上の効果を持っています。即ちクライアントから見た時に CGI ファイルである事が分からないのです。
Content-length
の値は、CGI プログラムが全てのデータを書き出すまで分かりません。そのため Pegasus の現在の版では Content-length
を省いています。その場合にはクライアントは
Connection: closeが指定されたものと解釈し、CGI が出力したデータを受け取った後、接続を切ってしまいます。
Pegasus 1.0 では 「CGI」と言う用語は意味を失っているのですが、慣用的にハンドラの意味でこの言葉の使用を継続する事にします。
CGI を書く言語
UNIX のシェルは問題が多く CGI を書くには適さなかったのですが、Plan9 のシェルである rc はよく設計されていて、筆者は rc をもっとも多く使用しています。次の好みは awk であり、さらに高度な CGI では Python を使用しています。perl は嫌い! (プラグマティズムの見本を見せつけられているようだ)CGI スクリプトの多数のサンプルが配布ファイルの
example
に含まれています。 参考にして下さい。
URI との関係
HTTP/1.0 及び HTTP/1.1 では URI のドキュメントへのパスに続いてparam
と query
を書くことができます。即ち、次の様になっています。path;params?query params = param[;params]Web のサーバは(伝統的には)
param
を無視し、query
をデコードして CGI に引数として渡している様です。Pegasus はこの伝統的な方式を改め、 param
を実行ハンドラに引数として渡すべき部分であると認め、他方query
に関してはサーバは解釈に関与しないことにしました。(query の値は単に環境変数として実行ハンドラに渡る。)
CGI の名前空間(ハンドラの名前空間)
CGI プログラム(ハンドラ)が見る名前空間は、サービス空間の中でのファイル/etc/namespace.cgiで再編成できます。
ユーザ独自の CGI ツールを追加したい場合には、このファイルの内容を
bind -a /etc/bin/$objtype /bin bind -a /etc/bin/rc /binとして、サービス空間の
/etc/bin/386
や /etc/bin/rc
にツールを置きます。
このファイルが存在しない場合、あるいは存在しても再編成をしていない場合には、CGI プログラムが見る名前空間はサービス空間と同じです。
CGI の環境変数(ハンドラの環境変数)
Pegasus は多数の環境変数を持っていますが、しかしながら現在の版では多くはまだ確定してはいません。確定的なのは以下に掲げる少数の環境変数だけです。GATEWAY_INTERFACE SERVER_NAME SERVER_PORT SERVER_SOFTWARE SERVER_PROTOCOL REQUEST_METHOD REMOTE_ADDR QUERY_STRING HTTP_HEADER HTTP_HOST HTTP_REFERER HTTP_USER_AGENT home # /doc query # QUERY_STRING に同じ target # 要求されたドキュメントの(サービス空間での)パス name # taget の basename cputype # 386 objtype # 386 date # 'Mon, 04 Mar 2002 07:32:40 GMT' のような時刻他の環境変数は将来廃止されるかも知れないし、また名称が変更されるかも知れません。
POST データのハンドリング
POST データは一旦サーバ(Pegasus)がクライアントから受け取ります。(その際に実際に受け取ったデータ量とContent-Length
の整合性がチェックされます。)次にサーバ(Pegasus)はこの POST データを CGI の標準入力に渡します。(従って POST データのパーサは
Content-Length
を調べる必要は無いはずです。)