CGIプログラミング(1)

CGIとは

World Wide Webには、ユーザがWebブラウザに入力したデータを受け取って、 それをプログラムによって処理して、応答を返す仕組みが用意されている。 そのような仕組みの中で、古くからあり、広く使われているものにCGIがある。

CGIはCommon Gateway Interfaceの略で、Webサーバからプログラムを実行する場合の規定(決まり事)である。 CGIの仕組みによってWebサーバから起動されたプログラムをCGIプログラムという。 また、CGIプログラムのうちスクリプト言語で書かれたものをCGIスクリプトと呼ぶ。 CGIプログラムは特に開発言語は問われない。例えばCを使うことも可能である。 しかし、実際には、手軽なスクリプト言語を使うことが多く、Perlが広く使われている。ここではPerlを使ってCGIプログラムを作成する。

CGIの典型的な使用例として以下のようなものがある。

CGIの仕組み

CGIが動作する時には、以下のような手順を踏む。

これを図で書くと以下のようになる。

通常のHTMLファイルにアクセスした場合

CGIにアクセスした場合

一番簡単なCGI

ここで、ごく簡単なCGIプログラムを作成する。まずユーザからの入力は考えず、 決まったメッセージ"Hello CGI's World!"を表示するプログラムを実行する。

hello.cgi - 簡単なCGIプログラム
#!/usr/bin/env perl
print "Content-Type: text/html\n\n";
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">\n";
print "<html lang=\"ja\">\n";
print "<head>\n";
print "<title>CGI Test</title>\n";
print "</head>\n";
print "<body>\n";
print "Hello CGI's World!\n";
print "</body>\n";
print "</html>\n";
このプログラムは、常に以下のような決まった内容を出力する。
hello.cgi が標準出力に出力する内容
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html lang="ja">
<head>
<title>CGI Test</title>
</head>
<body>
Hello CGI's World!
</body>
</html>

CGIの作成手順

  1. 上記 hello.cgi を、例えば ~/public_html 上に作成する。
  2. setwwwを実行してパーミッションを設定する。 setwwwについては、情報教育システムの環境で CGIを使用する方法を見よ。
  3. Webブラウザからアクセスする。例えば、~/public_html 上に作成したなら、 http://www.edu.tuis.ac.jp/~ユーザ名/hello.cgi というURLでアクセスする。
  4. Hello CGI's World! と表示されれば成功。

※ 以上のCGIファイル作成は、以下の手段のいずれかを用いることを勧める。

おさらい:emacsの主要コマンド(C-■はCtrlキーを押しながら■を押す)

CGIプログラムの説明

上記のhello.cgiの内容を順に説明する。

1行目は#から始まるので単なるコメントのようだが、意味がある。 この行を先頭につけることで、このファイルはコマンドとして実行できるようになる。 さらに、CGIとして実行するには、ファイルがWebサーバから読み取り可で実行可でなければならない。 chmod コマンドでそのように設定せよ。
※ 本学のシステムの場合は、設定が違う。 情報教育システムでCGIを使用する方法にあるようにsetwwwコマンドを使用せよ。

2行目は、Content-Type: text/htmlと標準出力に表示して、その後改行を2つ表示している。 これは、http形式でHTMLを出力する際の決り文句である。 標準出力について復習したい人は、UNIXの標準入出力とリダイレクションを見よ。

3行目以降は、HTMLの内容を標準出力に表示している。 HTMLファイルとして作ってあるものと同じものをprint文で表示しているのである。

ヒアドキュメントを使う

以上は、1行出力するたびにprint文を使っていたが、 ヒアドキュメントという仕組みをつかえばもっと簡単に書ける。 以下のプログラムを実行すると上記のプログラムと同じ結果になる。

#!/usr/bin/env perl
print << "END";
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title>CGI Test</title>
</head>
<body>
Hello CGI's World!
</body>
</html>
END

※ 最後のENDの行は改行が必要。改行がないとエラーになるので注意。

2行目にprint << "END"; と書くと、 その後のENDと書かれた行までの間を表示する。 もし、表示したい内容にENDという行を含めないといけない場合は、 例えば、print << "EOS";として、 文字列の最後もEOSにして合わせる。 なお、print << "END";と書いても、 END2など、完全にENDと等しい行でない場合は、 文字列の最後とは見なされない。

日本語を表示するには:

2つの方法がある。
  1. 通常のHTMLファイルと同様にmetaタグで文字コードを指定する。
    以下はUTF-8コードの場合の例である。
    #!/usr/bin/env perl
    print << "END";
    Content-Type: text/html
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
    <html lang="ja">
    <head>
    <title>CGI Test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    日本語のテストです
    </body>
    </html>
    END
    なお、ヒアドキュメントを使わずに、print文を使った場合は、"の表示するには\"と書くことに注意すること。例えば、上記のmetaタグの行の場合は以下のようになる。
    print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
  2. 先頭のContent-type:ヘッダで文字コードを指定する。
    以下はUTF-8コードの場合の例である。
    #!/usr/bin/env perl
    print << "END";
    Content-Type: text/html; charset=UTF-8
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
    <html lang="ja">
    <head>
    <title>CGI Test</title>
    </head>
    <body>
    日本語のテストです
    </body>
    </html>
    END

変数の値を表示する

print文で表示する内容に変数を入れることができる。 perlの場合、変数は変数名の前に$を付ける。また、変数の宣言は必要ない。

var.cgi - 変数の値を表示するプログラム
#!/usr/bin/env perl
$answer = 100/3;
print "Content-Type: text/html\n\n";
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">\n";
print "<html lang=\"ja\">\n";
print "<body>\n";
print "100/3 = $answer\n";
print "</body>\n";
print "</html>\n";

課題

  1. 以下のように自分の学籍番号と名前を表示するCGIを作成せよ。
    私は学籍番号s05987の情報太郎です。
  2. 乱数を使ってさいころを振った値を表示するCGIで作成せよ。 Perlで乱数を使う方法は以下のプログラムを参考にせよ。
    #!/usr/bin/env perl
    $random = int(rand(100)); # 0から99までの範囲で一様分布疑似乱数を発生する
    print $random, "\n";
    
  3. 現在の時刻(時、分、秒)を表示するCGIを作成せよ。現在の時刻の表示方法は以下のプログラムを参考にせよ。
    #!/usr/bin/env perl
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
    $year += 1900;
    $mon ++;
    print "現在の時刻は、$hour時 $min分 $sec秒です\n";
    print "本日は、$year年 $mon月 $mday日です\n";
    

東京情報大学情報システム学科
大見 嘉弘(Yoshihiro OHMI)
<ohmi@rsch.tuis.ac.jp>