静的ページに見せかけるために調べてみた。
Google で検索したところ、drry+@-> PHP で Apache 風 ETag の生成が見つかった。この方法だと、確かにハイフンで区切られた最後の部分が、Apache で生成されるべき値ではなかった。
そこで少し調べてみた。まず、「そもそもファイルの更新時刻ではない」というところから。これは Apache のドキュメントにファイルの更新時刻を ETag 生成に利用できると書いてあるので否定される。つまり、最後のパートはファイルの更新時刻となる。
続いて「ファイルの更新時刻だけなのか」という点について。これについてはファイルの更新時刻を変更するほか無い。ファイルの更新時刻にだけ依るならば、2 つ以上の内容の異なるファイルで、唯一更新時刻だけを同じにすれば分かる。ファイルの更新時刻を任意に設定するには touch コマンドを使うと便利。例えば 2007-08-12T01:23:45 に設定するならば、touch -t 200708120123.45 FILENAME となる。結果、最後のパートは同じ ETag が生成されたので更新時刻にだけ依ると分かった。
そして最後は「更新時刻を基にハッシュ値を用いているのではないか」という点。ハッシュ値ならば諦めるしかないかと思ったが、Apache のソースコードより httpd-2.2.4/modules/http/http_etag.c に含まれる ap_make_etag 関数を見てみるとハッシュ値ではないと分かった。
ap_make_etag 関数の一部
if (etag_bits & ETAG_INODE) {
next = etag_ulong_to_hex(next, (unsigned long)r->finfo.inode);
bits_added |= ETAG_INODE;
}
if (etag_bits & ETAG_SIZE) {
if (bits_added != 0) {
*next++ = '-';
}
next = etag_ulong_to_hex(next, (unsigned long)r->finfo.size);
bits_added |= ETAG_SIZE;
}
if (etag_bits & ETAG_MTIME) {
if (bits_added != 0) {
*next++ = '-';
}
next = etag_ulong_to_hex(next, (unsigned long)r->mtime);
}というわけで、恐らく利用されている mtime が違うのだろうということが分かった。因みに ap_make_etag 関数中で利用されている etag_ulong_to_hex 関数は、単純に long 型を 16 進数に変換しているだけである。
あとは複数のサンプルを取って、数学的に解くほか無い。まず 1 秒ごとに更新時刻を変更したファイルにアクセスし、ETag がどのように変化するか調べた。
- a296aac0 (12:20:35)
- a2a5ed00 (12:20:36)
- a2b52f40 (12:20:37)
差を取ると、どれも F4240(16)、即ち 1,000,000 だった。ということで、drry+@-> PHP で Apache 風 ETag の生成を次のように変えると Apache と全く同じ ETag を生成できる。
修正した ETag 生成コード
$etag = sprintf( '"%x-%x-%x"', $stats['ino'], $stats['size'], $stats['mtime'] * 1000000 );
これからすると、Apache の内部では更新時刻をマイクロタイム単位で扱っているようだ。
Related Entries
There is not related articles.
Trackbacks
Trackback URI: http://blog.c--v.net/trackback/2007/08/12/1
There is no trackback.
There is no comment.