HTTP のお浚い

 CGI プログラムの入出力は HTTP(HyperText Transfer Protocol, 超越書類転送作法) に拠るので、まずは HTTP を押さえておきましょう。
 2000年11月現在で最新の HTTP は、HTTP 1.1 です。

HTTP 概略

 World-Wide Web は、クライアント/サーバ方式によるインターネット上の情報交換システムです。敢えて訳すなら、クライアントは主人、サーバは召使を意味するので、クライアント/サーバ・システムとは「ご主人様と奴隷もの」ということになります。
 このシステムでは複数のご主人様が奴隷を共有するので、奴隷は一人でご主人様の人数分を奉仕せねばなりません。奴隷が疲れて動きがとれなくなると「遅い」「役に立たん」「もっと速い奴と取り替えろ」と文句を言われ、過労で倒れでもしたら「動かねえ」「仕事ができん」「損害が出た」などと非難囂囂、奴隷の道もなかなかに厳しいようです。

 HTTP は、このご主人様と奴隷の間でやり取りする、要求 request と応答 response の作法を取り決めたものです。HTTP/1.1 の用語定義によると、(要求を出すために)接続を果たすプログラムが client、要求を執り行う client が user agent、応答を返すプログラムが server とされています。 利用者手先 user agent は同時にご主人様 client でもあるのですが、ご主人様は自ら率先して働くとは限らないわけですね。
 従ってこの作法による通信は、client が接続を張った上で、user agent から server へ送られた要求について、server から user agent へ応答を返す、この繰り返しになります。この通信は、双方向ではありますが、対等ではないのです。

        要求 →→→→→→→→→→→→
  User Agent ------------ 接続 ------------ Server
        ←←←←←←←←←←←← 応答

 この図は直接に繋いだときのもので、実際には間に proxy や gateway や tunnel を介することがあります。これらは要求と応答を中継するので、user agent の機能と server の機能を併せ持つプログラムになっています。

 ところで、Server から返される内容が既存のファイルであれば、Server は単にファイルを探して拾ってくればいいわけです。

        要求 →→→→→→
  User Agent ------ 接続 ------ Server ------> ファイル
        ←←←←←← 応答

 ここで、取ってきたものがファイルでなくプログラムであったときは、Server はプログラムを起動して入力を渡し、出力を受け取ります。この入出力の作法を、CGI (Common Gateway Interface) と呼んでいるのです。

        要求 →→→→    入力→→→→→
  User Agent ---- 接続 ---- Server ---- CGI ---- プログラム
        ←←←← 応答    ←←←←←出力

 CGI (っつーか、Gateway)自体は何も処理しません。その役割は、Server からの入力をプログラムに渡し、プログラムからの出力を Server に返す、その仲立ちをするのみです。
 つまり、CGI とは World-Wide Web のために取り決められた作法の一つなのですが、プロトコルとしてはまだ仕様が固まっておらず、CGI/1.1 の確定に向けてプロジェクトが進行中です。

HTTP message の構成

 User Agent と Server の間でやり取りする要求 request と応答 response を、まとめて HTTP 通信文 HTTP message と呼びます。

       HTTP-message   = Request | Response     ; HTTP/1.1 messages

 この2つはいずれも RFC 822 形式の通信文で、開始行・0個以上の頭項目・頭項目の終りを示すための空行(CRLF 以外何もない行)・通信文本文から成ります。複数の頭項目は、それぞれ CRLF で区切ります。

        generic-message = start-line
                          *(message-header CRLF)
                          CRLF
                          [ message-body ]
        start-line      = Request-Line | Status-Line

通信文頭 Message Headers

 日本では古来より、手紙にいきなり用件を述べることは失礼とされてきました。頭語をつけ、挨拶をつけ、時候の話題について述べ、段々に用件に入るのが礼儀であったので、このような本文の前に置く文章を頭(かしら)と呼びます。今日でも文書を送るときは、何かしら挨拶の文章を置くのが普通でしょう。また、本文を始めるより前に、日付や名目や差出人などを明記するあたり、文書の頭には挨拶だけでなく、付加情報を入れることもあるわけです。

 英語圏でいう header は、ほぼ日本での頭に相当します。コンピュータ通信においても、その用語と概念をそっくり拝借しているので、通信文 message は、頭 header と本文 body とに分けて構成されています。
 もっとも、機械相手に挨拶は無用なので、コンピュータ通信文における頭は付加情報の塊です。

 HTTP header fields として定義されている項目には、以下の4通りがあります。
 項目を書く順序は決まってはいませんが、どちらかというと、この順に並べたほうがわかりやすいでしょう。

  1. 一般頭 general-header (HTTP/1.1 section 4.5)
  2. 要求頭 request-header (HTTP/1.1 section 5.3)
  3. 応答頭 response-header (HTTP/1.1 section 6.2)
  4. 実体頭 entity-header (HTTP/1.1 section 7.1)

 頭項目は、項目名と項目値を1行に組み合わせて書きます。名と値はコロン ":" で区切ります。ただし、項目値は空白文字から始めてよいことになっており、実際読むときには1文字開けたほうが見やすいので、コロン + 半角空白 ": " で区切ると覚えてもいいでしょう。(行継続文字として)タブか半角スペースを付ければ、単一の項目を複数の行にまたがって書くことができます。項目名には HTTP 仕様書に定められたものを使いますが、大文字・小文字は区別しません。

       message-header = field-name ":" [ field-value ]
       field-name     = token
       field-value    = *( field-content | LWS )
       field-content  = <the OCTETs making up the field-value
                        and consisting of either *TEXT or combinations
                        of token, separators, and quoted-string>

 この拡張 BNF に出てくる LWS とは Linear White Space の略で、空白文字の連続を意味します。従って、項目値は半角スペースから始めるとは限らず、タブから始めても、スペースをいくつ開けてもいいわけです。

一般頭項目 General Header Fields

 要求と応答のいずれにも使える頭項目を、一般頭項目 General Header Fields と呼びます。

       general-header = Cache-Control
                      | Connection
                      | Date
                      | Pragma
                      | Trailer
                      | Transfer-Encoding
                      | Upgrade
                      | Via
                      | Warning

通信文本文 Message Body

 通信文本文は、何らかの方式で符号化された実体を担うものとされています。文章であれば文字コード、画像であればバイナリが、ここに入るわけです。

       message-body = entity-body
                    | <entity-body encoded as per Transfer-Encoding>

要求 Request

 HTTP 要求文の第1行には、素材に適用されるべき手法、素材の識別子、利用する作法の版番号が入れられます。

        Request       = Request-Line
                        *(( general-header
                         | request-header
                         | entity-header ) CRLF)
                        CRLF
                        [ message-body ]

要求行 Request-Line

 要求行は手法の指定をもって始め、次に要求する URI と作法の版番号を書き、CRLF で終わります。各要素は空白文字で区切ります。要求行の途中に CR あるいは LF を入れてはなりません。

        Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

 この拡張 BNF に出てくる SP とは Space の略で、US-ASCII 32 番を指します。

手法 Method

 手法指定は、要求 URI で識別された素材を取り扱う手法を示すものです。大文字・小文字は区別しません。

       Method         = "OPTIONS"
                      | "GET"
                      | "HEAD"
                      | "POST"
                      | "PUT"
                      | "DELETE"
                      | "TRACE"
                      | "CONNECT"
                      | extension-method
       extension-method = token
要求 URI Request-URI

 要求 URI は、定型素材識別子及び要求に適応する素材の識別子群です。

       Request-URI    = "*" | absoluteURI | abs_path | authority

 この4つのうちいずれを使うかは、要求次第です。例えば、proxy に対しては絶対 URI を使う必要があります。絶対 URI を使うなら、要求行全体は次のような形になります。

       GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

 もっとありがちな使い方としては、元のサーバあるいは gateway 上の素材を指定することでしょう。
 絶対 URI を使ってもいいのですが、ホストから見た経路を指定したほうが簡潔になります。この経路指定を使うときは

       GET /pub/WWW/TheProject.html HTTP/1.1
       Host: www.w3.org

のようにします。

要求頭項目 Request Header Fields

 要求の際に追加できる頭を、要求頭 request-header と呼びます。追加情報のみならず、client 自体の情報も含まれます。

       request-header = Accept
                      | Accept-Charset
                      | Accept-Encoding
                      | Accept-Language
                      | Authorization
                      | Expect
                      | From
                      | Host
                      | If-Match
                      | If-Modified-Since
                      | If-None-Match
                      | If-Range
                      | If-Unmodified-Since
                      | Max-Forwards
                      | Proxy-Authorization
                      | Range
                      | Referer
                      | TE
                      | User-Agent

応答 Response

 サーバは受け取った要求に対して、HTTP 応答文 HTTP response message を返します。

       Response      = Status-Line
                       *(( general-header
                        | response-header
                        | entity-header ) CRLF)
                       CRLF
                       [ message-body ]

状況行 Status-Line

 応答文第1行は、状況行 Status-Line です。これは、作法の版番号・数字による状況符号・関連語句、及び各要素を区切る空白文字から構成されます。状況行の途中に CR あるいは LF を入れてはなりません。

       Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
状況符号 Status-Code

 状況符号は、3桁の数字です。最初の数字が、5級までの応答の階級を示します。

- 1xx: Informational
Request received, continuing process
- 2xx: Success
The action was successfully received, understood, and accepted
- 3xx: Redirection
Further action must be taken in order to complete the request
- 4xx: Client Error
The request contains bad syntax or cannot be fulfilled
- 5xx: Server Error
The server failed to fulfill an apparently valid request

 HTTP/1.1 に定められた全コードは、次のとおりです。

      Status-Code    =
            "100"  ; Section 10.1.1: Continue
          | "101"  ; Section 10.1.2: Switching Protocols
          | "200"  ; Section 10.2.1: OK
          | "201"  ; Section 10.2.2: Created
          | "202"  ; Section 10.2.3: Accepted
          | "203"  ; Section 10.2.4: Non-Authoritative Information
          | "204"  ; Section 10.2.5: No Content
          | "205"  ; Section 10.2.6: Reset Content
          | "206"  ; Section 10.2.7: Partial Content
          | "300"  ; Section 10.3.1: Multiple Choices
          | "301"  ; Section 10.3.2: Moved Permanently
          | "302"  ; Section 10.3.3: Found
          | "303"  ; Section 10.3.4: See Other
          | "304"  ; Section 10.3.5: Not Modified
          | "305"  ; Section 10.3.6: Use Proxy
          | "307"  ; Section 10.3.8: Temporary Redirect
          | "400"  ; Section 10.4.1: Bad Request
          | "401"  ; Section 10.4.2: Unauthorized
          | "402"  ; Section 10.4.3: Payment Required
          | "403"  ; Section 10.4.4: Forbidden
          | "404"  ; Section 10.4.5: Not Found
          | "405"  ; Section 10.4.6: Method Not Allowed
          | "406"  ; Section 10.4.7: Not Acceptable
          | "407"  ; Section 10.4.8: Proxy Authentication Required
          | "408"  ; Section 10.4.9: Request Time-out
          | "409"  ; Section 10.4.10: Conflict
          | "410"  ; Section 10.4.11: Gone
          | "411"  ; Section 10.4.12: Length Required
          | "412"  ; Section 10.4.13: Precondition Failed
          | "413"  ; Section 10.4.14: Request Entity Too Large
          | "414"  ; Section 10.4.15: Request-URI Too Large
          | "415"  ; Section 10.4.16: Unsupported Media Type
          | "416"  ; Section 10.4.17: Requested range not satisfiable
          | "417"  ; Section 10.4.18: Expectation Failed
          | "500"  ; Section 10.5.1: Internal Server Error
          | "501"  ; Section 10.5.2: Not Implemented
          | "502"  ; Section 10.5.3: Bad Gateway
          | "503"  ; Section 10.5.4: Service Unavailable
          | "504"  ; Section 10.5.5: Gateway Time-out
          | "505"  ; Section 10.5.6: HTTP Version not supported
          | extension-code

      extension-code = 3DIGIT
      Reason-Phrase  = *<TEXT, excluding CR, LF>

応答頭項目 Response Header Fields

 応答頭項目は、サーバから返される応答に追加できる頭です。これにはサーバ自体の情報や、目当ての素材に関する情報などが含まれます。

       response-header = Accept-Ranges           ; Section 14.5
                       | Age                     ; Section 14.6
                       | ETag                    ; Section 14.19
                       | Location                ; Section 14.30
                       | Proxy-Authenticate      ; Section 14.33
                       | Retry-After             ; Section 14.37
                       | Server                  ; Section 14.38
                       | Vary                    ; Section 14.44
                       | WWW-Authenticate        ; Section 14.47

実体 Entity

 要求及び応答通信文は、要求の手法や応答文の状況符号によって制限されていない限り、実体へ変換してかまいません。実体は、実体の頭項目と実体の本文から成ります。

実体頭項目 Entity Header Fields

 実体頭項目は、実体本文あるいは目当ての素材に関わる前置情報を定義します。これら前置情報には追加的なものもあり、必須とされるものもあります。

       entity-header  = Allow                    ; Section 14.7
                      | Content-Encoding         ; Section 14.11
                      | Content-Language         ; Section 14.12
                      | Content-Length           ; Section 14.13
                      | Content-Location         ; Section 14.14
                      | Content-MD5              ; Section 14.15
                      | Content-Range            ; Section 14.16
                      | Content-Type             ; Section 14.17
                      | Expires                  ; Section 14.21
                      | Last-Modified            ; Section 14.29
                      | extension-header

       extension-header = message-header

実体本文 Entity Body

 HTTP 要求あるいは応答をもって送られる実体本文は、実体頭項目で定義された形式及び符号化に則ります。

       entity-body    = *OCTET
Copyright(C): 2000, 魔術幻燈
poetlabo@cap.bekkoame.ne.jp