$Id: cgi-mechanism.html,v 2.8 2001-07-02 09:40:26+09 kabe Exp $
CGI (Common Gateway Interface) とは、情報サーバーが外部のプログラム (ゲートウェイ)を走らせるためのインターフェースである。 現在の所、情報サーバーとしてはHTTPサーバーだけが定義されている。 この機能を用いれば、静的なデータだけでなく、動的なデータも URIでアクセスすることができる。
ちまたでは CGI と言うと、このプログラム自体を指すようですが、 本当に正確に言うのであれば CGI は単なるインタフェースの規格で、 プログラム自体はゲートウェイと言うのが正しい。HTTPd <----> Gateway <----> 他のシステム(データベースとか) ↑ ここのプロトコルがCGI (Common Gateway Interface)
<A HREF="...">に直接CGIのURLを書くこともあるが、 この場合はすぐにHTTPサーバーが仕事をする ことになる。
%xx
)される。
また、空白文字は'+'に置換される。
'+'自身は'%2B'になる。
<INPUT TYPE=TEXT NAME="name" VALUE="John Doe">というフィールドを form data setに変換すると、
name=John+Doeとなる。
たとえば、
<FORM METHOD=GET ACTION="http://somehost/cgi-bin/foo" >で、form data setが
name=John+Doe&gender=maleだとすると、アクセスされるURIは
http://somehost/cgi-bin/foo?name=John+Doe&gender=maleとなる。
たとえば、
<FORM METHOD=POST ACTION="http://somehost/cgi-bin/bar">だったとすると、上の例の form data setはHTTP上では
POST /cgi-bin/bar HTTP/1.0 Content-type: application/x-www-form-urlencoded Content-Length: 25 name=John+Doe&gender=maleと送信される。 POSTでは最低限 Content-Length: フィールドが必要なため、 HTTP/1.0 以上でないと送信できない。
form data setがとんでもなく長くなる場合は、 GETではURIが長くなってしまうため、古いサーバーが萎えてしまうことがある。 こんな時は、副作用がなくても例外的にPOSTを使ったFORMを書く 場合もある。
HTMLの規格では、<ISINDEX> は <HEAD> の中、 <IMG ISMAP> は <A HREF=...> の中でしか使えない。 特に<ISINDEX>は手軽なので <BODY> の中で 使いたくなるが、厳密には規格に沿っていない。気をつけよう。
Netscape拡張では <ISINDEX> のプロンプト文字列が変えられる。 ますます <BODY> で使う人が増えそうだ…って、 Netscape拡張には DTD がないから何をどー書いてもかまわないという話もある:-P
HREF="..."
に書く場合ゲートウェイ呼出のURIは上のように <ISINDEX> か <FORM> で 生成するのが本来の経路であるが、めんどくさい場合には直接 <A HREF> や <IMG SRC> で指定することも少なくない。 この場合は & を & にエスケープすること。
http://somehost/cgi-bin/foo?name=John+Doe&gender=male ↓ <A href="http://somehost/cgi-bin/foo?name=John+Doe&gender=male">...</A>
注意しなければならないのは、URIとしては あくまで `&'が 正しく、`&'への変換は HTML(SGML)のHREF属性の値として埋め込むためという 事情による。従って WWWブラウザはこの & を `&' に戻して サーバーに URLを送信する。
ただやっかいなことにこの処理をきちんとやらないブラウザが 世の中にはびこっているので、どうしても安全側に倒したい人は `&'を使わずに 値を渡す手段も考える余地あり。 どっちにしてもform data setの解釈はゲートウェイの作り方次第なので、 HREFに直書きするなら別に & でなくてもよい。
この「環境変数で渡す」というのが要するに Common Gateway Interfaceの方法なので、 CGIではないゲートウェイ起動方法 (プラグインとか)では 環境変数を使わないこともある。
ゲートウェイに渡される環境変数にはさまざまのものがあり、 どんなものがあるかは使っているHTTPサーバーに依存する。 このうち、NCSA HTTPdの実装をまとめたものが CGI/1.1 であり、W3C httpdをはじめ多くのサーバーはこれに準拠 (完全対応とはいってない:P)しているようである。
CGI/1.1では、CGIを指すscript URIが以下のように定義されている。 見ためは普通のURIと変わらない。
://
SERVER_NAME
[ :
SERVER_PORT ]
enc-script
[ enc-path-info ]
[ ?
QUERY_STRING ]
SCRIPT_NAME
をURIエンコードしたもの。
PATH_INFO
(追加パス)をURIエンコードしたもの。
例としては
http://somehost/cgi-bin/test-cgi?keyword
script URIをサーバーが受けとっても、
QUERY_STRING
を
QUERY_STRINGに設定する。
PATH_INFO
に
enc-path-infoをデコードして設定する。
=
'が
含まれていなければargv[1]にも
QUERY_STRINGをデコードして渡す。
CONTENT_LENGTH
にBody
(form data set)の
長さを設定する。
設定方法は違えどこういったメカニズムはどのHTTPサーバーも 持っている。渡されたURIをどう解釈し、どうゲートウェイに渡すかは 本当はサーバー依存なのだが、 やはり普及しているW3CやNCSAのサーバー (CGI/1.1) と 大きく違う動作をするものは 互換性の点であまり使われていないような気がする。
というか、大きく違うものは "CGI" ではなく、 別のインターフェースになる。
より多くの環境変数を渡すことには問題がないので、 サーバーによってはCGI/1.1よりも多くの有用な情報を渡してくれる ものもある。 その機能を使用するゲートウェイは残念ながら他のサーバーの管理下では 使えなくなる可能性があるが、 実際問題としてサーバーのグレードダウンはそうそうないであろうから、 問題は少ないと思う。 あなたのサイトのサーバーにも、何か面白い機能があるかもしれない。
逆に、他のサイトでも使ってもらいたいようなゲートウェイ (CGIプログラム)を作って公開する場合は、サーバー依存の環境変数は あまり使わない方がいいだろうし、使っている場合はちゃんと 動作環境として「ほげサーバー専用」と書かないといけない。 (意外にみんな書かない)
たとえばREQUEST_URI
やSCRIPT_FILENAME
なんてのは 良く使われてそうだが、実は Apache依存。
特に指定がなければ、ゲートウェイは生成するデータを標準出力に 書き出すのが一般的である。 サーバーはこのデータを読みとり、必要に応じてHTTP Responseに 変換する。
"Content-Type" ":"
media-type NL
"Location" ":"
URI NL
"Status" ":"
3digit SP reason-phrase NL
考え方自体はInternet MailやNetNewsと同じ。 空行でヘッダと本文を区切る。