20.18. "BaseHTTPServer" --- 基本的な機能を持つ HTTP サーバ
**********************************************************

注釈: "BaseHTTPServer" モジュールは、Python 3 では "http.server" モ
  ジュー ルに統合されました。 *2to3* ツールが自動的にソースコード内の
  import を修正します。

**ソースコード:** Lib/BaseHTTPServer.py

======================================================================

このモジュールでは、 HTTP サーバ (Web サーバ) を実装するための二つのの
クラスを定義しています。通常、このモジュールが直接使用されることはなく
、特定の機能を持つ Web サーバを構築するために使われます。
"SimpleHTTPServer" および "CGIHTTPServer" モジュールを参照してください
。

最初のクラス "HTTPServer" は "SocketServer.TCPServer" のサブクラスで、
従って "SocketServer.BaseServer" インタフェースを実装しています。
"HTTPServer" は HTTP ソケットを生成してリクエスト待ち (listen) を行い
、リクエストをハンドラに渡します。サーバを作成して動作させるためのコー
ドは以下のようになります:

   def run(server_class=BaseHTTPServer.HTTPServer,
           handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
       server_address = ('', 8000)
       httpd = server_class(server_address, handler_class)
       httpd.serve_forever()

class BaseHTTPServer.HTTPServer(server_address, RequestHandlerClass)

   このクラスは "TCPServer" 型のクラスの上に構築されており、サーバのア
   ドレスをインスタンス変数 "server_name" および "server_port" に記憶
   します。サーバはハンドラからアクセス可能で、通常 "server" インスタ
   ンス変数でアクセスします。

class BaseHTTPServer.BaseHTTPRequestHandler(request, client_address, server)

   このクラスはサーバに到着したリクエストを処理します。このメソッド自
   体では、実際のリクエストに応答することはできません; (GET や POST の
   ような) 各リクエストメソッドを処理するためにはサブクラス化しなけれ
   ばなりません。 "BaseHTTPRequestHandler" では、サブクラスで使うため
   のクラスやインスタンス変数、メソッド群を数多く提供しています。

   このハンドラはリクエストを解釈し、次いでリクエスト形式ごとに固有の
   メソッドを呼び出します。メソッド名はリクエストの名称から構成されま
   す。例えば、リクエストメソッド "SPAM" に対しては、 "do_SPAM()" メソ
   ッドが引数なしで呼び出されます。リクエストに関連する情報は全て、ハ
   ンドラのインスタンス変数に記憶されています。サブクラスでは
   "__init__()" メソッドを上書きしたり拡張したりする必要はありません。

   "BaseHTTPRequestHandler" は以下のインスタンス変数を持っています:

   client_address

      HTTP クライアントのアドレスを参照している、"(host, port)" の形式
      をとるタプルが入っています。

   server

      server インスタンスが入っています。

   command

      HTTP 命令 (リクエスト形式) が入っています。例えば "'GET'" です。

   path

      リクエストされたパスが入っています。

   request_version

      リクエストのバージョン文字列が入っています。例えば "'HTTP/1.0'"
      です。

   headers

      "MessageClass" クラス変数で指定されたクラスのインスタンスを保持
      しています。このインスタンスは HTTP リクエストのヘッダを解釈し、
      管理しています。

   rfile

      入力ストリームが入っており、そのファイルポインタはオプション入力
      データ部の先頭を指しています。

   wfile

      クライアントに返送する応答を書き込むための出力ストリームが入って
      います。このストリームに書き込む際には、HTTP プロトコルに従った
      形式をとらなければなりません。

   "BaseHTTPRequestHandler" は以下のクラス変数を持っています:

   server_version

      サーバのソフトウェアバージョンを指定します。この値は上書きする必
      要が生じるかもしれません。書式は複数の文字列を空白で分割したもの
      で、各文字列はソフトウェア名[/バージョン] の形式をとります。例え
      ば、"'BaseHTTP/0.2'" です。

   sys_version

      Python 処理系のバージョンが, "version_string" メソッドや
      "server_version" クラス変数で利用可能な形式で入っています。例え
      ば "'Python/1.4'" です。

   error_message_format

      クライアントに返すエラー応答を構築するための書式化文字列を指定し
      ます。この文字列は丸括弧で囲ったキー文字列で指定する形式を使うの
      で、書式化の対象となる値は辞書でなければなりません。キー *code*
      は整数で、HTTP エラーコードを特定する数値です。 *message* は文字
      列で、何が発生したかを表す (詳細な) エラーメッセージが入ります。
      *explain* はエラーコード番号の説明です。 *message* および
      *explain* の標準の値は *response* クラス変数でみつけることができ
      ます。

   error_content_type

      エラーレスポンスをクライアントに送信する時に使う Content-Type
      HTTP ヘッダを指定します。デフォルトでは "'text/html'" です。

      バージョン 2.6 で追加: 以前は、 Content-Type は常に
      "'text/html'" でした。

   protocol_version

      この値には応答に使われる HTTP プロトコルのバージョンを指定します
      。 "'HTTP/1.1'" に設定されると、サーバは持続的 HTTP 接続を許可し
      ます; しかしその場合、サーバは全てのクライアントに対する応答に、
      正確な値を持つ "Content-Length" ヘッダを ("send_header()" を使っ
      て) 含め *なければなりません* 。以前のバージョンとの互換性を保つ
      ため、標準の設定値は "'HTTP/1.0'" です。

   MessageClass

      HTTP ヘッダを解釈するための "rfc822.Message" 類似のクラスを指定
      します。通常この値が上書きされることはなく、標準の値
      "mimetools.Message" になっています。

   responses

      この変数はエラーコードを表す整数を二つの要素をもつタプルに対応付
      けます。タプルには短いメッセージと長いメッセージが入っています。
      例えば、 "{code: (shortmessage, longmessage)}" といったようにな
      ります。 *shortmessage* は通常、エラー応答における *message* キ
      ーの値として使われ、 *longmessage* は *explain* キーの値として使
      われます ("error_message_format" クラス変数を参照してください)
      。

   "BaseHTTPRequestHandler" インスタンスは以下のメソッドを持っています
   :

   handle()

      "handle_one_request()" を一度だけ (持続的接続が有効になっている
      場合には複数回) 呼び出して、HTTPリクエストを処理します。このメソ
      ッドを上書きする必要はまったくありません; そうする代わりに適切な
      "do_*()" を実装してください。

   handle_one_request()

      このメソッドはリクエストを解釈し、適切な "do_*()" メソッドに転送
      します。このメソッドを上書きする必要はまったくありません。

   send_error(code[, message])

      完全なエラー応答をクライアントに送信し、ログ記録します。 *code*
      は数値型で、HTTP エラーコードを指定します。 *message* はオプショ
      ンで、より詳細なメッセージテキストです。 完全なヘッダのセットが
      送信された後、 "error_message_format" クラス変数を使って組み立て
      られたテキストが送られます。 メソッドが HEAD もしくはレスポンス
      コードが次のどれかの場合はボディは空です: "1xx", "204 No
      Content", "205 Reset Content", "304 Not Modified" 。

   send_response(code[, message])

      応答ヘッダを送信し、受理したリクエストをログ記録します。HTTP 応
      答行が送られた後、 *Server* および *Date* ヘッダが送られます。こ
      れら二つのヘッダはそれぞれ "version_string()"  および
      "date_time_string()" メソッドで取り出します。

   send_header(keyword, value)

      出力ストリームに特定の HTTP ヘッダを書き込みます。 *keyword* は
      ヘッダのキーワードを指定し、 *value* にはその値を指定します。

   end_headers()

      応答中の HTTP ヘッダの終了を示す空行を送信します。

   log_request([code[, size]])

      受理された (成功した) リクエストをログに記録します。*code* には
      この応答に関連付けられた HTTP コード番号を指定します。応答メッセ
      ージの大きさを知ることができる場合、*size* パラメタに渡すとよい
      でしょう。

   log_error(...)

      リクエストを遂行できなかった際に、エラーをログに記録します。標準
      では、メッセージを "log_message()" に渡します。従って同じ引数
      (*format* と追加の値) を取ります。

   log_message(format, ...)

      任意のメッセージを "sys.stderr" にログ記録します。このメソッドは
      通常、カスタムのエラーログ記録機構を作成するために上書きされます
      。 *format* 引数は標準の printf 形式の書式化文字列で、
      "log_message()" に渡された追加の引数は書式化の入力として適用され
      ます。ログ記録される全てのメッセージには、クライアントの IP アド
      レスおよび現在の日付、時刻が先頭に付けられます。

   version_string()

      サーバソフトウェアのバージョン文字列を返します。この文字列はクラ
      ス変数 "server_version" および "sys_version" を組み合わせたもの
      です。

   date_time_string([timestamp])

      メッセージヘッダ向けに書式化された、 *timestamp* ("time.time()"
      のフォーマットである必要があります)で与えられた日時を返します。
      もし *timestamp* が省略された場合には、現在の日時が使われます。

      出力は "'Sun, 06 Nov 1994 08:49:37 GMT'" のようになります。

      バージョン 2.5 で追加: *timestamp* パラメータ.

   log_date_time_string()

      ログ記録向けに書式化された、現在の日付および時刻を返します。

   address_string()

      ログ記録向けに書式化された、クライアントのアドレスを返します。こ
      のときクライアントの IP アドレスに対する名前解決を行います。


20.18.1. 他の例
===============

永遠ではなく、何かの条件が満たされるまでの間実行するサーバーを作るには
:

   def run_while_true(server_class=BaseHTTPServer.HTTPServer,
                      handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
       """
       This assumes that keep_running() is a function of no arguments which
       is tested initially and after each request.  If its return value
       is true, the server continues.
       """
       server_address = ('', 8000)
       httpd = server_class(server_address, handler_class)
       while keep_running():
           httpd.handle_request()

参考:

  "CGIHTTPServer" モジュール
     CGI スクリプトをサポートするように拡張されたリクエストハンドラ。

  "SimpleHTTPServer" モジュール
     ドキュメントルートの下にあるファイルに対する要求への応答のみに制
     限した基本リクエストハンドラ。
