クッキーで接続状態の保持
 

WWWの世界では、HTTPプロトコルが用いられていますがHTTPは一組のリクエスト/レスポンスで成り立っています。つまり、ブラウザがあるページを見たいという要求をWebサーバに送り、WebサーバはHTMLなどのコンテンツを送り返します。Webページのブラウズは、これの繰り返しです。それぞれの処理後(ブラウザにページが表示された直後)にはWebサーバとブラウザの接続が切れるわけです。つまり、状態の保持ができません。
CGIを使う場合、連続したページ間で状態を保持するには <FORM> タグの中で <INPUT TYPE="hidden" ...> で受け渡すことができますが、これだとブラウザを終了させてしまうと、その情報は残りません。そこでクッキーが登場するわけです。
クッキーのしくみも非常に簡単です。クッキーはHTTPのリクエスト/レスポンスのヘッダ中に埋め込まれてやりとりされます。すなわち、その内容はユーザーの目に触れることはありません。クッキーの利用に不安をもたれる一つの理由もここにありますが、その内容や情報の利用の目的をユーザに公開して不安を取り除いてあげると、クッキーを有効に活用できるはずです。

クッキーに関する仕様はNetscape Communications社が公開しています。
http://www.netscape.com/newsref/std/cookie_spec.html

クッキーを使う場合に始めにやりとりされるのは、WebサーバからのHTTPレスポンスのヘッダに

Set-Cookie: Name=Value; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure

を設定します。以降、有効期限が切れるまでブラウザ側のローカルディスクにクッキーが保存され、次のリクエストのときに自動的に送信されます。Name=Valueにいろいろな情報を設定し、その他は省略可能です。
 
Name=Value クッキーの名前がNameです。それに対応する値がValueです。セミコロンや空白文字、カンマなどの特殊文字は利用できませんが、%16進数で表現して使うことが推奨されています。日本語コードの場合も同様です。
expires=DATE クッキーの有効期限です。有効期限が切れたクッキーは無効になります。DATEは
Mon, 25-Jan-1999 01:13:47 GMT
のような書式です。タイムゾーンはGMTのみです。省略した場合は、ブラウザを終了させるとクッキーは消滅します。
path=PATH Webサーバ内のどのデータを要求するときに必要かを記述します。PATH=/Info
と指定した場合は、/Info 以下のデータが要求されたときにクッキーが送られます。省略した場合は、Set-Cookieが送られてきたパスとなります。
domain=DOMAIN_NAME どのWebサーバへクッキーを送り返してもらうかを指定します。
Set-Cookieを送ったWebサーバがwww1.domain.co.jpでも
domain=www2.domain.co.jp
ならばクッキーはwww1.domain.co.jpには送られずwww2.domain.co.jpに送られます。
domain=.domain.co.jp
とするとwww1.domain.co.jpとwww2.domain.co.jpの両方に送られます。省略された場合は、Set-Cookieを送ったWebサーバになります。
secure クッキーがHTTPSでの暗号化などの安全性の確保ができる手段が使える場合のみに送られます。

クッキーファイルはWindowsのNetscape Communicatorだと
\Program Files\Netscape\Users\<User Name>\cookie.txt
にあり、UNIXのNetscape Communicatorだと
$HOME/.netscape/cookies
にあります。詳しくはブラウザのドキュメントを参照してください。
 

このサンプルプログラムでは、ブラウザを終了するまでCountがアップします。途中で全く関係のないページを表示したあともCountが保持されます。ブラウザの「戻る」ボタンで戻った場合でも保持されます。

[サンプルプログラムの実行]
 
 
cookie.cgi
#!/usr/bin/perl
#
# cookie.cgi
#
# (C)1999 Kaoru Fujita
#
use lib './lib';
require 'jcode.pl';

#
# 定数
#

#
# 変数
#
$cookie = false;


#
# メインプログラム
#

if ($ENV{'HTTP_COOKIE'}) {
        *data = getCookie($ENV{'HTTP_COOKIE'});
        $count = $data{'Count'};
        $count++;
}
else {
        # 初回のアクセスでは 0 を設定する。
        $count = 0;
}

#Set-Cookie: Count=$count\; expires=$ENV{'DATE'}+1minutes\; path=\; domanin=\; secure\

print <<ENDOFHTML;
Content-type: text/html
Set-Cookie: Count=$count;


<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
Count: $count<BR>
<FORM ACTION="/cgi-bin/cookie.cgi" METHOD="POST">
<INPUT TYPE="submit" VALUE="Next">
</FORM>
</BODY>
</HTML>
ENDOFHTML

exit(0);


sub getCookie
{
        local($cookie) = $ENV{'HTTP_COOKIE'};
        local(*data, @cookie);

        @cookie = split(/ /, $cookie);

        foreach (@cookie) {
                local($name, $val) = split(/=/);
                $data{$name} = $val;
        }

        return *data;
}

#--End of cookie.cgi