以下の文章は、私が1994年2月に公開したものです。公開してすでに6年以上経ち、 技術解説としてはおそらく役に立たないと思います。CGIの使い方について知りたい方は、 別の情報を探すことをおすすめします。このページは歴史的記録として残しておくことにします。江渡 浩一郎 2000/06/11
このドキュメントは、CGIおよびFORMという機能の使い方を簡単に 解説したものです。できるだけ間違いのないように注意しましたが、 いろいろあるだろうと思います。見つかったら指摘してください。 ここがわからない、こうしたほうがいい、などのコメントがありま したら、t91069ke@sfc.keio.ac.jpまでE-mailをください。
このドキュメントは、NCSAのhttpdを使っていて、標準のディレク トリー構成であることを前提としています。また、だいたいのhtml の書き方と、perlの書き方がわかっていることを前提としてます。 htmlの書き方がわからない人は、 HTML入門を読んでください。また、perlの書き方については、 ここを参考にして ください。できればserverの管理者であるほうが望ましいです。
以下のドキュメントを参考にしました。
client側でのscript実行にはまだ多くの問題がある。この 文章を参照のこと。 FORMというのは、HTML+で規定されたタグで、HTML文章中でinput fieldを作れるようにするものである。
http://andro.sfc.keio.ac.jp/cgi-bin/date
これは現在のandro.sfc.keio.ac.jpというserverの時間である。 server側でdateを実行してその出力をMosaicに出している。server 側で何を実行しているか見てみよう。
==> /usr/local/etc/httpd/cgi-bin/date <== #!/bin/sh DATE=`which date` echo Content-type: text/plain echo if [ -x $DATE ]; then $DATE else echo Cannot find date command on this system. fi ==> end <==
shell scriptの中身は、ようするに見てわかるとおり、標準出力に だしたものがhtmlのファイルとして処理されて、Mosaicの画面にで てくる。
いくつか注意。
echo Content-type: text/plain echo
この2行を忘れてはならない。これを忘れると、でてこない。
また、server側でscriptが無限ループにはいると、clientはアクセ スした状態でとまってしまう。
このdateというscriptは、NCSA httpdについてきたものである。 /usr/local/etc/httpd/cgi-binというのがdefaultのcgi scriptの 置かれるところである。
もしあなたがserverの管理者なら、httpdの配布についてきた scriptを、/usr/local/etc/httpd/cgi-binに置いてみよう。 そして、
http://あなたのserver名/cgi-bin/date
と、実行してみよう。同じように実行できるはずだ。
cgi-binについては、設定ファイル
/usr/local/etc/httpd/conf/srm.conf
で変えられる。
# ScriptAlias: This controls which directories contain server scripts. # Format: ScriptAlias fakename realname ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/
ここを変更すればscriptの置き場所を自由に決定できる。もちろん、 このdirectory以外のところにおいてあるscriptは実行できない。 やろうとしても、scriptがplain textとして読み出されるだけだ。
これでserver側でのscript実行についてだいたいわかったもらえた と思う。ここまでではまだ、client側からserver側へ、情報を送る ことができない。次にFORMの使い方についてみてみよう。
僕のadd-name.htmlをサンプルとして見てみよう。
=== add-name.html === <FORM METHOD="POST" ACTION="/cgi-bin/add-name"> Please add your name to my visited person list.<P> Please input your name: <INPUT NAME="name" SIZE=30> <P> Please input your mail address: <INPUT NAME="address" SIZE=40> <P> Please input your home page URL: <INPUT NAME="url" SIZE=40> <P> If you don't have your home page, please keep it brank.<P> After input these field, press this button: <INPUT TYPE="submit" VALUE="ADD"> <P> </FORM>
余分なところは削ってある。それぞれの項目を簡単に解説する。
まずFORMというタグで、ある部分を囲むようにする。その中がひと まとまりの情報となって送られるということだ。また、FORMはネス トできない。FORMの部分をわかりやすくするために、前後に <HR>(horizontal rule)というタグをつけることが 推奨されている。
<FORM METHOD="POST" ACTION="/cgi-bin/add-name">
METHODのところはGETとPOSTの2種類から選ぶ。serverに対してどの ように情報を送るのかの方法を選んでいる。
ようするに違いは、
INPUTというタグのところで、実際にインプットフィールドが作ら れる。NAMEというのは、そのフィールドにつけた名前。server側で はこの名前をもとにして情報を受け取る。
SIZEで大きさを指定する。defaultだと20になっている。ここでは 少し横に大きくするために、SIZEを30とか40にしている。
<INPUT TYPE="submit" VALUE="ADD">
TYPE="submit"というのは、これが選ばれると、情報が送られると いうこと。Mosaicだとボタンの形になる。INPUTが一つだけだと、 そこでリターンを押したときに自動的にsubmitになる。複数の INPUTがあるときは必ずこれを作らなくてはならない。VALUE="ADD" というのは、ボタンにつく名前。
TYPEというのはもっといろいろあるが、とりあえず省略。
詳し くは、 Fill-out Formについての文章を読んでみてほしい。 submitが押されると、FORMのところのACTIONに示されるものが実行 される。これで、インプットフィールドの情報がserverへと送られ る。次にどのように情報の受け渡しがなされるか見てみよう。
http://andro.sfc.keio.ac.jp/cgi-bin/finger?eto
のように、?のあとに情報がくっつくという形式だった。 このときは、一つしか情報が送れなかった。
FORMではどのように拡張されているかというと、上記のINPUTタグ のNAMEというところについている名前を使って指定するようになっ ている。 たとえば上記のhtmlで、情報が以下のようになっていたとする。
このとき、
name=ETO+Kouichirou&address=t91069ke@sfc.keio.ac.jp&url=http%3a%2f%2fandro.sfc.keio.ac.jp%2feto%2f
という形で送られる。GETの場合はこれが環境変数QUERY_STRINGに、 POSTの場合はこれが標準入力から送られる。
見るとわかるように、
cat > $tmp
とかやってもだめ。終りを読みとってくれないから、そこで止まっ てしまう。
GETとPOSTの区別は、REQUEST_METHODという環境変数で送られる。 GETの場合はQUERY_STRINGという環境変数に情報が入る。
ということで、これらをふまえた上で、これをperlで書いてみよう。 これがadd-name scriptの本体。これ は、comp.infosystems.wwwで流れていたperlによるcgiの書き方の newsを参考にして書いたものだ。これが もとの サンプル。これを元にいろいろ改変を加えている。 以下に、少しづつ解説を加えていく。
&cgi'header; まず、例の
Content-type: text/html
というヘッダーを書いている。
&cgi'decode;
というところで実際のdecodeの処理をやってくれている。0という のはverboseかどうかを指定しているのがが、とりあえず無視して いい。ここで、%cgi'tagsに、連想配列の形で送られてきた情報を 入れている。&cgi'decodeの中身を見てみよう。
if ($ENV{'REQUEST_METHOD'} eq "POST"){ $n_read = sysread(STDIN, $args, $ENV{'CONTENT_LENGTH'}); } else { $args = $ENV{'QUERY_STRING'}; }
POSTかGETかを判別して、$argsに送られてきた情報をいれている。
@terms = split('&', $args);
まず、&で区切る。
foreach (@terms) { ($tag, $value) = split(/=/, $_, 2);
= で区切って、
$value =~ s/\+/ /g;
+ を ' ' に変換。
$value =~ s/%(..)/pack("c", hex($1))/ge;
%?? を元の文字列に変換。
$tags{$tag} = $value; # tags is global
cgi_tags に連想配列の形でいれて、return。
$cont = $cgi_tags{$tag}; $cont =~ s/&/&/g; $cont =~ s/</</g; $cont =~ s/>/>/g;
ここで、& < >を実際にそう見えるように変換している。 あとの残りは見ればわかると思うので省略。 これをパッケージの形に書き直してみた。 here
だいたいこのくらいわかれば自分でもCGIとFORMの機能を利用した ページを作れるのではないかと思う。日本のWWWでも、これらの機 能を利用したページが増えるとうれしい。
最後に、このドキュメントを読んだ人は、ぜひここをアクセスして、僕の訪問者 リストに名前をつけくわえていってください。:-)
それでは、Have a Happy Networking!
history: