ブラウザキャッシュの挙動を見てみる
改めて勉強したかったので、こんなテストしてみました。
Apacheの設定とテスト内容
<VirtualHost *:80> ServerAdmin zigorou@localhost DocumentRoot /home/zigorou/www/cache ServerName cachetest.art-code.org ExpiresDefault "access plus 5 minutes" Alias /test1 /home/zigorou/www/cache/test Alias /test2 /home/zigorou/www/cache/test Alias /test3 /home/zigorou/www/cache/test <Location /test1> FileETag None ExpiresActive Off </Location> <Location /test2> FileETag Size ExpiresActive Off </Location> <Location /test3> FileETag Size ExpiresActive On </Location> </VirtualHost>
どういう設定かまとめると、
test no | FileETag | ExpiresActive |
---|---|---|
1 | None | Off |
2 | Size | Off |
3 | Size | On |
ってなってて、それぞれのパスに対してIf-Modified-Since, If-None-Match, Cache-Controlヘッダを飛ばしながら200 or 304なのかどうか調べてみる。
テストスクリプト
最近のエントリはこれに繋がってた次第ですがw
#!/usr/bin/perl use strict; use warnings; use Data::Dump qw(dump); use DateTime; use DateTime::Format::HTTP; use HTTP::Request; use LWP::UserAgent; use Set::CrossProduct; use Text::SimpleTable; my $date = DateTime::Format::HTTP->format_datetime(DateTime->now - DateTime::Duration->new(minutes => 30)); my $entries = { 'Cache-Control' => [q|no-cache|, q|max-age=0|, undef], 'If-None-Match' => [q|"2232"|, q|"2222"|, undef], 'If-Modified-Since' => [$date, undef] }; sub request { my ($url, $headers) = @_; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new('GET', $url); for (keys %$headers) { $req->header($_, $headers->{$_}) if ($headers->{$_}); } my $res = $ua->request($req); return ($req, $res); } my $cp = Set::CrossProduct->new([values %$entries]); my @headers = (); for my $header_vals ($cp->combinations) { my %header; @header{keys %$entries} = @$header_vals; push(@headers, \%header); } for my $idx (1..3) { my $table = Text::SimpleTable->new([6, "no"], [20, "Cache-Control"], [20, "If-None-Match"], [20, "If-Modified-Since"], [7, "status"]); my $url = sprintf("http://cachetest.art-code.org/test%d/logo.gif", $idx); my $hidx = 0; for my $header (@headers) { my ($req, $res) = request($url, $header); $table->row(++$hidx, values %$header, $res->code); } print "test$idx results: \n"; print $table->draw; }
ちなみに正しいETagは2232です。
あと、実験でアクセスしてるファイルのstatは、
$ stat test/logo.gif File: `test/logo.gif' Size: 8754 Blocks: 12 IO Block: 1024 ・evice: 3cb4a463h/1018471523d Inode: 844424930313348 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1006/zigorou) Gid: ( 513/ zigorou) Access: 2007-08-13 20:14:28.437500000 +0900 Modify: 2007-08-13 20:14:28.437500000 +0900 Change: 2007-08-13 20:14:28.437500000 +0900
で昨日がLast-Modifiedになってます。
実験結果
FileETag: None, ExpiresActive Offの場合
まずは結果。
test1 results: .--------+----------------------+----------------------+----------------------+---------. | no | Cache-Control | If-None-Match | If-Modified-Since | status | +--------+----------------------+----------------------+----------------------+---------+ | 1 | no-cache | "2232" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 2 | no-cache | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 3 | no-cache | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 4 | no-cache | "2232" | | 200 | | 5 | no-cache | "2222" | | 200 | | 6 | no-cache | | | 200 | | 7 | max-age=0 | "2232" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 8 | max-age=0 | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 9 | max-age=0 | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 10 | max-age=0 | "2232" | | 200 | | 11 | max-age=0 | "2222" | | 200 | | 12 | max-age=0 | | | 200 | | 13 | | "2232" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 14 | | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 15 | | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 16 | | "2232" | | 200 | | 17 | | "2222" | | 200 | | 18 | | | | 200 | '--------+----------------------+----------------------+----------------------+---------'
ここから分かるのはIf-None-Matchヘッダを送ると、有無を言わさずキャッシュが無効になり、新しいコンテンツをWebサーバーが返すって事。
Cache-Controlのno-cache, max-age=0とかは全然無関係。
なのでこの状態で有効なヘッダはIf-Modified-Since, If-None-Matchで、If-None-Matchはキャッシュ無効に無条件になり、無かったときにLast-ModifiedとIf-Modified-Sinceの比較が行われて、Last-Modified以降の日時をIf-Modified-Sinceで送っておけば304が返って来る。
FileETag: Size, ExpiresActive Offの場合
結果はこちら。
test2 results: .--------+----------------------+----------------------+----------------------+---------. | no | Cache-Control | If-None-Match | If-Modified-Since | status | +--------+----------------------+----------------------+----------------------+---------+ | 1 | no-cache | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 2 | no-cache | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 3 | no-cache | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 4 | no-cache | "2232" | | 304 | | 5 | no-cache | "2222" | | 200 | | 6 | no-cache | | | 200 | | 7 | max-age=0 | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 8 | max-age=0 | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 9 | max-age=0 | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 10 | max-age=0 | "2232" | | 304 | | 11 | max-age=0 | "2222" | | 200 | | 12 | max-age=0 | | | 200 | | 13 | | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 14 | | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 15 | | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 16 | | "2232" | | 304 | | 17 | | "2222" | | 200 | | 18 | | | | 200 | '--------+----------------------+----------------------+----------------------+---------'
正しいETagを送ってれば、304が返って来る。逆にETagが誤っていると無条件に新しいコンテンツを取らなくてはならない。
あとはtest1と同等。
やはりCache-Controlは無関係っぽぃ。
FileETag: Size, ExpiresActive Onの場合
結果はtest2と同じ。
test3 results: .--------+----------------------+----------------------+----------------------+---------. | no | Cache-Control | If-None-Match | If-Modified-Since | status | +--------+----------------------+----------------------+----------------------+---------+ | 1 | no-cache | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 2 | no-cache | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 3 | no-cache | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 4 | no-cache | "2232" | | 304 | | 5 | no-cache | "2222" | | 200 | | 6 | no-cache | | | 200 | | 7 | max-age=0 | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 8 | max-age=0 | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 9 | max-age=0 | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 10 | max-age=0 | "2232" | | 304 | | 11 | max-age=0 | "2222" | | 200 | | 12 | max-age=0 | | | 200 | | 13 | | "2232" | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 14 | | "2222" | Tue, 14 Aug 2007 07- | 200 | | | | | :59:19 GMT | | | 15 | | | Tue, 14 Aug 2007 07- | 304 | | | | | :59:19 GMT | | | 16 | | "2232" | | 304 | | 17 | | "2222" | | 200 | | 18 | | | | 200 | '--------+----------------------+----------------------+----------------------+---------'
何が違うかと言えば、
Cache-Control: max-age=300 Expires: Tue, 14 Aug 2007 08:43:02 GMT
のようにCache-Control, Expiresヘッダをレスポンスヘッダで返すって事。
これをブラウザが受け取り通常、期限が切れて居ない場合はリクエスト自体飛ばさない事になる。
あと、奥さんのエントリも同様に見ると勉強になります。