Studying HTTP > RFC-Translations related HTTP

この文書は、 >D. Robinson, K. Coar: The Common Gateway Interface (CGI) Version 1.1 (RFC 3875), October 2004. を 橋本英彦 が日本語訳した物です。 この文書の取り扱いについては、[Studying HTTP] の RFC 日本語訳を利用するにあたってに従って下さい。


Network Working Group
Request for Comments: 3875
Category: Informational
                    D. Robinson
                        K. Coar
 The Apache Software Foundation
                   October 2004

The Common Gateway Interface (CGI) Version 1.1

この文書の位置付け

この文書はインターネットコミュニティのための情報を提供する物である。 この文書はいかなる種のインターネットの標準も明述する物ではない。 この文書の配布に制限は無い。

著作権表示

Copyright © The Internet Society (2004). All Rights Reserved.

IESG Note

This document is not a candidate for any level of Internet Standard. The IETF disclaims any knowledge of the fitness of this document for any purpose, and in particular notes that it has not had IETF review for such things as security, congestion control or inappropriate interaction with deployed protocols. The RFC Editor has chosen to publish this document at its discretion. Readers of this document should exercise caution in evaluating its value for implementation and deployment.

概要

Common Gateway Interface (CGI) は、プラットフォームに依存しない方法で情報サーバのもとで、外部プログラム、ソフトウェア、ゲートウェイを動かするための単純なインタフェースである。 現在、サポートされている情報サーバは、HTTP サーバである。

このインタフェースは、1993 年以来 World Wide Web (WWW) にて使用されている。 この仕様書は、the U.S. National Centre for Supercomputing Applications にて開発、文書化された 'CGI/1.1' インタフェースの '現在の慣習' のパラメータを定義するものである。 また、この文書は UNIX ® や、他の同様のシステム上での CGI/1.1 インタフェースの使用方法も定義する。

目次

1 導入
1.1 目的
1.2 必要条件
1.3 仕様
1.4 専門用語
2 表記の慣習と一般文法
2.1 拡張 BNF
2.2 基本的な規定
2.3 URL エンコーディング
3 スクリプトの呼び出し
3.1 サーバの責任
3.2 スクリプトの選択
3.3 Script-URI
3.4 実行
4 CGI リクエスト
4.1 リクエスト外部変数
4.1.1 AUTH_TYPE
4.1.2 CONTENT_LENGTH
4.1.3 CONTENT_TYPE
4.1.4 GATEWAY_INTERFACE
4.1.5 PATH_INFO
4.1.6 PATH_TRANSLATED
4.1.7 QUERY_STRING
4.1.8 REMOTE_ADDR
4.1.9 REMOTE_HOST
4.1.10 REMOTE_IDENT
4.1.11 REMOTE_USER
4.1.12 REQUEST_METHOD
4.1.13 SCRIPT_NAME
4.1.14 SERVER_NAME
4.1.15 SERVER_PORT
4.1.16 SERVER_PROTOCOL
4.1.17 SERVER_SOFTWARE
4.1.18 プロトコル特有の外部変数
4.2 リクエストメッセージボディ
4.3 リクエストメソッド
4.3.1 GET
4.3.2 POST
4.3.3 HEAD
4.3.4 プロトコル特有のメソッド
4.4 スクリプトコマンドライン
5 NPH スクリプト
5.1 識別
5.2 NPH レスポンス
6 CGI レスポンス
6.1 レスポンスの扱い
6.2 レスポンスタイプ
6.2.1 文書レスポンス
6.2.2 ローカルリダイレクトレスポンス
6.2.3 クライアントリダイレクトレスポンス
6.2.4 文書を伴うクライアントリダイレクトレスポンス
6.3 レスポンスヘッダフィールド
6.3.1 Content-Type
6.3.2 Location
6.3.3 Status
6.3.4 プロトコル特有のヘッダフィールド
6.3.5 拡張ヘッダフィールド
6.4 レスポンスメッセージボディ
7 システム仕様
7.1 AmigaDOS
7.2 UNIX
7.3 EBCDIC/POSIX
8 実装
8.1 サーバについての推奨事項
8.2 スクリプトについての推奨事項
9 セキュリティについての考察
9.1 安全なメソッド
9.2 機密性の高い情報を含むヘッダフィールド
9.3 データのプライバシー
9.4 情報セキュリティモデル
9.5 スクリプトのサーバへの干渉
9.6 データ長とバッファリングについて
9.7 ステートレスな処理
9.8 相対的パス
9.9 Non-parsed Header の出力
10 謝辞
11 参照文献
11.1 規約の一部としての参照
11.2 情報提供としての参照
12 筆者のアドレス
13 著作権表示全文

1. 導入

1.1. 目的

Common Gateway Interface (CGI) [22] は、HTTP [1], [4] サーバや CGI スクリプトに、クライアントのリクエストに応答するための責任を共有させる。 クライアントのリクエストは、 Uniform Resource Identifier (URI) [11]、リクエストメソッド、及び転送プロトコルによって提供されるリクエストについての様々な付属的情報を含んでいる。

CGI は、クライアントのリクエストを説明するための、外部変数として知られる、抽象的なパラメータを定義する。 これは、具体的なプログラマインタフェースと共に、スクリプトと HTTP サーバ間のプラットフォームに依存しないインターフェースを規定する。

サーバは、クライアントのリクエストに関連する、接続、データ転送、転送、及びネットワーク上の問題の管理について責任を負うが、CGI スクリプトは、データアクセスや文書処理のような、アプリケーション上の問題を扱う。

1.2. 必要条件

この文書内の 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'MAY', 'OPTIONAL' 各キーワードは、BCP 14 である、 RFC 2119 [3] にて説明されるように解釈されるべきである。

それが実装するプロトコルの 一つ以上の 'must' 要件を満足しなければ、実装は適合しているとはいえない。 その特徴について、全ての 'must' と全ての 'should' 要件を満足する実装は、'無条件に適合' と呼ばれる; 一方、全ての 'must' 要件は満足するものの、全ての 'should' 要件は満足しないような実装は、'条件付適合' と呼ばれる。

1.3. 仕様

この仕様書の主となる部分で CGI の全ての機能や特性が定義されているわけではない。 規定されていない特性を説明するために、以下の語句が使用される:

'システム的に規定される {system-defined}'
この特性は、システム間では異なるかもしれないが、同じシステムを使用する別の実装では同じでなければならない。 システムは、通常オペレーティングシステムの種別を識別する。 いくつかのシステムは、この文書の section 7 にて定義されている。 新しいシステムは、この文書の改訂するのではなく、新しい仕様書によって定義されるであろう。
'実装的に規定される {implementation-defined}'
その機能の振る舞いは、実装毎に異なるであろう; そのため、個別の実装はその振る舞いを文書化しなければならない。

1.4. 専門用語

この仕様書では、HTTP/1.1 仕様書 [4] にて定義される多くの用語を使用する; しかし、以下の用語は、HTTP/1.1 仕様書における定義、あるいはその一般的な意味とは異なる意味で使用する。

'外部変数 {meta-variable}'
サーバからスクリプトへ情報を運ぶ名前付パラメータ。 多くの一般的な実装ではオペレーティングシステムの環境における変数であるが、そうである必要はない。
'スクリプト {script}'
このインターフェースに従いサーバによって呼び出されるソフトウェア。 単独のプログラムである必要はなく、動的に読み込まれたり共有されるライブラリ、あるいはサーバにおけるサブルーチンであってもよい。 'スクリプト' という語は、しばしば実行時に解釈される文の集合であるとされるが、そうである必要は無く、この仕様書の文脈においてこの用語はより広い定義を表す。
'サーバ {server}'
クライアントからのリクエストを処理するためにスクリプトを呼び出す応用プログラム。

2. 表記の慣習と一般文法

2.1. 拡張 BNF

この文書で規定されるメカニズムは全て、通常の文章、及び RFC 822 にて使用されるものに類似する拡張 Backus-Naur 形式 (BNF) によって記述される。 特に言及されなければ、要素は大文字小文字を区別する。 この拡張 BNF は、以下の構造を含む。

name = definition
規定の名前と定義は等号 ('=') によって区切られる。 空白は、定義の連続する行が字下げされる時にのみ意味を持つ。
"literal"
二重引用符 (") はリテラルテキストを括る。 但し、リテラルの引用符は、山括弧 ('<' と '>') によって括られる。
rule1 | rule2
選択的規定は、縦棒 ('|') によって分けられる。
(rule1 rule2 rule3)
丸括弧によって括られる要素は、単一の要素として扱われる。
*rule
アスタリスク ('*') を前に置く規定は、0 回以上の発生を表す。 完全形は 'n*m rule' であり、これはその規定が最低 n 回、最高 m 回発生する事を示す。 n と m は省略可能な十進数値で、デフォルトの値はそれぞれ 0 と無限大である。
[rule]
角括弧 ('[' と ']') によって括られる要素は選択可能であり、'*1 rule' と等価である。
N rule
十進数値を前に置く規定は、その規定の厳密な N 回の発生を表す。 'N*N rule' と等価である。

2.2. 基本的な規定

この仕様書は、文字上では定義される BNF に類似する文法を使用する。 プロトコルによって許されるバイト列を定義するという多くの仕様書とは異なり、ここでの文法中の各リテラルはそれが表現する文字に対応する。 システム内でビット上あるいはバイト上それらの文字がどのように表されるかは、システム的に規定されるか、あるいは特定の文脈によって規定される。 唯一の例外は、規則 'OCTET' で、以下の定義される。

以下の規則は、基本的な構文解析構造を説明するためにこの仕様書を通じて使用される。

 alpha         = lowalpha | hialpha
 lowalpha      = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |
                 "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |
                 "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |
                 "y" | "z"
 hialpha       = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" |
                 "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" |
                 "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" |
                 "Y" | "Z"

 digit         = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
                 "8" | "9"
 alphanum      = alpha | digit
 OCTET         = <any 8-bit byte>
 CHAR          = alpha | digit | separator | "!" | "#" | "$" |
                 "%" | "&" | "'" | "*" | "+" | "-" | "." | "`" |
                 "^" | "_" | "{" | "|" | "}" | "~" | CTL
 CTL           = <any control character>
 SP            = <space character>
 HT            = <horizontal tab character>
 NL            = <newline>
 LWSP          = SP | HT | NL
 separator     = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" |
                 "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" |
                 "}" | SP | HT
 token         = 1*<any CHAR except CTLs or separators>
 quoted-string = <"> *qdtext <">
 qdtext        = <any CHAR except <"> and CTLs but including LWSP>
 TEXT          = <any printable character>

改行 (NL) は、単一の制御文字である必要はなく、制御文字の連続するもの {sequence} であってもよい。 システムは、TEXT を <CTL を除くが、 LWSP を含む任意の CHAR> よりも大きな文字集合であると定義する事ができる

2.3. URL エンコーディング

ここで使用される変数や構造のいくつかは、'URL エンコードされ' ているとして説明される。 このエンコーディングは、RFC 2396 [2] の section 2 にて説明される。 URL エンコードされた文字列において、エスケープされる文字列はパーセント文字 ("%") と二つの 16 進数字から成り、この二つの 16 進数字が 1 つのオクテットを形成する。 エスケープされる文字列は、もしその中に US-ASCII [9] コード文字集合内のコードであるオクテットが存在すれば、その図形文字を表す。 現在、どの文字集合が非 ASCII コードを表現するかを識別するための URI 構文内での規定がないので、 CGI は場当たり的 {ad-hoc} にこの問題を扱う。

いくつかの安全でない (予約) 文字は、エンコードされると異なる意味を持つかもしれない事に注意せよ。 どの文字が安全でないかの定義は文脈に依存する; 正式な扱いについては、RFC 2732 [7] によって更新されているが、RFC 2396 [2] の section 2 を参照。 これら予約文字は、例えばフィールド分割のように、通常文字列に構文上の構造を規定するために使用される。 全ての場合において、その文字列は存在するあらゆる予約文字に関して最初に処理され、そこから得られたデータを "%" エスケープされる文字列をそれに対応する文字値で置き換える事によって、URL デコードされる事になっている。

文字列をエンコードするためには、全ての予約文字と禁止文字を対応する "%" エスケープされる文字列に置き換える。 その後、その文字列は URI を組み立てるために使用する事ができる。 予約文字は文脈によって変わるであろうが、常に以下の集合から引き出される:

 reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" |
            "," | "[" | "]"

最後の二つの文字は RFC 2732 [7] にて追加された。 いかなる文脈においても、これらの文字の部分集合が予約されるであろう; すなわち、この集合内のその他の文字は、その文脈で文字列が URL エンコードされる時にはエンコードされてはならない。 URL 構文を記述するために使用されるその他の基本規則は:

 hex        = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b"
              | "c" | "d" | "e" | "f"
 escaped    = "%" hex hex
 unreserved = alpha | digit | mark
 mark       = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"

3. スクリプトの呼び出し

3.1. サーバの責任

サーバは、アプリケーションゲートウェイのように振る舞う。 サーバは、クライアントからリクエストを受け取り、そのリクエストを扱う CGI スクリプトを選択し、クライアントのリクエストを CGI リクエストに変換し、スクリプトを実行し、 CGI レスポンスをクライアントへのレスポンスに変換する。 クライアントリクエストを処理する時、サーバにはあらゆるプロトコルやトランスポート層レベルでの認証やセキュリティを実装する責任がある。 また、サーバは、'透過的でない' 方法で、例えばメディアタイプ変換やプロトコルのダウングレードのような、更なる追加的サービスを提供するためにリクエストやレスポンスを修正するようにしてもよい

サーバは、この仕様書によって要求されるようにクライアント要求データへの翻訳やプロトコル変換を行わなければならない。 更に、サーバは、例えその CGI スクリプトがこの仕様書に適合しなくても、関係するネットワークプロトコルには適合するという事をクライアントに対して責任を負う。

サーバがリクエストへ認証を適用する場合、そのリクエストが定義される全てのアクセス制御を通過しなければ、サーバはそのスクリプトを実行してはならない

3.2. スクリプトの選択

サーバは、クライアントにより与えられる一般形式の URI に基づいて、CGI によって実行されるスクリプトがどれかを決定する。 この URI は、"/" によって分けられる構成要素を伴う階層的なパスを含む。 どんな特定のリクエストについても、サーバは個別のスクリプトが持つこのパスの全てあるいはその先頭部分を識別し、そのスクリプトをパス階層における特定の位置に配置するであろう。 パスに残りの部分がある場合、それはスクリプトによって解釈されるリソース、あるいはサブリソースの識別子になる。

このパスの分割についての情報は、後述する、外部変数としてスクリプトから利用できる。 非階層的な URI スキームのサポートは、この仕様書の範囲外である。

3.3. Script-URI

クライアントのリクエスト URI からのスクリプトの選択のマッピングは、特定のサーバの実装とその設定によって定義される。 サーバは、そのスクリプトがいくつかの異なる URI パス階層の集合によって識別されるようにしてもよく、 その場合、外部変数の処理や生成の間は、その URI をこの集合の他のものに置き換える事が許される。 サーバは

  1. 特定のクライアントリクエストにおける URI を維持してもよい; あるいは
  2. 各スクリプトが取り得る URI の集合の中から標準形 URI を選択してもよい; あるいは
  3. その集合から URI の他の選択を実装する事ができる。

このようにして生成された外部変数から、'Script-URI' と呼ばれる、URI は構築されるであろう。 これは、クライアントが代わりにこの URI にアクセスした場合、そのスクリプトが SCRIPT_NAME, PATH_INFO, QUERY_STRING 外部変数について同じ値を持って実行されるであろうという特性を持たなければならない。 Script-URI は、RFC 2396 [2] の section 3 にて定義されるような一般 URI の構造を持つが、オブジェクトパラメータとフラグメント識別子は許されない。 Script-URI の各構成要素は、いくつかの外部変数によって定義される (以下参照);

 script-URI = <scheme> "://" <server-name> ":" <server-port>
              <script-path> <extra-path> "?" <query-string>

ここで、<scheme> は SERVER_PROTOCOL から見つけられ、<server-name>, <server-port>, <query-string> はそれぞれの外部変数の値である。 ";", "=", "?" 各予約文字を URL エンコードした SCRIPT_NAME と PATH_INFO の値は、<script-path> と <extra-path> になる。

PATH_INFO 外部変数についての更なる情報は、section 4.1.5 を参照。

scheme とプロトコルは、scheme はアプリケーションプロトコルに加えてアクセス方法も識別するという意味において、同一ではない。 例えば、トランスポート層セキュリティ (TLS: Transport Layer Security) [14] を用いてアクセスされるリソースは、HTTP プロトコル [19] を使用する場合、https という scheme を持つリクエスト URI になるだろう。 CGI/1.1 はスクリプトが scheme を再構成する一般的な方法を提供していないので、定義される Script-URI は使用される基底プロトコルを含む事になる。 しかし、スクリプトは URI scheme をよりよく推定するために scheme 特有な外部変数を使用する事ができる

また、この定義によって、URI は、適切な構成要素を修正する事によって、path-info や query-string について任意の許される値を持つスクリプトを呼び出すように構成されうるという事にも注意せよ。

3.4. 実行

スクリプトは、システム的に規定される方法をもって呼び出される。 他で規定されていなければ、スクリプトを含むファイルは実行可能なプログラムとして呼び出されるであろう。 サーバは section 4 にて記述されるな CGI リクエストを準備する; ここにはリクエスト外部変数 (実行時はスクリプトで直ちに利用可能) とリクエストメッセージデータを含む。 リクエストデータは、スクリプトで直ちに利用可能である必要はない; スクリプトはサーバがクライアントから全てのデータを受信する前に実行され得る。 スクリプトからのレスポンスは、section 56 にて記述されるように、サーバへ返される。

エラー状況の場合には、サーバはいつでも警告なしにスクリプトの実行を中断あるいは終了できる。 これは、例えば、サーバとクライアント間での転送の失敗という場合がある; そのため、スクリプトは異常終了を処理するための用意をすべきである

4. CGI リクエスト

リクエストについての情報は二つの異なる情報源から来る; すなわち、リクエスト外部変数と任意の関連する message-body である。

4.1. リクエスト外部変数

外部変数は、サーバからスクリプトへ渡されるリクエストについてのデータを含み、システム的に規定される方法をもってスクリプトによってアクセスされる。 外部変数は、大文字・小文字を区別しない名前によって識別される; すなわち、二つの異なる変数においてその名前の大文字・小文字のみが異なるものはありえない。 ここでは、大文字と下線 ("_") の正式な表現を使用してそれらを示す。 特定のシステムでは、異なる表現を定義する事ができる。

 meta-variable-name = "AUTH_TYPE" | "CONTENT_LENGTH" |
                      "CONTENT_TYPE" | "GATEWAY_INTERFACE" |
                      "PATH_INFO" | "PATH_TRANSLATED" |
                      "QUERY_STRING" | "REMOTE_ADDR" |
                      "REMOTE_HOST" | "REMOTE_IDENT" |
                      "REMOTE_USER" | "REQUEST_METHOD" |
                      "SCRIPT_NAME" | "SERVER_NAME" |
                      "SERVER_PORT" | "SERVER_PROTOCOL" |
                      "SERVER_SOFTWARE" | scheme |
                      protocol-var-name | extension-var-name
 protocol-var-name  = ( protocol | scheme ) "_" var-name
 scheme             = alpha *( alpha | digit | "+" | "-" | "." )
 var-name           = token
 extension-var-name = token

scheme と同じ名前の外部変数、そしてプロトコルあるいは scheme の名前で始まる名前 (例えば、HTTP_ACCEPT) も定義される。 このような変数の数と意味は、この仕様書とは無関係に変化するであろう。 (section 4.1.18 も参照)

サーバは、実装的に規定される拡張外部変数を追加的に設定する事ができるが、その名前は先頭に "X_" をつけるべきである

この仕様書は、長さゼロ (NULL) の値と値なしを区別しない。 例えば、二つのリクエスト http://host/script と http://host/script? は共に QUERY_STRING 外部変数が NULL になるため、スクリプトはこれらを区別する事ができない。

 meta-variable-value = "" | 1*<TEXT, CHAR or tokens of value>

省略可能な外部変数は、その値が NULL の場合、省略して (設定しないでおいて) もよい。 外部変数の値は、他に言及されていなければ、大文字・小文字を区別するとみなされなければならない。 外部変数における文字の表現はシステム的に規定される; すなわち、サーバはそれらの値をその対応する表現に変換しなければならない

4.1.1. AUTH_TYPE

AUTH_TYPE 変数は、ユーザを認証するためにサーバによって使用されるメカニズムを識別する。 ここには、クライアントのプロトコルやサーバの実装によって定義される大文字・小文字を区別しない値を含む。

HTTP において、クライアントのリクエストが外部のアクセスについての認証を要求する場合、サーバはこの変数の値をリクエストの Authorization ヘッダフィールド内の 'auth-scheme' トークンから設定しなければならない

 AUTH_TYPE      = "" | auth-scheme
 auth-scheme    = "Basic" | "Digest" | extension-auth
 extension-auth = token

HTTP アクセス認証スキームは、RFC 2617 [5] にて記述される。:

4.1.2. CONTENT_LENGTH

CONTENT_LENGTH 変数は、リクエストが message-body を持つ場合、オクテットの十進数でそのサイズを含む。 データが付加されていなければ、 NULL (あるいは未設定) である。

 CONTENT_LENGTH = "" | 1*digit

サーバは、リクエストが message-body エンティティが伴っている場合にのみ、この外部変数を設定しなければならない。 CONTENT_LENGTH 値は、サーバが任意の転送コーディングや内容コーディングを取り除いた後、message-body の長さを反映しなければならない。

4.1.3. CONTENT_TYPE

リクエストが message-body を含む場合、CONTENT_TYPE 変数は message-body のインターネットメディアタイプ [6] を設定する。

 CONTENT_TYPE = "" | media-type
 media-type   = type "/" subtype *( ";" parameter )
 type         = token
 subtype      = token
 parameter    = attribute "=" value
 attribute    = token
 value        = token | quoted-string

type, subtype, parameter 属性名は大文字・小文字を区別しない。 parameter の値は、大文字・小文字を区別するかもしれない。 HTTP におけるメディアタイプとその使用法は、HTTP/1.1 仕様書 [4] の section 3.7 にて記述される。

この変数のための既定値はない。 この変数が設定されていない場合にのみ、スクリプトは受信されるデータのメディアタイプを決定しようとしてもよい。 タイプが未知のままの場合、スクリプトは application/octet-stream というタイプだとみなしてもよいし、あるいは (section 6.3.3 にて記述されるように) エラーをもってそのリクエストを拒否してもよい

各メディアタイプは、任意なパラメータと必須なパラメータの集合を定義する。 これは、message-body をコード化する文字セットを定義している、大文字・小文字を区別しない値を持つ charset パラメータを含むかもしれない。 charset パラメータが省略される場合、既定値は最初に以下の規則のいずれかを適用する事によって生成されるべきである:

  1. いくつかのメディアタイプでは、システム的に規定される既定の文字セットが存在するかもしれない
  2. "text" というメディアタイプの既定値は、ISO-8859-1 [4] である。
  3. そのメディアタイプの仕様書にて定義される既定値。
  4. 既定値は US-ASCII である。

サーバは、HTTP Content-Type フィールドがクライアントリクエストヘッダ内に存在する場合は、この外部変数を設定しなければならない。 サーバは、エンティティが付加されており Content-Type ヘッダフィールドのないリクエストを受信した場合は、正しい内容タイプを決定しようとしてもよいが、そうでなければこの外部変数は省略すべきである。

4.1.4. GATEWAY_INTERFACE

GATEWAY_INTERFACE 変数は、スクリプトを介して通信するサーバがによって使用されている CGI の能力{dialect} が設定されなければならない。 構文は:

 GATEWAY_INTERFACE = "CGI" "/" 1*digit "." 1*digit

メジャー番号とマイナー番号は分割された整数値として扱われるので、それぞれが複数桁になりうる事に注意せよ。 従って、CGI/2.4 は CGI/2.13 よりも下のバージョンで、さらにそれらは CGI/12.3 よりも下となる。 先行するゼロはスクリプトによって無視されなければならないし、またサーバによって生成されてはならない

この文書は、CGI インタフェースのバージョン 1.1 を定義する。

4.1.5. PATH_INFO

PATH_INFO 変数は、CGI スクリプトによって解釈されるパスを規定する。 これは CGI スクリプトによって返されるリソースあるいはリソースの一部を識別し、URI のパス階層のうちのスクリプト自身を識別する部分の後の部分に由来する。 URI のパスとは異なり、PATH_INFO は URL エンコードされず、パス要素{segment} の引数を含む事はできない。 "/" という PATH_INFO は、単一の空のパス要素{segment} を表す。

 PATH_INFO = "" | ( "/" path )
 path      = lsegment *( "/" lsegment )
 lsegment  = *lchar
 lchar     = <"/" を除く任意の TEXT か CTL>

値は、大文字・小文字を区別するとみなされ、サーバはリクエスト URI にあるようにパス経路の大文字・小文字を保持しなければならない。 サーバは、PATH_INFO についてどんな値が許されるについての制限を課してもよいし、好ましくないとみなす任意の値に遭遇した場合エラーをもってそのリクエストを拒否してもよい。 ここには、それがスクリプトへの情報の喪失を表すので、PATH_INFO 内でデコードされると "/" となるような任意のリクエストを含んでもよい。 同様に、パス内の非 US-ASCII 文字の扱いはシステム的に規定される。

URL エンコードされた PATH_INFO 文字列は、そのパスの SCRIPY_NAME 部分に続く Script-URI (section 3.3 参照) の更なるパス構成要素を形成する。

4.1.6. PATH_TRANSLATED

PATH_TRANSLATED 変数は、PATH_INFO 値を取得し、それ自身をローカル URI として構文解析し、サーバの文書レポジトリ構造にマッピングする事で適切に仮想的なものから物理的なものへの変換を実行することで得られる。 その結果で許される文字集合は、システム的に規定される。

 PATH_TRANSLATED = *<any character>

これは、以下についてのリクエストによってアクセスされるファイルの場所となり、

 <scheme> "://" <server-name> ":" <server-port> <extra-path>

ここで、<scheme> は元々のクライアントリクエストにおける scheme、<extra-path> は ";", "=", "?" 予約文字を含む、PATH_INFO を URI エンコードしたものである。 例えば、以下のようなリクエスト:

 http://somehost.com/cgi-bin/somescript/this%2eis%2epath%3binfo

は、PATH_INFO の値は以下のようなものになる。

 /this.is.the.path;info

内部的 URI は、schema, サーバの位置、URL エンコードされた PATH_INFO から構築される:

 http://somehost.com/this.is.the.path%3binfo

そして、これがサーバの文書レポジトリ内の位置に変換され、おそらく以下のようなファイルシステムパスとなる:

 /usr/local/www/htdocs/this.is.the.path;info

PATH_TRANSLATED の値は、この変換の結果である。

この値は、妥当なレポジトリ内の場所へとマッピングされるかどうかとは無関係にこの方法によって得られる。 サーバは、使用しているレポジトリが名前の大文字・小文字を区別しないものでなければ、extra-path 要素の大文字・小文字を保持しなければならない。 レポジトリが文書名に関してのみ大文字・小文字を区別する、保持する、あるいは問わないというものであれば、サーバは変換を通じて元の要素の大文字・小文字を保持する必要はない。

サーバが PATH_TRANSLATED を得るために使用する変換アルゴリズムは、実装的に規定される; この変数を使用する CGI スクリプトは、可搬性{portability} が制限される恐れがある。

サーバは、リクエスト URI が path-info 構成要素を含む場合、この外部変数を設定すべきである。 PATH_INFO が NULL の場合、PATH_TRANSLATED 変数も NULL に設定 (あるいは未設定と) しなければならない

4.1.7. QUERY_STRING

QUERY_STRING 変数は、URL エンコードされた検索用、あるいはパラメータ用文字列を含む; これは CGI スクリプトによって返される文書に作用する、あるいは変更するための情報を提供する。

検索文字列のための URL 構文は RFC 2396 [2] の section 3 にて記述される。 QUERY_STRING 値は、大文字・小文字を区別する。

 QUERY_STRING = query-string
 query-string = *uric
 uric         = reserved | unreserved | escaped

問い合わせ文字列を解析し、デコードする際、その解析の詳細や予約文字、非 US-ASCII 文字についてのサポートは、状況に依存する。 例えば、HTML 文書からのフォーム提出 [18] は、application/x-www-form-urlencoded 符号化を使用し、その場合は文字 "+", "&", "=" が予約されており、非 US-ASCII 文字については ISO 8859-1 エンコーディングが使用されているであろう。

QUERY_STRING 値は、Script-URI の query-string 部を提供する。 (section 3.3 参照)。

サーバはこの変数を設定しなければならない; もし Script-URI が問い合わせ構成要素を含んでいなければ、QUERY_STRING は空文字列 ("") として定義されなければならない

4.1.8. REMOTE_ADDR

REMOTE_ADDR 変数は、サーバへリクエストを送信しているクライアントのネットワークアドレスを設定しなければならない

 REMOTE_ADDR  = hostnumber
 hostnumber   = ipv4-address | ipv6-address
 ipv4-address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
 ipv6-address = hexpart [ ":" ipv4-address ]
 hexpart      = hexseq | ( [ hexseq ] "::" [ hexseq ] )
 hexseq       = 1*4hex *( ":" 1*4hex )

IPv6 アドレスの形式は、RFC 3513 [15] にて記述されている。

4.1.9. REMOTE_HOST

REMOTE_HOST 変数は、もしそれが存在すれば、そのリクエストをサーバに送信しているクライアントの完全修飾ドメイン名を、なければ NULL を含む。 完全修飾ドメイン名は、RFC 1034 [17] の section 3.5 や RFC 1123 [12] の section 2.1 に記述されるような形式を取る。 ドメイン名は、大文字・小文字を区別しない。

 REMOTE_HOST   = "" | hostname | hostnumber
 hostname      = *( domainlabel "." ) toplabel [ "." ]
 domainlabel   = alphanum [ *alphahypdigit alphanum ]
 toplabel      = alpha [ *alphahypdigit alphanum ]
 alphahypdigit = alphanum | "-"

サーバはこの変数を設定すべきである。 もしパフォーマンスやその他の理由のために hostname が利用できなければ、サーバは REMOTE_ADDR の値で代用してもよい

4.1.10. REMOTE_IDENT

REMOTE_IDENT 変数は、遠隔エージェントに対する RFC 1413 [20] リクエストによる接続について報告される識別情報があれば、これを提供するために使用する事ができる。 サーバは、この機能を提供しない、効率上の理由のためデータを要求しない、あるいは利用可能な識別データを返さない、のいずれかを選択する事ができる。

 REMOTE_IDENT = *TEXT

返されるデータは認証目的のために使用する事ができるが、その信頼度は最小限であるべきである。

4.1.11. REMOTE_USER

REMOTE_USER 変数は、ユーザ認証の一部としてクライアントによって供給されるユーザ識別用文字列を提供する。

 REMOTE_USER = *TEXT

クライアントリクエストが、HTTP 認証 [5] を要求した (例えば AUTH_TYPE 外部変数が "Basic" や "Digest" と設定されている) 場合は、REMOTE_USER 外部変数の値は供給されるユーザ ID に設定されなければならない

4.1.12. REQUEST_METHOD

外部変数 REQUEST_METHOD は、section 4.3 にて記述されるように、リクエストを処理するためにスクリプトによって使用されるべきメソッドが設定されなければならない

 REQUEST_METHOD   = method
 method           = "GET" | "POST" | "HEAD" | extension-method
 extension-method = "PUT" | "DELETE" | token

メソッドは、大文字・小文字を区別する。 HTTP メソッドは、HTTP/1.0 仕様書 [1] section 5.1.1 や HTTP/1.1 仕様書 [4] section 5.1.1 にて記述されている。

4.1.13. SCRIPT_NAME

SCRIPT_NAME 変数は、(スクリプトの出力ではなく) CGI スクリプトを識別できる (URL エンコードされていない) URL パスが設定されなければならない。 構文は PATH_INFO (section 4.1.5) と同じである。

 SCRIPT_NAME = "" | ( "/" path )

先頭の "/" はパスの一部ではない。 パスが NULL ならばこれは省略可能である; しかし、その場合でさえも、変数は設定されなければならない

SCRIPT_NAME 文字列は、実装的に規定されるある種の方法に由来する Script-URI のパス構成要素の先頭部分を形成する。 PATH_INFO 部分 (section 4.1.5 参照) は、SCRIPT_NAME 値には含まれない。

4.1.14. SERVER_NAME

SERVER_NAME 変数は、クライアントリクエストが向けられるサーバのホスト名が設定されなければならない。 この値は、大文字・小文字を区別しないホスト名、あるいはネットワークアドレスである。 これは、Script-URI のホスト部分を形成する。

 SERVER_NAME = server-name
 server-name = hostname | ipv4-address | ( "[" ipv6-address "]" )

複数の HTTP バーチャルホストが同じ IP 番地を共有していれば、設置されるサーバはこの変数の値を複数持ち得る。 その場合、サーバは正しいバーチャルホストを選択するためにリクエストの Host ヘッダフィールドの内容を使用する。

4.1.15. SERVER_PORT

SERVER_PORT 変数は、クライアントから受信されたこのリクエストにおける TCP/IP ポート番号が設定されなければならない。 この値は、Script-URI のポート部分に使用される。

 SERVER_PORT = server-port
 server-port = 1*digit

この変数は、たとえそのポートがその scheme についての既定のポートであり、URI から省略できる場合であっても、設定されなければならない事に注意せよ。

4.1.16. SERVER_PROTOCOL

SERVER_PROTOCOL 変数は、この CGI リクエストのために使用されるアプリケーションプロトコルの名前とバージョンが設定されなければならない。 これは、そのクライアントと通信するサーバによって使用されるプロトコルのバージョンと異なっていてもよい

 SERVER_PROTOCOL   = HTTP-Version | "INCLUDED" | extension-version
 HTTP-Version      = "HTTP" "/" 1*digit "." 1*digit
 extension-version = protocol [ "/" 1*digit "." 1*digit ]
 protocol          = token

ここで、'protocol' は、サーバとスクリプトの間で受け渡しされる情報 ('プロトコル的に規定される' 特性) のいくつかの構文を定義する。 これは、大文字・小文字を区別せず、通常は大文字で表される。 プロトコルは、スクリプト URI の scheme 部分とは異なり、サーバと通信するためにクライアントによって使用されるアクセスメカニズム全体を定義する。 例えば、"HTTP" のプロトコルをもってスクリプトに到達するリクエストは、"https" scheme を使用しているかもしれない。

サーバが使用できる SERVER_PROTOCOL についてよく知られている値はの1つは "INCLUDED" で、 これは 現在の文書がクライアントのリクエストの直接の対象ではなく、複合文書の一部として含まれているという事を示している。 スクリプトは、これを HTTP/1.0 リクエストとして扱うべきである。

4.1.17. SERVER_SOFTWARE

SERVER_SOFTWARE 外部変数は、CGI リクエストを作成している (またゲートウェイを運用している) サーバソフトウェアの名前とバージョンの情報が設定されなければならない。 これは、クライアントに報告されるサーバの説明がある場合、それと同じであるべきである

 SERVER_SOFTWARE = 1*( product | comment )
 product         = token [ "/" product-version ]
 product-version = token
 comment         = "(" *( ctext | comment ) ")"
 ctext           = <any TEXT excluding "(" and ")">

4.1.18. プロトコル特有な外部変数

サーバは、そのリクエストについてのプロトコルや scheme に特有の外部変数を設定すべきである。 プロトコル特有の変数の解釈は、SERVER_PROTOCOL 内のプロトコルバージョンに依存する。 サーバは、その scheme がそのプロトコルと同じでなければ、scheme の名前を持つ外部変数に NULL でない値を設定してもよい。 このような変数の有無は、そのリクエストでどの scheme が使用されているかをスクリプトに示す。

使用されているプロトコルが HTTP の場合、"HTTP_" で始まる名前を持つ外部変数はクライアントのリクエストヘッダフィールドから読み込んだ値を含む。 外部変数名は、HTTP ヘッダフィールド名が大文字に変換され、存在する全ての "-" を "_" に置換し、先頭に "HTTP_" が与えられたものとなる。 ヘッダデータは、クライアントによって送られる通りに表す事もできるし、あるいはその意味を変えないように書き換える事もできる。 同じ名前のフィールド名を持つ複数のヘッダフィールドを受信した場合、サーバは同じ意味を持つ単一の値に書き換えなければならない。 同様に、複数行にわたるヘッダフィールドは、単一の行に結合されなければならない。 サーバは、必要であれば、データの表現 (例えば、文字セット) を CGI 外部変数にとって適切なように変更しなければならない

サーバは、それが受信した全てのヘッダフィールドについての外部変数を作成する必要はない。 特に、例えば 'Authorization' のような、認証情報を転送する任意のヘッダフィールドや、あるいは、例えば 'Content-Length' や 'Content-Type' のような、他の変数からスクリプトにて利用可能なものは取り除くすべきである。 サーバは、'Connection' のような、クライアント側との通信上の点にのみ関係するようなヘッダフィールドは取り除いてもよい

4.2. リクエストメッセージボディ

リクエストデータは、システム的に規定される方法においてスクリプトによってアクセスされる; 他に定義されていなければ、これは '標準入力' のファイル記述子あるいはファイルハンドルを読み込む事によってなされるであろう。

 Request-Data   = [ request-body ] [ extension-data ]
 request-body   = <CONTENT_LENGTH>OCTET
 extension-data = *OCTET

request-body は、CONTENT_LENGTH が NULL でない場合に与えられる。 サーバは、少なくとも多くの量のバイト数がスクリプトが読み込むために利用できるようにしなければならない。 サーバは、 CONTENT_LENGTH バイト読み込まれた後にファイル末端{end-of-file} 状態を示してもよいし、あるいは拡張データを供給してもよい。 従って、スクリプトは、たとえ CONTENT_LENGTH バイト以上のデータが利用可能であっても、それ以上読もうとしてはならない。 しかし、任意のデータを読み込む事を義務付けられるわけではない。

ヘッダ非解析 (NPH: non-parsed header) スクリプト (section 5) において、サーバは スクリプトに供給されるデータがまさにクライアントに供給されるものであり、サーバによって変更されていないという事を保証しようとすべきである

転送コーディングは request-body においてはサポートされていないので、サーバは message-body からそれらのコーディングを取り除き、CONTENT_LENGTH を再計算しなければならない。 これが (例えば、大きなバッファについての要求によって) 不可能である場合、サーバはクライアントのリクエストを拒否すべきである。 また、サーバは message-body から内容コーディングを取り除いてもよい

4.3. リクエストメソッド

リクエストメソッドは、REQUEST_METHOD 外部変数として与えられるが、レスポンスを生成する際にスクリプトによって適用される処理の方法を識別する。 スクリプトの著者は、特定のアプリケーションについて最も適するようにそのメソッドを実装するという事を選択できる。 もしスクリプトが自身がサポートしないメソッドを持つリクエストを受信した場合、エラーとともにそれを拒否すべきである (section 6.3.3 参照)。

4.3.1. GET

GET メソッドは、スクリプトが外部変数の値に基づいて文書を生成すべきという事を示す。 慣例により、GET メソッドは '安全' かつ '冪等' であり、文書の生成以外の動作を行う事の意味を持つべきではない

GET メソッドの意味は、プロトコル特有の外部変数によって修正、あるいは再定義されるかもしれない。

4.3.2. POST

POST メソッドは、スクリプトが、外部変数に加えて、リクエストメッセージボディ内のデータに基づいて処理を行い文書を生成するように要求するために使用される。 一般的には HTML [18] におけるフォーム提出に使用され、例えばデータベース内の変更のような、恒久的な影響をもつスクリプトによって処理を開始されるという事が意図される。

スクリプトは、付加される message-body を読み込む前に CONTENT_LENGTH 変数の値をチェックしなければならないし、またそれを処理する前に CONTENT_TYPE 値をチェックすべきである

4.3.3. HEAD

HEAD メソッドは、スクリプトにレスポンスメッセージボディを供給する事なく、レスポンスヘッダフィールドを返すために十分な処理をする事を要求する。 スクリプトは、HEAD リクエストについてのレスポンスメッセージボディを供給してはならない。 もしそうなった場合、サーバはスクリプトからのレスポンスを読み込む時にその message-body を破棄しなければならない

4.3.4. プロトコル特有のメソッド

スクリプトは、HTTP/1.1 の PUT や DELETE のような、任意のプロトコル特有なメソッドを実装する事ができる; そうする時は、SERVER_PROTOCOL の値をチェックすべきである

サーバは、あるメソッドがスクリプトにとって適切ではない、あるいは認められないと決定する事ができるし、そのメソッドをサーバ自身で扱ってもよいし、クライアントにエラーとして返したりしてもよい。

4.4. スクリプトコマンドライン

いくつかのシステムでは、CGI スクリプトに文字列の配列を供給するための方法をサポートする。 これは、エンコードされていない "=" 文字が含まれない URI クエリ文字列による 'GET' あるいは 'HEAD' リクエストによって識別されるような、'索引付きの' HTTP 問い合わせの場合にのみ使用される。 そのようなリクエストにおいては、サーバは query-string を search-string として扱い、以下の規則に従って、その中の語を解析すべきである

 search-string = search-word *( "+" search-word )
 search-word   = 1*schar
 schar         = unreserved | escaped | xreserved
 xreserved     = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," |
                 "$"

解析後、各 search-word は URL デコードされ、場合によってはシステム的に規定される方法においてエンコードされ、そしてコマンドライン引数リストに加えられる。

サーバがどんな引数リストも生成できない場合、サーバはいかなるコマンドライン情報も生成してはならない。 例えば、引数の数がオペレーティング・システムやサーバの制限を超えている、あるいは語の一つが引数として表現できない、という場合である。

スクリプトは、QUERY_STRING 値がエンコードされていない "=" 文字を含むかどうかをチェックすべきであり、その場合コマンドライン引数を使用すべきではない

5. NPH スクリプト

5.1. 識別

サーバは、NPH (Non-Parsed Header) スクリプトをサポートする事ができる; これらは、サーバが負うレスポンス処理についての全ての責任を渡されたスクリプトである。

この仕様書では、NPH スクリプトがその出力データのみに基づいて識別されるようなメカニズムは提供しない。 慣例により、任意のスクリプトは一つの種類 (NPH か CGI) の出力のみしか提供できないので、そのスクリプト自身は 'NPH スクリプト' と表現される。 NPH をサポートするサーバは、おそらくスクリプトの名前や位置に基づいた、NPH スクリプトを識別するための実装的に規定されるメカニズムを提供しなければならない

5.2. NPH レスポンス

スクリプトがデータをサーバやクライアントに送り返すためのシステム的に規定される方法が存在しなければならない; すなわち、スクリプトは常に何らかのデータを返さなければならない。 そのように定義されなければ、それは従来の CGI スクリプトと同じあろう。

現在、NPH スクリプトは HTTP クライアントリクエストについてにのみ定義されている。 (HTTP) NPH スクリプトは、今のところ HTTP 仕様書 [1], [4] の section 6 にて記述されているように、完全な HTTP レスポンスメッセージを返さなければならない。 スクリプトは、レスポンスについて適切な書式を決定するために SERVER_PROTOCOL 変数を使用しなければならない。 また、スクリプトは、特定のプロトコル仕様書によって強制されているような、そのリクエストにおける任意の一般的の、あるいはプロトコル特有の外部変数に注意を払わなければならない

サーバは、スクリプトの出力がクライアントに修正されずに送られるという事を保証しなければならない。 これは、スクリプトがヘッダフィールドにおいて正しい文字セット (HTTP においては US-ASCII [9] や ISO 8859-1 [10] ) を使用する事を要求しているのであるという事に注意せよ。 サーバは、内部的に最小限のバッファリングとなるように、また転送部分ではバッファリングのないように、スクリプトの出力がクライアントに直接送られるという事を保証しようとすべきである

実装が他に定義をしなければ、スクリプトは自身のレスポンス中でクライアントが同じ接続上で更なるリクエストを送信できるという事を示してはならない

6. CGI レスポンス

6.1. レスポンスの扱い

スクリプトは常に空でないレスポンスを与えなければならないので、それがサーバにデータを送り返すためのシステム的に規定される方法がある。 他に定義されなければ、それは '標準出力' ファイル記述子を経由するであろう。

スクリプトは、リクエストを処理し、そのレスポンスを準備する際、REQUEST_METHOD 変数をチェックしなければならない

サーバは、データがスクリプトから受信されなければならないタイムアウト時間を実装する事ができる。 もしサーバ実装がタイムアウトを定義し、その間にスクリプトからデータを受信しなければ、サーバはそのスクリプト処理を終了してもよい

6.2. レスポンスタイプ

レスポンスは、message-header と message-body で構成され、空行によって分けられる。 message-header は一つ以上のヘッダフィールドを含む。 message-body は NULL でもよい。

 generic-response = 1*header-field NL [ response-body ]

スクリプトは、文書レスポンス、ローカルリダイレクトレスポンス、あるいはクライアントリダイレクト (文書を伴っても良い) レスポンスのいずれかを返さなければならない。 以下のレスポンス定義において、レスポンス中のヘッダフィールドの順序は (BNF ではそう見えたとしても) 重要ではない。 ヘッダフィールドは、section 6.3 にて定義される。

 CGI-Response = document-response | local-redir-response |
                client-redir-response | client-redirdoc-response

6.2.1. 文書レスポンス

CGI スクリプトは、文書レスポンスにおいてユーザに文書を返す事ができるが、この時レスポンスの成功状態を示すエラーコードを伴う事ができる。

 document-response = Content-Type [ Status ] *other-field NL
                     response-body

スクリプトは、Content-Type ヘッダフィールドを返さなければならない。 Status ヘッダフィールドは省略可能であり、省略された場合はステータス 200 'OK' とみなされる。 サーバは、スクリプトの出力がクライアントへのレスポンスがレスポンスプロトコルのバージョンを満たす事を保証するようにあらゆる適切な修正を施さなければならない

6.2.2. ローカルリダイレクトレスポンス

CGI スクリプトは、Location ヘッダフィールドにてローカルリソースについての URI パスと query-string ('local-pathquery') を返す事ができる。 これは、指定されたパスを使用してそのリクエストを再処理すべきであるという事をサーバに示す。

 local-redir-response = local-Location NL

スクリプトはいかなる他のヘッダフィールドも message-body も返してはならないし、 サーバは以下のような URL を含むリクエストへのレスポンスを生成する時と同じレスポンスを生成しなければならない

 scheme "://" server-name ":" server-port local-pathquery

6.2.3. クライアントリダイレクトレスポンス

CGI スクリプトは、クライアントに指定された URI を使用してそのリクエストを再処理すべきであるという事を示すために、Location ヘッダフィールドにて絶対 URI パスを返す事ができる。

 client-redir-response = client-Location *extension-field NL

スクリプトは、サーバ的に規定される CGI 拡張ヘッダを除く、いかなるヘッダフィールドも提供してはならない。 HTTP クライアントのリクエストについて、サーバは 302 'Found' HTTP レスポンスメッセージを生成しなければならない

6.2.4. 文書を伴うクライアントリダイレクトレスポンス

CGI スクリプトは、クライアントに指定された URI を使用してそのリクエストを再処理すべきであるという事を示すために、Location ヘッダフィールドにて絶対 URI パスを返し、かつ文書を伴う事ができる。

 client-redirdoc-response = client-Location Status Content-Type
                            *other-field NL response-body

ここでは 302 'Found' のステータスコードを含む Status ヘッダフィールドは必ず与えられなければならないが、クライアントリダイレクトを意味する他の妥当なステータスコードである extension-code を含む事ができる。 サーバは、スクリプトの出力がクライアントへのレスポンスがレスポンスプロトコルのバージョンを満たす事を保証するようにあらゆる適切な修正を施さなければならない

6.3. レスポンスヘッダフィールド

レスポンスヘッダフィールドは、サーバによって解釈される CGI ヘッダフィールドや拡張ヘッダフィールド、あるいはクライアントに返されるレスポンスに含まれるプロトコル特有のヘッダフィールドのいずれかである。 少なくとも一つ CGI フィールドが与えられなければならない; しかし、各 CGI フィールドはそのレスポンス中に複数現れてはならない。 レスポンスヘッダフィールドは、以下の構文を持つ:

 header-field    = CGI-field | other-field
 CGI-field       = Content-Type | Location | Status
 other-field     = protocol-field | extension-field
 protocol-field  = generic-field
 extension-field = generic-field
 generic-field   = field-name ":" [ field-value ] NL
 field-name      = token
 field-value     = *( field-content | LWSP )
 field-content   = *( token | separator | quoted-string )

field-name は、大文字・小文字を区別しない。 NULL フィールド値は、送信されていないフィールドと等価である。 CGI-Response 中の各ヘッダフィールドは単一行で指定されなければならない事に注意せよ; CGI/1.1 は連続する行をサポートしない。 空白は、 ":" と field-value の間と field-value 内の token 間で認められる (但し field-name と ":" 間では認められない)。

6.3.1. Content-Type

Content-Type レスポンスフィールドは、エンティティボディののインターネットメディアタイプ [6] を設定する。

 Content-Type = "Content-Type:" media-type NL

エンティティボディが返される場合、スクリプトはレスポンス中に Content-Type フィールドを与えなければならない。 そうされなければ、サーバは正しい内容タイプを決定しようとすべきではない。 この値は、任意の charset 引数の変更を除き、修正されずにクライアントに送信されるべきである

他にシステム的に規定されなければ、text メディアタイプについてクライアントに仮定される既定文字セットは、そのプロトコルが HTTP ならば ISO-8859-1 であり、それ以外では US-ASCII である。 故にスクリプトは、charset 引数を含めるべきである。 この点についての議論は、HTTP/1.1 仕様書 [4] の section 3.4.1 を参照。

6.3.2. Location

Location ヘッダフィールドは、そのスクリプトが実際の文書ではなく文書への参照を返している (section 6.2.36.2.4 を参照) という事をサーバに示すために使用される。 その参照は、クライアントがその参照される文書を取ってくるという事を示す、(fragment 識別子を伴い得る) 絶対 URI か、あるいは、サーバがその参照される文書を取ってきてレスポンスとしてクライアントに返すという事を示す、(fragment 識別子を伴い得る) ローカル URI パスである。

 Location        = local-Location | client-Location
 client-Location = "Location:" fragment-URI NL
 local-Location  = "Location:" local-pathquery NL
 fragment-URI    = absoluteURI [ "#" fragment ]
 fragment        = *uric
 local-pathquery = abs-path [ "?" query-string ]
 abs-path        = "/" path-segments
 path-segments   = segment *( "/" segment )
 segment         = *pchar
 pchar           = unreserved | escaped | extra
 extra           = ":" | "@" | "&" | "=" | "+" | "$" | ","

absoluteURI の構文は、 RFC 2396 [2] と RFC 2732 [7] 内に規定されるものをこの文書に組み入れた。 妥当な absoluteURI は、英文字で始まり、英数字, "+", "-", "." のいずれかが連なる scheme 名で始まり、":"; が続く。 ローカル URI パスやクエリは、絶対パスでなければならず、相対パスや NULL であってはならないので、"/" から始まらなければならない。

リクエスト (例えば POST リクエスト) に付加される message-body はリダイレクトの対象であるリソースとしては利用できないかもしれないという事に注意せよ。

6.3.3. Status

Status ヘッダフィールドは、そのリクエストを処理しようするスクリプトの試みの成功度合いを示す 3 桁の整数結果コードを含む。

 Status         = "Status:" status-code SP reason-phrase NL
 status-code    = "200" | "302" | "400" | "501" | extension-code
 extension-code = 3digit
 reason-phrase  = *TEXT

ステータスコード 200 'OK' は成功を表し、文書レスポンスにおいて仮定される既定値である。 ステータスコード 302 'Found' は、Location ヘッダフィールド及びレスポンス message-body を伴い使用される。 ステータスコード 400 'Bad Request' は、例えば CONTENT_TYPE が無いような、未知のリクエストフォーマットのために使用する事ができる。 ステータスコード 501 'Not Implemented' は、スクリプトがサポートしない REQUEST_METHOD を受信した場合にそれを返す事ができる。

他の妥当なステータスコードは、HTTP 仕様書 [1], [4] の section 6.1.1 や、IANA HTTP ステータスコードレジストリ [8] にて列挙され、上に列挙されたものに加えて、あるいはその代わりに使用する事ができる。 スクリプトは、HTTP/1.1 ステータスコードを使用する前に SERVER_PROTOCOL の値をチェックすべきである。 スクリプトは、 サポートしていないメソッドを使用してな行われた HTTP/1.1 リクエストを 405 'Method Not Allowed' エラーをもって拒否する事ができる

エラーステータスコードを返す事がスクリプト自身におけるエラー状態を意味する必要はないという事に注意せよ。 例えば、サーバによってエラー処理として呼び出されたスクリプトはサーバのエラー状態にふさわしいコードを返すべきである。

reason-phrase は、人間のためにクライアントに返される逐語的なエラーの説明である。

6.3.4. プロトコル特有のヘッダフィールド

スクリプトは、SERVER_PROTOCOL (HTTP/1.0 [1] か HTTP/1.1 [4]) の仕様書によって定義されるレスポンスメッセージに関係する任意の他のヘッダフィールドを返す事ができる。 CGI ヘッダの構文と HTTP ヘッダの構文が異なる場合、 サーバはそのデータを変換しなければならない。 例えば、 CGI スクリプトによって使用される改行の文字列 (例えば UNIX の US-ASCII LF) は、HTTP によって使用されるもの (US-ASCII の CR と LF) と同じでないかもしれない。

スクリプトは、クライアント側の通信に関係し、そしてそのクライアントにレスポンスを送るためのサーバの能力に影響し得るようないかなるヘッダフィールドも返してはならない。 サーバは、クライアントによって返されたそのようなヘッダフィールドを削除してもよい。 サーバは、スクリプトによって返されるヘッダフィールドと自身が本来送信するであろうヘッダフィールドとの衝突を解決すべきである

6.3.5. 拡張ヘッダフィールド

実装的に規定される CGI ヘッダフィールドを追加する事ができるが、そのフィールド名は "X-CGI-" で始めるべきである。 サーバは、スクリプトから受信される "X-CGI-" で始まる名前の認識できないあらゆるヘッダフィールドも無視する (そして削除する) 事ができる

6.4. レスポンスメッセージボディ

レスポンスメッセージボディは、サーバによってクライアントに返される付属文書である。 サーバは、スクリプトがファイル末端を通じて message-body の終端を知らせるまで、スクリプトによって提供される全てのデータを読み込まなければならない。 message-body は、HEAD リクエスト、あるいはあらゆる要求された転送コーディング、内容コーディング、文字セット変換を除き、修正されずにクライアントに送信されるべきである

 response-body = *OCTET

7. システム仕様

7.1. AmigaDOS

外部変数
外部変数は、同一に名付けられた環境変数にてスクリプトに渡される。 これらへは、DOS ライブラリルーチン GetVar() によってアクセスされる。 flags 引数は 0 とすべきである。 大文字・小文字は区別されないが、区別するシステムとの互換性のために大文字が推奨される。
その時点の作業ディレクトリ
スクリプトのその時点の作業ディレクトリは、スクリプトを含むディレクトリに設定される。
文字セット
外部変数、ヘッダフィールド、値の定義には US-ASCII 文字セット [9] が使用される; 改行 (NL) 文字列は LF である; しかし、サーバは CR LF も改行として受け入れるべきである

7.2. UNIX

UNIX 互換の OS については、以下が定義される:

外部変数
外部変数は、同一に名付けられた環境変数にてスクリプトに渡される。 これらへは、C ライブラリルーチン getenv() やそれに関する変数によってアクセスされる。
コマンドライン
これは main() の argc や argv 引数を使用する事でアクセスされる。 その語は、バックスラッシュでエスケープされる Bourne Shell における 'active' であるあらゆる文字である。
その時点の作業ディレクトリ
スクリプトについてのその時点の作業ディレクトリは、そのスクリプトを含むディレクトリに設定されるべきである
文字セット
外部変数、ヘッダフィールド、CHAR 値の定義には、NUL 値を除き、US-ASCII 文字セット [9] が使用される; TEXT 値は ISO-8859-1 を使用する。 PATH_TRANSLATED 値は NUL を除くあらゆる 8-bit バイトを含み得る。 改行 (NL) 文字列は LF である; しかし、サーバは CR LF も改行として受け入れるべきである

7.3. EBCDIC/POSIX

EBCDIC 文字セットを使用する POSIX 互換 OS については、以下が定義される:

外部変数
外部変数は、同一に名付けられた環境変数にてスクリプトに渡される。 これらへは、C ライブラリルーチン getenv() によってアクセスされる。
コマンドライン
これは main() の argc や argv 引数を使用する事でアクセスされる。 その語は、バックスラッシュでエスケープされる Bourne Shell における 'active' であるあらゆる文字である。
その時点の作業ディレクトリ
スクリプトについてのその時点の作業ディレクトリは、そのスクリプトを含むディレクトリに設定されるべきである
文字セット
外部変数、ヘッダフィールド、値、TEXT 文字列、PATH_TRANSLATED 値の定義には、NUL 値を除き、IBM1047 文字セット [21] が使用される。 改行 (NL) 文字列は LF である; しかし、サーバは CR LF も改行として受け入れるべきである
メディアタイプ文字セットの既定値
テキスト (や他の実装的に規定される) メディアタイプの文字セットの既定値は、IBM1047 である。

8. 実装

8.1. サーバについての推奨事項

サーバと CGI スクリプトは URL パス (それぞれ、クライアント URL と PATH_INFO データ) の扱いが一貫している必要はないが、サーバの作者は一貫性を持たせたいと願うかもしれない。 そのため、サーバ実装は以下の場合についてその振る舞いを規定すべきである:

  1. パス要素で認められる制約条件、特に末端でないところでの NULL 断片が許されるかどうかの定義;
  2. "." や ".." パス要素についての振る舞いの定義; すなわち、これらは禁止されるのか、普通のパス要素として扱われるのか、あるいは相対的 URL の仕様書 [2] の通りに解釈されるのか;
  3. パスや検索文字列の長さの限界や、サーバが解析できるヘッダフィールドの量の限界を含む、実装の限界の定義。

8.2. スクリプトについての推奨事項

スクリプトが PATH_INFO データを処理するつもりでない場合、PATH_INFO が NULL でなければ、404 Not Found をもってそのリクエストを拒否すべきである。

フォームの出力が処理される場合は、CONTENT_TYPE が "application/x-www-form-urlencoded" [18] か "multipart/form-data" [16] である事をチェックせよ。 CONTENT_TYPE が空白の場合、そのプロトコルによってサポートされていれば、スクリプトは 415 'Unsupported Media Type' エラーをもってそのリクエストを拒否できる。

スクリプトは、PATH_INFO, PATH_TRANSLATED, SCRIPT_NAME を解析する時、空のパス要素 ("//") や特別なパス要素 ("." や "..") に注意すべきである。 OS システム呼出しにて使用する前にパスからこれらを取り除くか、404 'Not Found' をもってそのリクエストを拒否すべきである。

スクリプトは、ヘッダフィールドを返す時、どんな HTTP ヘッダフィールドよりも前に、できるだけすぐに CGI ヘッダフィールドを返そうとすべきである。 それによって、サーバメモリ要求量を減らす助けとなろう。

スクリプトの作者は、REMOTE_ADDR や REMOTE_HOST 外部変数 (section 4.1.84.1.9 を参照) がそのリクエストの最終的な根源ではないかもしれないという事に注意すべきである。 それらは、サーバへ直接リクエストしたクライアントを識別する; すなわち、そのクライアントは実際の根源のクライアントの代わりに動作するプロクシやゲートウェイ、あるいはその他の中継者である。

9. セキュリティについての考察

9.1. 安全なメソッド

HTTP 仕様書 [1], [4] のセキュリティについての考察で議論されるように、GET と HEAD のメソッドは '安全' かつ '冪等' である (繰り返されるリクエストは単一のリクエストと同じ効果を持つ) べきであるいう慣例が確立されている。

9.2. 機密性の高い情報を含むヘッダフィールド

HTTP ヘッダフィールドの中には、明示的にサーバがそれをスクリプトに渡すように設定していなければ、そうすべきではない機密性の高い情報を転送するものがあるかもしれない。 例えば、サーバが基本認証方式を使用する事によってスクリプトを保護するならば、クライアントはユーザ名とパスワードを含む Authorization ヘッダフィールドを送るであろう。 サーバがこの情報を検証するのだから、十分注意なしに HTTP_AUTHORIZATION 外部変数経由でパスワードを渡すべきではない。 また、これは Proxy-Authorization ヘッダフィールドと対応する HTTP_PROXY_AUTHORIZATION 外部変数にも当てはまる。

9.3. データのプライバシー

リクエスト内の機密データは POST リクエストの一部として message-body 内に置かれるべきであり、URI やメッセージヘッダ内に置かれるべきではない。 システムによっては、スクリプトに外部変数を渡す環境が他のスクリプトやユーザから見えるかもしれない。 加えて、多くの既存のサーバやプロクシ、クライアントは、第三者から見られる所に URI を永続的に記録しているであろう。

9.4. 情報セキュリティモデル

TLS を使用するクライアント接続について、そのセキュリティモデルはクライアントとサーバ間では適用されるが、クライアントとスクリプト間では適用されない。 TLS セッションを扱うのはサーバの責任であって、従ってクライアントに認証されるのはサーバであり、 CGI スクリプトではない。

この仕様書は、スクリプトがそれを呼び出したサーバを認証するためのメカニズムを提供しない。 CGI リクエストやレスポンス上の整合性も強制されない。

9.5. スクリプトのサーバへの干渉

多くの一般的な CGI の実装は、サーバプロセスと同じユーザとグループを使っている子プロセスとしてスクリプトを呼び出す。 従って、スクリプトはサーバプロセス、その設定ファイル、文書ファイル、あるいはログファイルに干渉できないという事を保証すべきである。

スクリプトが、(コンパイル時あるいは実行時に)サーバソフトウェア内部にリンクされる関数を呼び出す事によって実行される場合、 サーバのコアメモリを守る、あるいは信頼できないコードは実行できないようにするといった予防措置がとられるべきである。

9.6. データ長とバッファリングについて

この仕様書では、スクリプトに与えられる message-body の長さに制限を設けていない。 スクリプトは、どんなサイズの静的に割り当てられたバッファも提出されたもの全体を一度に含むのに十分であると仮定すべきではない。 オーバーフローチェックの心配をせずに固定長バッファ使用すると、攻撃者に基本システムの 'スタック破壊' や 'スタックオーバーフロー' 脆弱性を突かれる事になるかもしれない。 スクリプトは、大きな投稿をディスクやその他のバッファリングメディアに溜める事ができるが、大きな投稿の迅速な成功によってサービス拒否状態を引き起こすかもしれない。 もし message-body の CONTENT_LENGTH がリソースに許されると考えられるものよりも大きければ、スクリプトはそのプロトコルバージョンに応じたエラーステータスをもって応答すべきである; 利用可能であろうステータスコードには、503 'Service Unavailable' (HTTP/1.0 と HTTP/1.1), 413 'Request Entity Too Large' (HTTP/1.1), 414 'Request-URI Too Large' (HTTP/1.1) が含まれる。

同様の問題は、スクリプトからの CGI レスポンスのサーバの扱いにも当てはまる。 スクリプトによって返されるヘッダや message-body の長さには制限はない; 従って、サーバはどんなサイズの静的に割り当てられたバッファもレスポンス全体を含むのに十分であると仮定すべきではない。

9.7. ステートレスな処理

Web のステートレスな性質は、複数のリクエストが概念的に単一の Web 通信を構成する時でさえ、各スクリプトの実行やリソースの取得を全て独立なものにしてしまう。 このため、スクリプトはリクエストを提出するユーザエージェントの文脈についていかなる仮定もすべきではない。 特に、スクリプトは他のアプリケーションやコマンド、あるいは OS のサービスへの入力のような機密性の高い目的にそれらを適用する前に、クライアントから得られたデータを検査し、形式も内容も妥当であるかを検証すべきである。 それらの使用はシステムコールへの引数、データベースへの書き込み、動的に評価実行される{evaluated} ソースコード、証明書やその他安全な処理への入力を含む (但しそれだけに制限されない) 。 その非妥当性がユーザエラーによるものなのか、論理上のエラーによるものなのか、悪意のある動作によるものなのかに係わらず、アプリケーションは妥当でない入力からは保護されるという事が重要である。

複数のリクエスト通信にかかわるスクリプトの作者は、状態情報の検証について特に注意すべきである; 元々安全であるとみなされる投稿の一部について危険な値に置き換える事によって望まざる影響を引き起こすかもしれない。 この種の破壊は、 クライアントによって制御される事になっていなかった通信の前段階からのデータ (例えば、hidden HTML フォーム要素、Cookie, 埋め込まれた URL 等) が変更される時に起こる。

9.8. 相対的パス

サーバは、リクエスト URI 内の ".." パス要素に注意すべきである。 これらは、リクエスト URI を script-path と extra-path に分割する前に取り除かれるか解決されるべきである。 さもなくば、extra-path が PATH_TRANSLATED を探すために使われる時、パスの解決によって変換されるパスが想定されるパス階層の外に出たものにならないように注意すべきである。

9.9. Non-parsed Header の出力

スクリプトが non-parsed header 出力、すなわちその本来のプロトコル内でクライアントによって解釈されるものを返す場合、スクリプトはそのプロトコルに関連する全てのセキュリティについての考察について取り組まなければならない。

10. 謝辞

この作業は、'www-talk' メーリングリスト上の議論に起こった元来の CGI インターフェースに基づいている。 特に、Rob McCool, John Franks, Ari Luotonen, George Phillips, Tony Sanders 各氏へはこのインターフェースの初期バージョンを定義や実装への努力について特別のお礼を申し上げる。

また、この文書では Chris Adie, Dave Kristol, Mike Meyer; 更に David Morris, Jeremy Madea, Patrick McManus, Adam Donahue, Ross Patterson, Harald Alvestrand 各氏からより大いに有益な意見や提案を頂いている。

11. 参照文献

11.1. 規約の一部としての参照

1
Berners-Lee, T., Fielding, R. and H. Frystyk, Hypertext Transfer Protocol -- HTTP/1.0, RFC 1945, May 1996.
2
Berners-Lee, T., Fielding, R. and L. Masinter, Uniform Resource Identifiers (URI): Generic Syntax and Semantics, RFC 2396, August 1998.
3
Bradner, S., Key words for use in RFCs to Indicate Requirement Levels, BCP 14, RFC 2119, March 1997.
4
Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, Hypertext Transfer Protocol -- HTTP/1.1, RFC 2616, June 1999.
5
Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., Sink, E. and L. Stewart, HTTP Authentication: Basic and Digest Access Authentication, RFC 2617, June 1999.
6
Freed, N. and N. Borenstein, Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types, RFC 2046, November 1996.
7
Hinden, R., Carpenter, B., and L. Masinter, Format for Literal IPv6 Addresses in URL's, RFC 2732, December 1999.
8
HTTP Status Code Registry, http://www.iana.org/assignments/http-status-codes, IANA.
9
Information Systems -- Coded Character Sets -- 7-bit American Standard Code for Information Interchange (7-Bit ASCII), ANSI INCITS.4-1986 (R2002).
10
Information technology -- 8-bit single-byte coded graphic character sets -- Part 1: Latin alphabet No. 1, ISO/IEC 8859-1:1998.

11.2. 情報提供としての参照

11
Berners-Lee, T., Universal Resource Identifiers in WWW: A Unifying Syntax for the Expression of Names and Addresses of Objects on the Network as used in the World-Wide Web, RFC 1630, June 1994.
12
Braden, R., Requirements for Internet Hosts -- Communication Layers, STD 3, RFC 1123, October 1989.
13
Crocker, D., Standard for The Format of ARPA Internet Text Messages, STD 11, RFC 822, August 1982.
14
Dierks, T. and C. Allen, The TLS Protocol Version 1.0, RFC 2246, January 1999.
15
Hinden R. and S. Deering, Internet Protocol Version 6 (IPv6) Addressing Architecture, RFC 3513, April 2003.
16
Masinter, L., Returning Values from Forms: multipart/form-data, RFC 2388, August 1998.
17
Mockapetris, P., Domain Names - Concepts and Facilities, STD 13, RFC 1034, November 1987.
18
Raggett, D., Le Hors, A., and I. Jacobs, Eds., HTML 4.01 Specification, W3C Recommendation December 1999, http://www.w3.org/TR/html401/.
19
Rescola, E. HTTP Over TLS, RFC 2818, May 2000.
20
St. Johns, M., Identification Protocol, RFC 1413, February 1993.
21
IBM National Language Support Reference Manual Volume 2, SE09-8002-01, March 1990.
22
The Common Gateway Interface, http://hoohoo.ncsa.uiuc.edu/cgi/, NCSA, University of Illinois.

12. 筆者のアドレス

 David Robinson
 The Apache Software Foundation

 EMail: drtr@apache.org


 Ken A. L. Coar
 The Apache Software Foundation

 EMail: coar@apache.org

13. 著作権表示全文

Copyright © The Internet Society (2004). All Rights Reserved. この文書は、BCP 78 や www.rfc-editor.org に含まれる権利、許可、制限に従い、その中で明示されるものを除いて、著者が全ての権利を保持する。

この文書とここに含まれた情報は、"そのまま {AS IS}" である事を基に提供され、投稿者や、(もしいるならば) その人物が代表する、あるいはその人物を後援する組織、インターネット学会、及び IETF は、この中の情報の使用が、商用利用及び特定用途においていかなる権利もいかなる暗黙的保障も侵害していないという保障への制限を含め、明示的に又は暗黙的に、全ての保障を放棄する

知的所有権

IETF は、この文書内に記述された技術の実装や使用に付随して主張されるいかなる知的所有権あるいは他の権利の正当性や範囲に関して、あるいはその様な権利の下でいかなる許可が利用可能であり、また利用不可能であるかの範囲に関して、いかなる立場もとらない; すなわち、そのような権利を識別するためのいかなる独立的調査を行った事も明言しない。 IETF 文書内の権利に関する IETF の手続き上の情報は、BCP 78 と BCP 79 にて見つける事ができる。

IETF 事務局による IPR ディスクロージャのコピーや、利用可能とされるようなライセンスの保証や、この仕様書の実装者や利用者によってそのような所有者の権利の使用のために一般的なライセンスや許可を得るためになされた試みの結果は、http://www.ietf.org/ipr にある IETF オンライン IPR レポジトリから得る事ができる。

IETF は、この標準を実装するために必要な技術をカバーするためのあらゆる著作権、特許、特許の出願、あるいは他の所有権について明らかにする事に興味を持つ団体を募集している。 どうか IETF の ietf-ipr@ietf.org にその情報をお寄せ頂きたい。

謝辞

RFC Editer 機構の資金は、現在インターネット学会から提供されている。


#TOP
Copyright © 1999-2008 橋本英彦 (H-Hash), All Rights Reserved.