CGIを作ろう

文 :
Write :

概要

世の中に,CGI を作るための解説本や開設サイトは多々ありますが,初心者はプログラミングの説明などばかりで,なかなか本題の CGI について学ぶことができないのではないかと思います.

初心者が躓く原因として,解説本の多くが,プログラミングの解説に重点を置いており,CGI についての説明や,HTTP,httpd などについての解説が少ない点があると思います.

今後,数回にわたり,実際に CGI を作りながら,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 を得ることができます.

CGI.pm

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 を得ます.

Welcome spammers. If you are spammer, please mail to honeypot@bitcoffee.com. Thanks your spam!!