Apacheが生成するものと一致するエタグを作りたいと思っています。どのようにして、Apacheはetagsを作成しますか?Apacheにマッチするエタグをどうやって作っていますか?
答えて
Apacheは、iノード・ファイルサイズ・ファイルのmtimeの標準フォーマットを使用しています。これに対する唯一の注意点は、mtimeはエポックタイムでなければならず、ゼロが埋め込まれているため16桁であることです。 PHPでそれを行う方法は次のとおりです:
$fs = stat($file);
header("Etag: ".sprintf('"%x-%x-%s"', $fs['ino'], $fs['size'],base_convert(str_pad($fs['mtime'],16,"0"),10,16)));
あなたのページを動的に生成しているのであれば、これはおそらく意味がありません。 PHPを使用している場合は、メインスクリプトのinodeとファイルサイズを選択できますが、データが変更されたかどうかは変更時にはわかりません。良いキャッシングプロセスや静的ページを生成しない限り、etagsは役に立ちません。良いキャッシングプロセスがある場合、iノードとファイルサイズはおそらく無関係です。
編集:etagが何であるかわからない人のために、コンテンツが変更されたときに変更される値であると考えられています。ブラウザはWebサーバーからetagを取得し、キャッシュされたコピーのetagと比較し、etagが変更された場合はページ全体を取得します。 ApacheのEtagsとについて覚えておくべき
このアプローチは、PHPを介してストリームファイルをダウンロードするスクリプトや、レスポンスが実際にリクエストごとに動的でないその他の状況に役立ちます。 –
(クリスから)上記の答えはうまく動作しますが、sprintfの中で暗黙のキャストを使用して単純化することができます。
sprintf('"%x-%x-%x"', $s['ino'], $s['size'], str_pad($s['mtime'], 16, "0"));
パディングが進に変換した後に適用されるため、ザ・が%016x
が動作しない提案、以前よりもむしろ。
これは**動作しません**、理由は分かりません。なぜなら%xは 'int'を入力として必要とするからでしょうか? – Halcyon
@FritsvanCampen:それはそれより少し複雑です。 'sprintf'は文字列を' int'にキャストしようとしますが、これらの数値は大きすぎるのでオーバーフローして問題を引き起こします。溶液を代わりfloat' '使用することである:'はsprintf( ' "%X-%X-%X"'、$ S [ 'イノ']、$ S [ 'サイズ']、(フロート)str_pad($ S [ 'mtime']、16、 '0')) '。 –
なぜ 'ヘッダ(のsprintf( 'のEtag: "%X-%X-%の016x"'、$ FS [ 'イノ']、$ FS [ 'サイズ']、$ FS [ 'のmtime'])) ; '? –
私は、ApacheサーバのETagのMTime部分が実際には多くのプリシーザMTimeを持っていることに気がつきました。それはマイクロ秒も使用しています。ですから、Apacheが正確にETagを生成したいのであれば、mtimeの微小時間が必要になります。私の知る限り、これはPHPでは不可能です。しかし、あなたができることは、ApacheのMTimeが_close enough_(<1秒)であるかどうかをチェックすることです。したがって、少なくとも「304 Not Modified」を返すことができます。 – Halcyon