同じ問題、同様の解決策
If-None-Match
開発中のサイトにアクセスしたときに Google Chrome がヘッダーを送信しない理由を突き止めようとしています。(Chrome 46.0.2490.71 m ですが、バージョンの関連性はよくわかりません。)
これは、最終的に引用されたOPとは異なる(非常に似ていますが)回答ですが(承認された回答に関するコメントで)、同じ問題に対処しています:
ブラウザーは、「必要な場合」に後続の要求でヘッダーを送信しませんIf-None-Match
(つまり、最初の応答でETag
orヘッダーを送信するために、PHP などを介したサーバー側のロジックが使用されています)。Last-Modified
前提条件
Chrome でロックを赤くする自己署名 TLS 証明書を使用すると、Chrome のキャッシュ動作が変わります。この性質の問題のトラブルシューティングを試みる前に、 https://stackoverflow.com/a/19102293で説明されているように、有効な信頼されたルート ストアに自己署名証明書をインストールし、ブラウザを完全に再起動してください。
最初のエピファニー: If-None-Match はサーバーからの ETag を必要とします。
サーバーが以前のリクエストに応答してヘッダーを送信するIf-None-Match
まで、Chrome (およびおそらく他のほとんどまたはすべてのブラウザー) はヘッダーを送信しないことにすぐに気付きました。論理的には、これは完全に理にかなっています。結局のところ、値が与えられていない場合、Chrome はどのように送信できるのでしょうか? ETag
If-None-Match
これにより、サーバー側のロジック、特に、ユーザー エージェントに応答をキャッシュさせたい場合にヘッダーが送信される方法を調べて、ETag
Chrome の最初の応答でヘッダーが送信されない理由を特定しようとしました。リソースのリクエスト。ETag
アプリケーションロジックにヘッダーを含めるために計算された努力をしました。
私はたまたまPHPを使用していたので、@ Mehranの(OPの)コメントが飛び出しました(彼/彼女はheader_remove()
、必要なキャッシュ関連のヘッダーを送信する前に呼び出すと問題が解決すると言っています)。
率直に言って、私はこのソリューションに懐疑的でした。なぜなら、a) PHP はデフォルトで独自のヘッダーを送信しないと確信していたからです (そして、私の構成では送信しません)。b) var_dump(headers_list());
PHP でカスタム キャッシング ヘッダーを設定する直前に呼び出したとき、ヘッダー セットは、意図的にすぐ上に設定していたものだけでした。
header('Content-type: application/javascript; charset=utf-8');
それで、失うものは何もないので、header_remove();
カスタムヘッダーを送信する直前に呼び出してみました. そして驚いたことに、PHP はETag
突然ヘッダーを送信し始めました!
2 番目の Epiphany: 応答を gzip 圧縮すると、ハッシュが変更されます
PHP でヘッダーを指定することで、Content-type
NGINX (私が使用している Web サーバー) に、PHP が応答を NGINX に返したら GZIP するように指示していました。明確にするためにContent-type
、私が指定していたのは、NGINX の gzip のタイプのリストにありました。
完全を期すために、私の NGINX GZIP 設定は次のとおりであり、PHP は php-fpm を介して NGINX に接続されています。
gzip on;
gzip_min_length 1;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
gzip_vary on;
「gzippable」コンテンツタイプが指定されているときに、なぜNGINXがETag
PHPで送信した. これは完全に理にかなっています。ETag
生成に使用された応答と一致しない場合にを送信しても意味がありません。NGINX がこのシナリオを非常にインテリジェントに処理するのは非常に巧妙です。
NGINX が、圧縮されていないがヘッダーを含むETag
応答本文を圧縮しないほど常にスマートであるかどうかはわかりませんが、それがここで起こっているようです。
更新:この点に関する NGINX の動作を説明する解説を見つけました。これは、この主題に関する 2 つの貴重な議論を引用しています。
- 動作について議論している NGINX フォーラム スレッド。
- プロジェクト リポジトリでの接線方向の議論。コメントを参照してください
Posted on Jun 15, 2013 by Massive Bird
。
この貴重な説明を保存するために、もしそれが消えてしまった場合、私Massive Bird
は の議論への貢献から引用します:
Nginx は、オンザフライで応答を gzip するときに Etag を取り除きます。gzip されていない応答は、gzip された応答に匹敵するバイト単位ではないため、これは仕様によるものです。
ただし、この点に関するNGINXの動作は、同じ仕様であるという点でわずかに欠陥があると見なされる場合があります
... また、weak Etags (W/ で始まる Etag 値) と呼ばれるものがあり、応答が意味的に同等であるかどうかを確認するために使用できることを示しています。その場合、Nginx はそれを台無しにすべきではありません。残念ながら、そのチェックがソース ツリーに反映されることはありませんでした [悲しいことに、引用は現在スパムでいっぱいです]。」
この点に関するNGINXの現在の性質、特に「弱い」Etagsのサポートが追加されているかどうかについては不明です.
それで、解決策は何ですか?
ETag
では、応答に戻るための解決策は何ですか? PHP で gzip を実行して、NGINX が応答が既に圧縮されていることを確認し、ETag
ヘッダーをそのままにして単純に渡すようにします。
ob_start('ob_gzhandler');
ヘッダーと応答本文を送信する前にこの呼び出しを追加すると、PHP はETag
すべての応答で値を送信し始めました。はい!
その他の教訓
以下は、私の調査から得られた興味深い情報です。この情報は、PHP であれ他の言語であれ、サーバー側のキャッシングの実装をテストする際に便利です。
Chrome とその開発者ツールの「ネット」パネルは、リクエストの開始方法によって動作が異なります。
たとえば を押すなどして、リクエストが「新しく」作成された場合Ctrl+F5
、Chrome は次のヘッダーを送信します。
Cache-Control: no-cache
Pragma: no-cache
サーバーが応答します200 OK
。
のみでリクエストが行われた場合F5
、Chrome は次のヘッダーを送信します。
Pragma: no-cache
サーバーが応答します304 Not Modified
。
最後に、既に表示しているページへのリンクをクリックするか、Chrome のアドレス バーにフォーカスを置いて Enter キーを押すことによってリクエストが行われた場合、Chrome は次のヘッダーを送信します。
Cache-Control: no-cache
Pragma: no-cache
サーバーが応答します200 OK (from cache)
。
この動作は最初は少し混乱しますが、どのように機能するかがわからない場合は、理想的な動作です。これにより、考えられるすべての要求/応答シナリオを非常に徹底的にテストできるからです。
おそらく最も紛らわしいのは、実際には Chrome がキャッシュから応答を取得しているときに (応答で証明されているように)、Chrome が自動的に発信要求にヘッダーCache-Control: no-cache
とヘッダーを挿入することです。Pragma: no-cache
200 OK (from cache)
この経験は私にとってかなり有益であり、他の人が将来この価値の分析を見つけてくれることを願っています.