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
を省略できました。この省略形は廃止します。)
Pegasus では、URI のバス部に続けて「;」で区切って(パスが実行ハンドラを起動する場合に)引数を渡すことができますが(この頁の「URI との関係」を見よ)、それらの引数は自動的に実行プログラムの引数として追加されます。
なおこの例に現れた
/bin/ftp2html
はftp のディレクトリを
扱うために筆者が使用しているツールです。他のサーバでは、index.html がない場合にディレクトリの内容を表示するオプションがあったりしますが、それと類似の機能を持っていますが、それだけではなく README があった場合にはそれも表示するとか、INDEX があった場合には、ディレクトリの内容ではなく INDEX の内容を気のきいたやり方で表示するとかします。
また/bin/dx
は筆者が作成して使用している SSI の機能を実行する(もっと一般的な、そしてシンプルな)ツールです。
/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」と言う用語は意味を失っているのですが、慣用的にハンドラの意味でこの言葉の使用を継続する事にします。
example
に含まれています。 参考にして下さい。
param
と query
を書くことができます。即ち、次の様になっています。path;params?query params = param[;params]Web のサーバは(伝統的には)
param
を無視し、query
をデコードして CGI に引数として渡している様です。Pegasus はこの伝統的な方式を改め、 param
を実行ハンドラに引数として渡すべき部分であると認め、他方query
に関してはサーバは解釈に関与しないことにしました。(query の値は単に環境変数として実行ハンドラに渡る。)
/etc/namespace.cgiで再編成できます。
bind -a /etc/bin/$objtype /bin bind -a /etc/bin/rc /binとして、サービス空間の
/etc/bin/386
や /etc/bin/rc
にツールを置きます。
このファイルが存在しない場合、あるいは存在しても再編成をしていない場合には、CGI プログラムが見る名前空間はサービス空間と同じです。
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' のような時刻他の環境変数は将来廃止されるかも知れないし、また名称が変更されるかも知れません。
Content-Length
の整合性がチェックされます。)Content-Length
を調べる必要は無いはずです。)