世の中に,CGI を作るための解説本や開設サイトは多々ありますが,初心者はプログラミングの説明などばかりで,なかなか本題の CGI について学ぶことができないのではないかと思います.
初心者が躓く原因として,解説本の多くが,プログラミングの解説に重点を置いており,CGI についての説明や,HTTP,httpd などについての解説が少ない点があると思います.
今後,数回にわたり,実際に CGI を作りながら,CGI を書くための基本を解説したいと思います.
プログラムは皆さんが PC 上などで使っていると思います.いわゆる,ソフトウェアのことですが,プログラムといった場合は,もっと簡単なコマンド程度のものも含むことがあります.
例えば,UNIX では,よく使うコマンドに,lsコマンドがあります.これは,カレントディレクトリにあるファイルなどを表示する,リスト(LiSt)・コマンドです.
sakuma@JUSHI /home/sakuma% ls -la[CRLF]
total 132
drwxr-xr-x 4 sakuma wheel 1024 Nov 12 17:50 .
drwxr-xr-x 4 root wheel 512 Jul 25 02:43 ..
-rw-r--r-- 1 sakuma wheel 767 Jul 21 15:48 .cshrc
-rw------- 1 sakuma wheel 922 Jul 21 15:58 .history
-rw-r--r-- 1 sakuma wheel 248 Jul 21 15:48 .login
-rw-r--r-- 1 sakuma wheel 158 Jul 21 15:48 .login_conf
-rw------- 1 sakuma wheel 373 Jul 21 15:48 .mail_aliases
-rw-r--r-- 1 sakuma wheel 331 Jul 21 15:48 .mailrc
-rw------- 1 sakuma wheel 13791 Nov 12 11:34 .mysql_history
-rw-r--r-- 1 sakuma wheel 797 Jul 21 15:48 .profile
-rw------- 1 sakuma wheel 276 Jul 21 15:48 .rhosts
-rw------- 1 sakuma wheel 1024 Nov 6 08:39 .rnd
-rw-r--r-- 1 sakuma wheel 975 Jul 21 15:48 .shrc
drwx------ 2 sakuma wheel 512 Jul 19 04:40 .ssh
-r--r--r-- 1 sakuma wheel 1785 Jul 21 15:54 .tcshrc
-r--r--r-- 1 sakuma wheel 5515 Jul 21 15:54 .tcshrc.alias
-r--r--r-- 1 sakuma wheel 16158 Jul 21 15:54 .tcshrc.bindkey
-r--r--r-- 1 sakuma wheel 55095 Jul 21 15:54 .tcshrc.complete
-r--r--r-- 1 sakuma wheel 336 Jul 21 15:54 .tcshrc.hosts
-r--r--r-- 1 sakuma wheel 372 Jul 21 15:54 .tcshrc.local
-r--r--r-- 1 sakuma wheel 7993 Jul 21 15:54 .tcshrc.set
drwxr-xr-x 3 sakuma wheel 512 Jul 21 15:50 work
といった感じで使います.-lはリスト表示を行うこと,-aは隠しファイル(.(ドット)で始まるファイル)を表示する,というオプションで,この-laのことを,引数(ひきすう)と言います.
コマンドなどプログラムは,利用者が,コマンド名,プログラム名に続き,オプションやファイル指定などを,引数として渡すことで,挙動を左右するようになっています.
CGI は,Webサーバと連携し,利用者との通信を行った上で,何らかの計算を行い,その結果を利用者に返すための取り決めです.この,Webサーバとプログラムの連携を行う取り決めのことを,CGI(The Common Gateway Interface) として,RFC3875 などで定義されています.
CGI では,いわゆる CGI と言われている CGIプログラムと Webサーバ間の情報のやり取りのために,標準入出力と環境変数が使われます.
標準入出力は,一般的なプログラムやコマンドでも使われますが,CGI の場合,HTTP の POSTメソッドで送られたデータを,CGIプログラムの標準入力から取り出せるようになっています.また,GETメソッドの場合,URI の ?以降が,環境変数の QUERY_STRING として得られるようになっています.
CGI プログラムでは,これらの情報を元に,何らかの計算を行い,その結果を標準出力に出力します.すると,Webサーバはその内容を,利用者に返すようになっています.
ただし,出力で特殊なのが,内容だけではなく,HTTPヘッダの一部である,Content-type なども,CGIプログラムから出力してやる必要がある点です.HTTPヘッダとHTTPボディは,空行で分けられます.
最も簡単な CGIプログラムの例として,環境変数を表示する Perl のプログラムを書いてみたいと思います.行数は分かりやすいように表示しているだけなので,実際にはエディタでは入力しません.
1: #!/usr/bin/perl -w
2:
3: use strict;
4:
5: print "Content-type: text/plain\n";
6: print "\n";
7:
8: foreach (keys %ENV) {
9: print "$_ = ";
10: print "$ENV{$_}\n";
11: }
12:
13: exit();
これだけで,立派な CGI プログラムです.実行すると,環境変数が一覧になって表示されます.
以下は表示の一例です.
SCRIPT_NAME = /env.cgi
SERVER_NAME = jushi.bitcoffee.net
REQUEST_METHOD = GET
SERVER_SOFTWARE = Apache/2.0.61 (FreeBSD)
QUERY_STRING =
SERVER_PORT = 80
SERVER_PROTOCOL = HTTP/1.1
REQUEST_URI = /env.cgi
GATEWAY_INTERFACE = CGI/1.1
1行目はシェバング(shebang)といい,このプログラムを実行するための,プログラムのパスを書きます.Perl の場合,ほとんどは,この書き方で問題ありません.
3行目は Perl を書く時のおまじないです.変な書き方をした場合に,注意を表示してくれます.
5行目は前述した HTTPヘッダの Content-type の出力です.今回は単なるプレインテキストなので,text/plain を指定します.
6行目は HTTPヘッダと HTTPボディを分けるための空行です.ここから先が,ブラウザで表示される部分になります.
8行目からループが始まります.foreach関数は,カッコの中の引数の配列の個数分,ループが回転します.カッコの中の keys関数は,引数の連想配列の key の配列を返します.keys関数の引数になっている %ENV は環境変数を格納した連想配列です.
連想配列は,Perl でよく使われる変数で,key とそれと対になる value を一気に格納できる便利な変数です.例えば,環境変数の QUERY_STRING であれば,$ENV{QUERY_STRING} という書き方でアクセスすることができます.
9行目では,環境変数の連想配列 %ENV の key を表示しています.$_ は,foreach が自動的に,そのループの回転時の引数を格納します.keys関数の返す連想配列の key が例えば,HTTP_HOST の番であれば,$_ には HTTP_HOST が格納されています.
10行目では,環境変数の value を表示しています.連想配列の key に,$_ を使うことで,自動的に value を得ることができます.
HTTPの GETメソッドでは,URI の一部として,QUERY_STRING を使って,ブラウザから CGIプログラムに,引数を渡すことができます.QUERY_STRING は,それを含んだリンクを作って,利用者にたどってもらうこともできますし,HTML の form から生成することもできます.
HTML の form から生成する場合,QUERY_STRING は,key=value という形式で,引数分だけ,& でつないだ形になります.具体的には,
http://example.org/path.cgi?key1=value1&key2=value2&key3=value3
という URI になり,この,key1=value1&key2=value2&key3=value3 の部分が QUERY_STRING になります.CGI プログラム側では,これを解析して,引数として使うのですが,この形式は決まっているため,解析を行うためのモジュールがすでに用意されています.
それが,CGI.pm です.CGI.pm を使って,QUERY_STRING を表示するプログラムを書いてみます.
1: #!/usr/bin/perl -w
2:
3: use strict;
4: use CGI;
5:
6: my $cgi = new CGI;
7:
8: print "Content-type: text/plain\n";
9: print "\n";
10:
11: foreach ($cgi->param()) {
12: print "$_ = ";
13: print $cgi->param($_) . "\n";
14: }
15:
16: exit();
実行する際は,適当な QUERY_STRING を付けて,呼び出してみます.(querystring.cgi?hoge=fuga&foo=bar など)
4行目で,CGI.pm を使う宣言を行います.
6行目で,CGI のインスタンスを生成します.
11行目の $cgi->param() は,QUERY_STRING の key の配列を返します.
13行目で,得られた key を引数に $cgi->param($key) を実行し,value を得ます.