この文書は、 >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
この文書はインターネットコミュニティのための情報を提供する物である。 この文書はいかなる種のインターネットの標準も明述する物ではない。 この文書の配布に制限は無い。
Copyright © The Internet Society (2004). All Rights Reserved.
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 インタフェースの使用方法も定義する。
Common Gateway Interface (CGI) [22] は、HTTP [1], [4] サーバや CGI スクリプトに、クライアントのリクエストに応答するための責任を共有させる。 クライアントのリクエストは、 Uniform Resource Identifier (URI) [11]、リクエストメソッド、及び転送プロトコルによって提供されるリクエストについての様々な付属的情報を含んでいる。
CGI は、クライアントのリクエストを説明するための、外部変数として知られる、抽象的なパラメータを定義する。 これは、具体的なプログラマインタフェースと共に、スクリプトと HTTP サーバ間のプラットフォームに依存しないインターフェースを規定する。
サーバは、クライアントのリクエストに関連する、接続、データ転送、転送、及びネットワーク上の問題の管理について責任を負うが、CGI スクリプトは、データアクセスや文書処理のような、アプリケーション上の問題を扱う。
この文書内の 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'MAY', 'OPTIONAL' 各キーワードは、BCP 14 である、 RFC 2119 [3] にて説明されるように解釈されるべきである。
それが実装するプロトコルの 一つ以上の 'must' 要件を満足しなければ、実装は適合しているとはいえない。 その特徴について、全ての 'must' と全ての 'should' 要件を満足する実装は、'無条件に適合' と呼ばれる; 一方、全ての 'must' 要件は満足するものの、全ての 'should' 要件は満足しないような実装は、'条件付適合' と呼ばれる。
この仕様書の主となる部分で CGI の全ての機能や特性が定義されているわけではない。 規定されていない特性を説明するために、以下の語句が使用される:
この仕様書では、HTTP/1.1 仕様書 [4] にて定義される多くの用語を使用する; しかし、以下の用語は、HTTP/1.1 仕様書における定義、あるいはその一般的な意味とは異なる意味で使用する。
この文書で規定されるメカニズムは全て、通常の文章、及び RFC 822 にて使用されるものに類似する拡張 Backus-Naur 形式 (BNF) によって記述される。 特に言及されなければ、要素は大文字小文字を区別する。 この拡張 BNF は、以下の構造を含む。
この仕様書は、文字上では定義される 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> よりも大きな文字集合であると定義する事ができる。
ここで使用される変数や構造のいくつかは、'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 = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
サーバは、アプリケーションゲートウェイのように振る舞う。 サーバは、クライアントからリクエストを受け取り、そのリクエストを扱う CGI スクリプトを選択し、クライアントのリクエストを CGI リクエストに変換し、スクリプトを実行し、 CGI レスポンスをクライアントへのレスポンスに変換する。 クライアントリクエストを処理する時、サーバにはあらゆるプロトコルやトランスポート層レベルでの認証やセキュリティを実装する責任がある。 また、サーバは、'透過的でない' 方法で、例えばメディアタイプ変換やプロトコルのダウングレードのような、更なる追加的サービスを提供するためにリクエストやレスポンスを修正するようにしてもよい。
サーバは、この仕様書によって要求されるようにクライアント要求データへの翻訳やプロトコル変換を行わなければならない。 更に、サーバは、例えその CGI スクリプトがこの仕様書に適合しなくても、関係するネットワークプロトコルには適合するという事をクライアントに対して責任を負う。
サーバがリクエストへ認証を適用する場合、そのリクエストが定義される全てのアクセス制御を通過しなければ、サーバはそのスクリプトを実行してはならない。
サーバは、クライアントにより与えられる一般形式の URI に基づいて、CGI によって実行されるスクリプトがどれかを決定する。 この URI は、"/" によって分けられる構成要素を伴う階層的なパスを含む。 どんな特定のリクエストについても、サーバは個別のスクリプトが持つこのパスの全てあるいはその先頭部分を識別し、そのスクリプトをパス階層における特定の位置に配置するであろう。 パスに残りの部分がある場合、それはスクリプトによって解釈されるリソース、あるいはサブリソースの識別子になる。
このパスの分割についての情報は、後述する、外部変数としてスクリプトから利用できる。 非階層的な URI スキームのサポートは、この仕様書の範囲外である。
クライアントのリクエスト URI からのスクリプトの選択のマッピングは、特定のサーバの実装とその設定によって定義される。 サーバは、そのスクリプトがいくつかの異なる URI パス階層の集合によって識別されるようにしてもよく、 その場合、外部変数の処理や生成の間は、その 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 について任意の許される値を持つスクリプトを呼び出すように構成されうるという事にも注意せよ。
スクリプトは、システム的に規定される方法をもって呼び出される。 他で規定されていなければ、スクリプトを含むファイルは実行可能なプログラムとして呼び出されるであろう。 サーバは section 4 にて記述されるな CGI リクエストを準備する; ここにはリクエスト外部変数 (実行時はスクリプトで直ちに利用可能) とリクエストメッセージデータを含む。 リクエストデータは、スクリプトで直ちに利用可能である必要はない; スクリプトはサーバがクライアントから全てのデータを受信する前に実行され得る。 スクリプトからのレスポンスは、section 5 と 6 にて記述されるように、サーバへ返される。
エラー状況の場合には、サーバはいつでも警告なしにスクリプトの実行を中断あるいは終了できる。 これは、例えば、サーバとクライアント間での転送の失敗という場合がある; そのため、スクリプトは異常終了を処理するための用意をすべきである。
リクエストについての情報は二つの異なる情報源から来る; すなわち、リクエスト外部変数と任意の関連する message-body である。
外部変数は、サーバからスクリプトへ渡されるリクエストについてのデータを含み、システム的に規定される方法をもってスクリプトによってアクセスされる。 外部変数は、大文字・小文字を区別しない名前によって識別される; すなわち、二つの異なる変数においてその名前の大文字・小文字のみが異なるものはありえない。 ここでは、大文字と下線 ("_") の正式な表現を使用してそれらを示す。 特定のシステムでは、異なる表現を定義する事ができる。
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 の場合、省略して (設定しないでおいて) もよい。 外部変数の値は、他に言及されていなければ、大文字・小文字を区別するとみなされなければならない。 外部変数における文字の表現はシステム的に規定される; すなわち、サーバはそれらの値をその対応する表現に変換しなければならない。
AUTH_TYPE 変数は、ユーザを認証するためにサーバによって使用されるメカニズムを識別する。 ここには、クライアントのプロトコルやサーバの実装によって定義される大文字・小文字を区別しない値を含む。
HTTP において、クライアントのリクエストが外部のアクセスについての認証を要求する場合、サーバはこの変数の値をリクエストの Authorization ヘッダフィールド内の 'auth-scheme' トークンから設定しなければならない。
AUTH_TYPE = "" | auth-scheme auth-scheme = "Basic" | "Digest" | extension-auth extension-auth = token
HTTP アクセス認証スキームは、RFC 2617 [5] にて記述される。:
CONTENT_LENGTH 変数は、リクエストが message-body を持つ場合、オクテットの十進数でそのサイズを含む。 データが付加されていなければ、 NULL (あるいは未設定) である。
CONTENT_LENGTH = "" | 1*digit
サーバは、リクエストが message-body エンティティが伴っている場合にのみ、この外部変数を設定しなければならない。 CONTENT_LENGTH 値は、サーバが任意の転送コーディングや内容コーディングを取り除いた後、message-body の長さを反映しなければならない。
リクエストが 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 パラメータが省略される場合、既定値は最初に以下の規則のいずれかを適用する事によって生成されるべきである:
サーバは、HTTP Content-Type フィールドがクライアントリクエストヘッダ内に存在する場合は、この外部変数を設定しなければならない。 サーバは、エンティティが付加されており Content-Type ヘッダフィールドのないリクエストを受信した場合は、正しい内容タイプを決定しようとしてもよいが、そうでなければこの外部変数は省略すべきである。
GATEWAY_INTERFACE 変数は、スクリプトを介して通信するサーバがによって使用されている CGI の能力{dialect} が設定されなければならない。 構文は:
GATEWAY_INTERFACE = "CGI" "/" 1*digit "." 1*digit
メジャー番号とマイナー番号は分割された整数値として扱われるので、それぞれが複数桁になりうる事に注意せよ。 従って、CGI/2.4 は CGI/2.13 よりも下のバージョンで、さらにそれらは CGI/12.3 よりも下となる。 先行するゼロはスクリプトによって無視されなければならないし、またサーバによって生成されてはならない。
この文書は、CGI インタフェースのバージョン 1.1 を定義する。
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 参照) の更なるパス構成要素を形成する。
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 に設定 (あるいは未設定と) しなければならない。
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 は空文字列 ("") として定義されなければならない。
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] にて記述されている。
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 の値で代用してもよい。
REMOTE_IDENT 変数は、遠隔エージェントに対する RFC 1413 [20] リクエストによる接続について報告される識別情報があれば、これを提供するために使用する事ができる。 サーバは、この機能を提供しない、効率上の理由のためデータを要求しない、あるいは利用可能な識別データを返さない、のいずれかを選択する事ができる。
REMOTE_IDENT = *TEXT
返されるデータは認証目的のために使用する事ができるが、その信頼度は最小限であるべきである。
REMOTE_USER 変数は、ユーザ認証の一部としてクライアントによって供給されるユーザ識別用文字列を提供する。
REMOTE_USER = *TEXT
クライアントリクエストが、HTTP 認証 [5] を要求した (例えば AUTH_TYPE 外部変数が "Basic" や "Digest" と設定されている) 場合は、REMOTE_USER 外部変数の値は供給されるユーザ ID に設定されなければならない。
外部変数 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 にて記述されている。
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 値には含まれない。
SERVER_NAME 変数は、クライアントリクエストが向けられるサーバのホスト名が設定されなければならない。 この値は、大文字・小文字を区別しないホスト名、あるいはネットワークアドレスである。 これは、Script-URI のホスト部分を形成する。
SERVER_NAME = server-name server-name = hostname | ipv4-address | ( "[" ipv6-address "]" )
複数の HTTP バーチャルホストが同じ IP 番地を共有していれば、設置されるサーバはこの変数の値を複数持ち得る。 その場合、サーバは正しいバーチャルホストを選択するためにリクエストの Host ヘッダフィールドの内容を使用する。
SERVER_PORT 変数は、クライアントから受信されたこのリクエストにおける TCP/IP ポート番号が設定されなければならない。 この値は、Script-URI のポート部分に使用される。
SERVER_PORT = server-port server-port = 1*digit
この変数は、たとえそのポートがその scheme についての既定のポートであり、URI から省略できる場合であっても、設定されなければならない事に注意せよ。
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 リクエストとして扱うべきである。
SERVER_SOFTWARE 外部変数は、CGI リクエストを作成している (またゲートウェイを運用している) サーバソフトウェアの名前とバージョンの情報が設定されなければならない。 これは、クライアントに報告されるサーバの説明がある場合、それと同じであるべきである。
SERVER_SOFTWARE = 1*( product | comment )
product = token [ "/" product-version ]
product-version = token
comment = "(" *( ctext | comment ) ")"
ctext = <any TEXT excluding "(" and ")">
サーバは、そのリクエストについてのプロトコルや scheme に特有の外部変数を設定すべきである。 プロトコル特有の変数の解釈は、SERVER_PROTOCOL 内のプロトコルバージョンに依存する。 サーバは、その scheme がそのプロトコルと同じでなければ、scheme の名前を持つ外部変数に NULL でない値を設定してもよい。 このような変数の有無は、そのリクエストでどの scheme が使用されているかをスクリプトに示す。
使用されているプロトコルが HTTP の場合、"HTTP_" で始まる名前を持つ外部変数はクライアントのリクエストヘッダフィールドから読み込んだ値を含む。 外部変数名は、HTTP ヘッダフィールド名が大文字に変換され、存在する全ての "-" を "_" に置換し、先頭に "HTTP_" が与えられたものとなる。 ヘッダデータは、クライアントによって送られる通りに表す事もできるし、あるいはその意味を変えないように書き換える事もできる。 同じ名前のフィールド名を持つ複数のヘッダフィールドを受信した場合、サーバは同じ意味を持つ単一の値に書き換えなければならない。 同様に、複数行にわたるヘッダフィールドは、単一の行に結合されなければならない。 サーバは、必要であれば、データの表現 (例えば、文字セット) を CGI 外部変数にとって適切なように変更しなければならない。
サーバは、それが受信した全てのヘッダフィールドについての外部変数を作成する必要はない。 特に、例えば 'Authorization' のような、認証情報を転送する任意のヘッダフィールドや、あるいは、例えば 'Content-Length' や 'Content-Type' のような、他の変数からスクリプトにて利用可能なものは取り除くすべきである。 サーバは、'Connection' のような、クライアント側との通信上の点にのみ関係するようなヘッダフィールドは取り除いてもよい。
リクエストデータは、システム的に規定される方法においてスクリプトによってアクセスされる; 他に定義されていなければ、これは '標準入力' のファイル記述子あるいはファイルハンドルを読み込む事によってなされるであろう。
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 から内容コーディングを取り除いてもよい。
リクエストメソッドは、REQUEST_METHOD 外部変数として与えられるが、レスポンスを生成する際にスクリプトによって適用される処理の方法を識別する。 スクリプトの著者は、特定のアプリケーションについて最も適するようにそのメソッドを実装するという事を選択できる。 もしスクリプトが自身がサポートしないメソッドを持つリクエストを受信した場合、エラーとともにそれを拒否すべきである (section 6.3.3 参照)。
GET メソッドは、スクリプトが外部変数の値に基づいて文書を生成すべきという事を示す。 慣例により、GET メソッドは '安全' かつ '冪等' であり、文書の生成以外の動作を行う事の意味を持つべきではない。
GET メソッドの意味は、プロトコル特有の外部変数によって修正、あるいは再定義されるかもしれない。
POST メソッドは、スクリプトが、外部変数に加えて、リクエストメッセージボディ内のデータに基づいて処理を行い文書を生成するように要求するために使用される。 一般的には HTML [18] におけるフォーム提出に使用され、例えばデータベース内の変更のような、恒久的な影響をもつスクリプトによって処理を開始されるという事が意図される。
スクリプトは、付加される message-body を読み込む前に CONTENT_LENGTH 変数の値をチェックしなければならないし、またそれを処理する前に CONTENT_TYPE 値をチェックすべきである。
HEAD メソッドは、スクリプトにレスポンスメッセージボディを供給する事なく、レスポンスヘッダフィールドを返すために十分な処理をする事を要求する。 スクリプトは、HEAD リクエストについてのレスポンスメッセージボディを供給してはならない。 もしそうなった場合、サーバはスクリプトからのレスポンスを読み込む時にその message-body を破棄しなければならない。
スクリプトは、HTTP/1.1 の PUT や DELETE のような、任意のプロトコル特有なメソッドを実装する事ができる; そうする時は、SERVER_PROTOCOL の値をチェックすべきである。
サーバは、あるメソッドがスクリプトにとって適切ではない、あるいは認められないと決定する事ができるし、そのメソッドをサーバ自身で扱ってもよいし、クライアントにエラーとして返したりしてもよい。
いくつかのシステムでは、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 値がエンコードされていない "=" 文字を含むかどうかをチェックすべきであり、その場合コマンドライン引数を使用すべきではない。
サーバは、NPH (Non-Parsed Header) スクリプトをサポートする事ができる; これらは、サーバが負うレスポンス処理についての全ての責任を渡されたスクリプトである。
この仕様書では、NPH スクリプトがその出力データのみに基づいて識別されるようなメカニズムは提供しない。 慣例により、任意のスクリプトは一つの種類 (NPH か CGI) の出力のみしか提供できないので、そのスクリプト自身は 'NPH スクリプト' と表現される。 NPH をサポートするサーバは、おそらくスクリプトの名前や位置に基づいた、NPH スクリプトを識別するための実装的に規定されるメカニズムを提供しなければならない。
スクリプトがデータをサーバやクライアントに送り返すためのシステム的に規定される方法が存在しなければならない; すなわち、スクリプトは常に何らかのデータを返さなければならない。 そのように定義されなければ、それは従来の CGI スクリプトと同じあろう。
現在、NPH スクリプトは HTTP クライアントリクエストについてにのみ定義されている。 (HTTP) NPH スクリプトは、今のところ HTTP 仕様書 [1], [4] の section 6 にて記述されているように、完全な HTTP レスポンスメッセージを返さなければならない。 スクリプトは、レスポンスについて適切な書式を決定するために SERVER_PROTOCOL 変数を使用しなければならない。 また、スクリプトは、特定のプロトコル仕様書によって強制されているような、そのリクエストにおける任意の一般的の、あるいはプロトコル特有の外部変数に注意を払わなければならない。
サーバは、スクリプトの出力がクライアントに修正されずに送られるという事を保証しなければならない。 これは、スクリプトがヘッダフィールドにおいて正しい文字セット (HTTP においては US-ASCII [9] や ISO 8859-1 [10] ) を使用する事を要求しているのであるという事に注意せよ。 サーバは、内部的に最小限のバッファリングとなるように、また転送部分ではバッファリングのないように、スクリプトの出力がクライアントに直接送られるという事を保証しようとすべきである。
実装が他に定義をしなければ、スクリプトは自身のレスポンス中でクライアントが同じ接続上で更なるリクエストを送信できるという事を示してはならない。
スクリプトは常に空でないレスポンスを与えなければならないので、それがサーバにデータを送り返すためのシステム的に規定される方法がある。 他に定義されなければ、それは '標準出力' ファイル記述子を経由するであろう。
スクリプトは、リクエストを処理し、そのレスポンスを準備する際、REQUEST_METHOD 変数をチェックしなければならない。
サーバは、データがスクリプトから受信されなければならないタイムアウト時間を実装する事ができる。 もしサーバ実装がタイムアウトを定義し、その間にスクリプトからデータを受信しなければ、サーバはそのスクリプト処理を終了してもよい。
レスポンスは、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
CGI スクリプトは、文書レスポンスにおいてユーザに文書を返す事ができるが、この時レスポンスの成功状態を示すエラーコードを伴う事ができる。
document-response = Content-Type [ Status ] *other-field NL
response-body
スクリプトは、Content-Type ヘッダフィールドを返さなければならない。 Status ヘッダフィールドは省略可能であり、省略された場合はステータス 200 'OK' とみなされる。 サーバは、スクリプトの出力がクライアントへのレスポンスがレスポンスプロトコルのバージョンを満たす事を保証するようにあらゆる適切な修正を施さなければならない。
CGI スクリプトは、Location ヘッダフィールドにてローカルリソースについての URI パスと query-string ('local-pathquery') を返す事ができる。 これは、指定されたパスを使用してそのリクエストを再処理すべきであるという事をサーバに示す。
local-redir-response = local-Location NL
スクリプトはいかなる他のヘッダフィールドも message-body も返してはならないし、 サーバは以下のような URL を含むリクエストへのレスポンスを生成する時と同じレスポンスを生成しなければならない。
scheme "://" server-name ":" server-port local-pathquery
CGI スクリプトは、クライアントに指定された URI を使用してそのリクエストを再処理すべきであるという事を示すために、Location ヘッダフィールドにて絶対 URI パスを返す事ができる。
client-redir-response = client-Location *extension-field NL
スクリプトは、サーバ的に規定される CGI 拡張ヘッダを除く、いかなるヘッダフィールドも提供してはならない。 HTTP クライアントのリクエストについて、サーバは 302 'Found' HTTP レスポンスメッセージを生成しなければならない。
CGI スクリプトは、クライアントに指定された URI を使用してそのリクエストを再処理すべきであるという事を示すために、Location ヘッダフィールドにて絶対 URI パスを返し、かつ文書を伴う事ができる。
client-redirdoc-response = client-Location Status Content-Type
*other-field NL response-body
ここでは 302 'Found' のステータスコードを含む Status ヘッダフィールドは必ず与えられなければならないが、クライアントリダイレクトを意味する他の妥当なステータスコードである extension-code を含む事ができる。 サーバは、スクリプトの出力がクライアントへのレスポンスがレスポンスプロトコルのバージョンを満たす事を保証するようにあらゆる適切な修正を施さなければならない。
レスポンスヘッダフィールドは、サーバによって解釈される 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 と ":" 間では認められない)。
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 を参照。
Location ヘッダフィールドは、そのスクリプトが実際の文書ではなく文書への参照を返している (section 6.2.3 と 6.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 はリダイレクトの対象であるリソースとしては利用できないかもしれないという事に注意せよ。
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 は、人間のためにクライアントに返される逐語的なエラーの説明である。
スクリプトは、SERVER_PROTOCOL (HTTP/1.0 [1] か HTTP/1.1 [4]) の仕様書によって定義されるレスポンスメッセージに関係する任意の他のヘッダフィールドを返す事ができる。 CGI ヘッダの構文と HTTP ヘッダの構文が異なる場合、 サーバはそのデータを変換しなければならない。 例えば、 CGI スクリプトによって使用される改行の文字列 (例えば UNIX の US-ASCII LF) は、HTTP によって使用されるもの (US-ASCII の CR と LF) と同じでないかもしれない。
スクリプトは、クライアント側の通信に関係し、そしてそのクライアントにレスポンスを送るためのサーバの能力に影響し得るようないかなるヘッダフィールドも返してはならない。 サーバは、クライアントによって返されたそのようなヘッダフィールドを削除してもよい。 サーバは、スクリプトによって返されるヘッダフィールドと自身が本来送信するであろうヘッダフィールドとの衝突を解決すべきである。
実装的に規定される CGI ヘッダフィールドを追加する事ができるが、そのフィールド名は "X-CGI-" で始めるべきである。 サーバは、スクリプトから受信される "X-CGI-" で始まる名前の認識できないあらゆるヘッダフィールドも無視する (そして削除する) 事ができる。
レスポンスメッセージボディは、サーバによってクライアントに返される付属文書である。 サーバは、スクリプトがファイル末端を通じて message-body の終端を知らせるまで、スクリプトによって提供される全てのデータを読み込まなければならない。 message-body は、HEAD リクエスト、あるいはあらゆる要求された転送コーディング、内容コーディング、文字セット変換を除き、修正されずにクライアントに送信されるべきである。
response-body = *OCTET
UNIX 互換の OS については、以下が定義される:
EBCDIC 文字セットを使用する POSIX 互換 OS については、以下が定義される:
サーバと CGI スクリプトは URL パス (それぞれ、クライアント URL と PATH_INFO データ) の扱いが一貫している必要はないが、サーバの作者は一貫性を持たせたいと願うかもしれない。 そのため、サーバ実装は以下の場合についてその振る舞いを規定すべきである:
スクリプトが 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.8 や 4.1.9 を参照) がそのリクエストの最終的な根源ではないかもしれないという事に注意すべきである。 それらは、サーバへ直接リクエストしたクライアントを識別する; すなわち、そのクライアントは実際の根源のクライアントの代わりに動作するプロクシやゲートウェイ、あるいはその他の中継者である。
HTTP 仕様書 [1], [4] のセキュリティについての考察で議論されるように、GET と HEAD のメソッドは '安全' かつ '冪等' である (繰り返されるリクエストは単一のリクエストと同じ効果を持つ) べきであるいう慣例が確立されている。
HTTP ヘッダフィールドの中には、明示的にサーバがそれをスクリプトに渡すように設定していなければ、そうすべきではない機密性の高い情報を転送するものがあるかもしれない。 例えば、サーバが基本認証方式を使用する事によってスクリプトを保護するならば、クライアントはユーザ名とパスワードを含む Authorization ヘッダフィールドを送るであろう。 サーバがこの情報を検証するのだから、十分注意なしに HTTP_AUTHORIZATION 外部変数経由でパスワードを渡すべきではない。 また、これは Proxy-Authorization ヘッダフィールドと対応する HTTP_PROXY_AUTHORIZATION 外部変数にも当てはまる。
リクエスト内の機密データは POST リクエストの一部として message-body 内に置かれるべきであり、URI やメッセージヘッダ内に置かれるべきではない。 システムによっては、スクリプトに外部変数を渡す環境が他のスクリプトやユーザから見えるかもしれない。 加えて、多くの既存のサーバやプロクシ、クライアントは、第三者から見られる所に URI を永続的に記録しているであろう。
TLS を使用するクライアント接続について、そのセキュリティモデルはクライアントとサーバ間では適用されるが、クライアントとスクリプト間では適用されない。 TLS セッションを扱うのはサーバの責任であって、従ってクライアントに認証されるのはサーバであり、 CGI スクリプトではない。
この仕様書は、スクリプトがそれを呼び出したサーバを認証するためのメカニズムを提供しない。 CGI リクエストやレスポンス上の整合性も強制されない。
多くの一般的な CGI の実装は、サーバプロセスと同じユーザとグループを使っている子プロセスとしてスクリプトを呼び出す。 従って、スクリプトはサーバプロセス、その設定ファイル、文書ファイル、あるいはログファイルに干渉できないという事を保証すべきである。
スクリプトが、(コンパイル時あるいは実行時に)サーバソフトウェア内部にリンクされる関数を呼び出す事によって実行される場合、 サーバのコアメモリを守る、あるいは信頼できないコードは実行できないようにするといった予防措置がとられるべきである。
この仕様書では、スクリプトに与えられる 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 の長さには制限はない; 従って、サーバはどんなサイズの静的に割り当てられたバッファもレスポンス全体を含むのに十分であると仮定すべきではない。
Web のステートレスな性質は、複数のリクエストが概念的に単一の Web 通信を構成する時でさえ、各スクリプトの実行やリソースの取得を全て独立なものにしてしまう。 このため、スクリプトはリクエストを提出するユーザエージェントの文脈についていかなる仮定もすべきではない。 特に、スクリプトは他のアプリケーションやコマンド、あるいは OS のサービスへの入力のような機密性の高い目的にそれらを適用する前に、クライアントから得られたデータを検査し、形式も内容も妥当であるかを検証すべきである。 それらの使用はシステムコールへの引数、データベースへの書き込み、動的に評価実行される{evaluated} ソースコード、証明書やその他安全な処理への入力を含む (但しそれだけに制限されない) 。 その非妥当性がユーザエラーによるものなのか、論理上のエラーによるものなのか、悪意のある動作によるものなのかに係わらず、アプリケーションは妥当でない入力からは保護されるという事が重要である。
複数のリクエスト通信にかかわるスクリプトの作者は、状態情報の検証について特に注意すべきである; 元々安全であるとみなされる投稿の一部について危険な値に置き換える事によって望まざる影響を引き起こすかもしれない。 この種の破壊は、 クライアントによって制御される事になっていなかった通信の前段階からのデータ (例えば、hidden HTML フォーム要素、Cookie, 埋め込まれた URL 等) が変更される時に起こる。
サーバは、リクエスト URI 内の ".." パス要素に注意すべきである。 これらは、リクエスト URI を script-path と extra-path に分割する前に取り除かれるか解決されるべきである。 さもなくば、extra-path が PATH_TRANSLATED を探すために使われる時、パスの解決によって変換されるパスが想定されるパス階層の外に出たものにならないように注意すべきである。
スクリプトが non-parsed header 出力、すなわちその本来のプロトコル内でクライアントによって解釈されるものを返す場合、スクリプトはそのプロトコルに関連する全てのセキュリティについての考察について取り組まなければならない。
この作業は、'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 各氏からより大いに有益な意見や提案を頂いている。
David Robinson The Apache Software Foundation EMail: drtr@apache.org Ken A. L. Coar The Apache Software Foundation EMail: coar@apache.org
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 機構の資金は、現在インターネット学会から提供されている。