週末には少しPerlを。

Perlスクリプトの学習日記です。

CGIプログラムでcookieに大きなサイズの情報を詰め込む実験をしてみる

HTTP cookieとは

Wikipedia によると

RFC 6265などで定義されたHTTPにおけるウェブサーバとウェブブラウザ間で状態を管理する
プロトコル、またそこで用いられるウェブブラウザに保存された情報のこと

おそらく日常で無意識的に使っているモノのだと思うのですが私は恥ずかしながら技術の詳細を理解せず今日まで来ています。

さて、クッキーに保存できる情報の大きさは当然ながら有限でありまして RFC HTTP 6265 State Management Mechanism の中の 6.1. Limits によれば、

   Practical user agent implementations have limits on the number and
   size of cookies that they can store.  General-use user agents SHOULD
   provide each of the following minimum capabilities:

   o  At least 4096 bytes per cookie (as measured by the sum of the
      length of the cookie's name, value, and attributes).

   o  At least 50 cookies per domain.

   o  At least 3000 cookies total.

しかしながら実際のところ、どこまで大きな情報を格納できるものかをひとつ自分のプログラムで試してみようと思った次第です。

Firefoxでのcookieの確認方法

格納可能な情報サイズはおそらくブラウザによっても異なるはずですが、今回はFirefox Ver.21で試します。 クッキーを確認する方法は、

  1. メニューバーから「ツール」-「ページの情報」をクリック。
  2. ダイアログウィンドウの「セキュリティ」-「プライバシーと履歴」に「Cookieを表示」ボタンがあります。

CGI.pmのcookie()

CGI.pmには cookieを扱うためのメソッド が準備されておりまして、これを利用してこんなCGIを設置してみました

#!/usr/bin/perl

use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $ck = $q->cookie(
    -name => 'z',
    -value => 'c' x 4095,
     );

print $q->header(-cookie => $ck);

print $q->start_html('cookie test');
print "This is cookie test.";
print $q->end_html;

このCGIにFirefoxでアクセスして前記の方法で確認すると、たしかに「z」という名前で「c」の行列を見ることができます。

複数のcookieを格納する

「At least 50 cookies per domain」とのRFC文書の記載から、次のように変更してみました。

my @cks;
for (1..50) {
    push @cks, $q->cookie(-name => sprintf("c%03d", $_), -value => 'c' x 4092);
}
print $q->header(-cookie => \@cks);

名前が3バイト増加した分、valueの大きさを減らして4092にしています。 このCGIにFirefoxでアクセスして確認したところ、たしかに50個のcookieが保存されていました。

ではさらに多くのcookieをとループの部分を0~999までにしたところ、 Firefoxではc850~c999までの150個のみが確認できました。

サーバー側のtcpdumpで850番より小さな番号のcookieもヘッダに入っていることを確認できましたので どうやらFirefox側で廃棄しているようです。

まとめ

RFC文書に曰く「Servers SHOULD use as few and as small cookies as possible」 とのことであります。