HTTP::Daemon

Hippo2000 (2000/7/28)

HTTP::Daemonモジュールなのです。

作者はGisle Aasさんです。メールで許可をいただきました。


目次


名前

HTTP::Daemon - 簡単なhttpサーバクラス


概要

  use HTTP::Daemon;
  use HTTP::Status;
  my $d = new HTTP::Daemon;
  print "Please contact me at: <URL:", $d->url, ">\n";
  while (my $c = $d->accept) {
      while (my $r = $c->get_request) {
          if ($r->method eq 'GET' and $r->url->path eq "/xyzzy") {
              #これは実際には推奨され*ない*ということを忘れないで下さい:-)
              $c->send_file_response("/etc/passwd");
          } else {
              $c->send_error(RC_FORBIDDEN)
          }
      }
      $c->close;
      undef($c);
  }

説明

HTTP::Daemonのインスタンスは、リクエストがやってくるソケットをlistenするHTTP/1.1サーバです。HTTP::DaemonIO::Socket::INETクラスのサブクラスです。そのため直接ソケット操作を行うことも出来ます。

accept()メソッドはクライアントからの接続が利用可能になると、返ります。返された値はHTTP::Daemon::ClientConnクラスのオブジェクトへのリファレンスで、それはもう1つのIO::Socket::INETのサブクラスです。このオブジェクトにget_request()メソッドを呼ぶと、クライアントからデータを読み込み、HTTP::Requestオブジェクト・リファレンスを返します。

このHTTPデーモンはあなたの代りにfork(2)をしません。あなたのアプリケーション、つまりHTTP::Daemonのユーザは、欲しいのであればフォークすることに責任を持たなければなりません。またユーザはHTTP/1.1プロトコルにしたがったレスポンスを作成することに責任を持たなければなりません。HTTP::Daemon::ClientConnは簡単にするためにいくつかのメソッドを提供します。


メソッド

以下にIO::Socket::INET基本クラスとの比較で、新しい(もしくは拡張された)メソッドの一覧を示します:

$d = new HTTP::Daemon
コンストラクタはIO::Socket::INET コンストラクタと同じパラメータを取ります。何もパラメータを指定せずに呼び出すことも出来ます。デーモンは5つの接続のlistenキューを設定し、いくつかのランダムなポート番号を占有します。標準のHTTPポートである特定のアドレスをバインドしたいサーバは以下のように組み立てます:
  $d = new HTTP::Daemon
        LocalAddr => 'www.someplace.com',
        LocalPort => 80;
$c = $d->accept([$pkg])
このメソッドは IO::Socket::accept と同じです。しかしデフォルトではHTTP::Daemon::ClientConn リファレンスを返します。それはもしタイムアウトを指定し、その時間までになにも接続がなければundefを返します。
$d->url
サーバ・ルートにアクセスするために使うことができるURL文字列を返します。
$d->product_tokens
このサーバがそれ自身を識別するために使う名前を返します。これはServerレスポンス・ヘッダで送信される文字列です。このメソッドを持っている主な理由は、他のプロダクト名を使いたいときサブクラスがオーバーライドすることができるからです。

HTTP::Daemon::ClientConnIO::Socket::INET のサブクラスです。このクラスのインスタンスはHTTP::Daemon.のaccept()メソッドにより返されます。以下の追加のメソッドが提供されます:

$c->get_request([$headers_only])
クライアントからデータを読み込み、返されるHTTP::Requestオブジェクトに変換します。リクエストの読み込みに失敗すれば、undefを返します。もし失敗すれば、HTTP::Daemon::ClientConnオブジェクト($c)は捨てられます。そしてこのメソッドを再び呼んではなりません。$c->reasonメソッドは、 なぜ$c->get_requestがundefを返したかについての情報を与えてくれるかもしれません。

$c->get_request メソッドはフッタのついたチャンクされた転送エンコーディングと自分で区切るmultipart/* コンテント・タイプも含めて、HTTP/1.1リクエスト コンテント・ボディをサポートします。

$c->get_request メソッドは通常はすべてのリクエストがクライアントから受信できるまで戻りません。もしリクエストが数メガバイトのファイルをアップロードする(そしてチャンクされた転送エンコーディングでHTTPが無限のリクエストメッセージをサポードすること−例えばライブな音声のアップロード−が出来たとしても)のであれば、これは望ましいことではないかもしれません。$headers_only引数としてTRUEを渡すと、$c->get_requestは、リクエスト・ヘッダを解析するとすぐに戻ります。そしてリクエスト内容の残りを読むかどうかの責任はあなたにあります。もし同じ接続に$c->get_requestを再び呼び出せば、正しいバイト数を読み込みます。

$c->read_buffer([$new_value])
$c->get_requestにより読み込まれたけれどもread bufferに置かれたバイト。次に$c->get_requestが呼ばれるとネットワーク接続自身からより多くのデータを読み込む前に、このバッファのなかのバイトを消費するでしょう。読み込みバッファは$c->get_requestが未定義の値を返した後は、不正です。

あなた自身でリクエストのコンテントの読み込みを扱うならば、さらに読み込む前にはこのバッファを空にする必要があります。そして消費されないバイトをここに置く必要があります。101 Switching Protocols. のようなサービスを実装するのであっても、このバッファが必要です。

このメソッドは常に古いバッファの内容を返します。引数を渡せば、オプションでバッファを置きかえることも出来ます。

$c->reason
$c->get_requestがundefを返すとき、$c->reasonを呼び出すことにより、なぜそうなったかを説明する短い文字列を取得することが出来ます。
$c->proto_ge($proto)
クライアントがプロトコルのバージョン番号が与えられた引数よりも大きいか同じだといっている場合、TRUEを返します。$proto引数は"HTTP/1.1"や単に"1.1"のような文字列にすることが出来ます。
$c->antique_client
クライアントがHTTP/0.9プロトコルを話していればTRUEを返します。ステータス・コード、ヘッダが何もなければ、そのようなクライアントを返します。これは!$c->proto_ge("HTTP/1.0")と同じです。
$c->force_last_request
$c->get_request がこの接続にさらにリクエストをしないことを保証します。自分自身が分割しないレスポンスをつくると、このメソッドを呼び出すことにより、このことを知らせなければいけません。

属性はクライアント・プロトコルがHTTP/1.0またはそれより悪く、"Connection;"、"Keep-Alive"ヘッダを含まないといっていれば、この属性は自動的にONに切り替わります。またHTTP/1.1またはそれよりもよいクライアントが"Connection:close"リクエスト・ヘッダを送信するとき自動的にONに切り替わります。

$c->send_status_line( [$code, [$mess, [$proto]]] )
クライアントにステータス行を送信します。$codeは想定される200は省略される.$messが省略されると、$code対応するメッセージが挿入されます。$protoが省略されると、$HTTP::Daemon::PROTO 変数の内容が使われます。
$c->send_crlf
クライアントにCRLFの並びを送信します。
$c->send_basic_header( [$code, [$mess, [$proto]]] )
ステータス行と"Date:"と"Server"ヘッダをクライアントに送信します。ヘッダが続くこと、そして空のCRLF行で終わらないことが想定されます。
$c->send_response( [$res] )
クライアントにレスポンスとしてHTTP::Response オブジェクトを書きます。接続がさらなるリクエスト/レスポンス交換のため永続化できるように、レスポンスが自己分割することを保証するようにしています。

HTTP::Response オブジェクトのcontent属性は通常の文字列またはサブルーチン・リファレンスにすることができます。もしサブルーチンであれば、このコールバック・ルーチンが返すものは何であれ、レスポンス・コンテントとしてクライアントに書き戻されます。ルーチンはそれが未定義あるいは空の値を返すまで呼ばれます。もしクライアントがHTTP/1.1がわかれば、レスポンスにチャンクされた転送エンコーディングを使います。

$c->send_redirect( $loc, [$code, [$entity_body]] )
クライアントにリダイレクト・レスポンスを送信します。ロケーション($loc)は絶対あるいは相対のURLを指定することが出来ます。$codeはリダイレクト・ステータス・コードの1つでなければなりません。そしてデフォルトは"301 Moved Permanently"です。
$c->send_error( [$code, [$error_message]] )
クライアントにエラー・レスポンスを送信します。$codeがなければ"Bad Request"エラーが報告されます。$error_messageはHTMLエンティティ・ボディのボディに結合さた文字列です。
$c->send_file_response($filename)
指定された$filenameをコンテントとしたレスポンスを返します。もしfileがディレクトリであれば、そのHTMLインデックスを作ろうとします。
$c->send_file($fd);
クライアントにファイルをコピーします。ファイルは文字列(ファイル名として解釈されます)またはIO::Handle へのリファレンスまたはglobのいずれかを指定することが出来ます。
$c->daemon
対応するHTTP::Daemonオブジェクトへのリファレンスを返します。

参考資料

RFC 2068

IO::Socket, Apache


著作権(COPYRIGHT)

Copyright 1996-1998, Gisle Aas

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


ホーム Perlの小技 HTTP

ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。