web-dev-qa-db-ja.com

304を返す要求を防ぐ方法

ブラウザがファイルのサーバーにリクエストを送信しないのはいつですか?

つまり、JavaScriptファイルが提供されています。そのHTTP応答ヘッダーには、ETagCache-Control: public、およびExpires: Tue, 19 Jan 2038 03:14:07 GMTがあります。

ブラウザのキャッシュが準備された後、サーバーは304を返します。

私の質問は、ブラウザがサーバーでチェックして、最初に304を取得するのはなぜですか?ブラウザに新しいバージョンがあるかどうかを尋ねて欲しくありません。スクリプトを提供するサーバーで変更をチェックせずに、ブラウザキャッシュから直接読み込む必要があります。

これを実現するHTTP応答ヘッダーの組み合わせは何ですか?

55
core

まず、関連するHTTP仕様は RFC 7234 です。仕様を見ると、次の2つのことがわかります。

  • 仕様では、requiredを決して必要とせず、キャッシュは再検証せずにコンテンツのキャッシュバージョンを提供します。キャッシュが要求を満たすためにキャッシュされたコンテンツを使用してはならないことを仕様が記述している場所はたくさんありますが、そうする必要がある、または再検証してはいけないと指示する場所はまったくありません。そのため、ブラウザーベンダーは、必要に応じていつでも自由に再検証できます。
  • 第二に、あなたはあなたの側で何も悪いことをしていない。ブラウザーは、応答をキャッシュし、返されたヘッダーを指定して、キャッシュされた応答を自由に使用できます。キーポイントは セクション4 にあり、キャッシュされた応答を提供するための条件の1つは、応答が次のいずれかであることです。

    • fresh(セクション4.2を参照)、または

    • 陳腐化することが許可されている(セクション4.2.4を参照)、または

    • 検証に成功しました(セクション4.3を参照)。

    未来のExpiresヘッダーを吐き出しているので、未来のその時点にまだ到達していないので、応答は「新鮮」であり、したがって再検証は必要ありません。だから、あなたはあなたの側にいるべきであると仕様が示唆するすべてをしている。 (Cache-Control: max-age=fooを使用することは、Expires:ヘッダーを使用するよりもキャッシュの有効期限を設定するより現代的な方法ですが。)

したがって、ブラウザのキャッシュ動作を変更する場合は、運が悪いです。

しかし、物事はあなたが思うほど悪くないかもしれません。テスト中にブラウザ内のページをrefreshingしているため、おそらくリクエストと304だけが表示されています。ブラウザは、リクエストがトリガーされた方法に応じて、キャッシュされたリソースを異なる方法で処理します。

JSファイルを指す<script>タグ、画像を指す<img>タグ、CSSスタイルシートを指す<link>タグを含むHTMLページを作成する簡単なテストを実行しました。これらのファイルはすべて、以下を提供するように構成されたApacheサーバーでホストされていました。

  • e-Tagヘッダー、
  • 最終更新日、
  • Cache-Control: max-age=172800ヘッダー

当然、最初のページの読み込み時にすべてのリソースに200コードが提供されていました。その後、Chromeでテストするか、Firefoxをデフォルト設定でインストールすると、次のことがわかりました。

  • あなたがrefresh F5 キーまたはRefreshボタン、ページおよびすべてのリソースが再検証されます(つまり、各リソースに対してサーバーに対してリクエストが行われ、304が返されます)。
  • リンクを介してページに戻るか、新しいタブのURLバーにURLを入力すると、no再検証が行われます(つまり、リクエストはありません)製)。
  • Chromeでは、URLバーを選択してEnterキーを押してページを更新すると、ページ自体が再検証されますが、他のリソースは更新されません。 Firefoxでは、ページもリソースも再検証されません。

このページ は、Internet Explorerの動作が同じであることを示します。

キャッシュされたエントリが有効かどうかを確認する必要があるInternet Explorerの状況はいくつかあります。

  • キャッシュされたエントリには有効期限がなく、ブラウザセッションで初めてコンテンツにアクセスしています
  • キャッシュされたエントリには有効期限がありますが、有効期限が切れています
  • ユーザーが[更新]ボタンをクリックするか、F5を押してページの更新を要求しました

つまり、通常、ユーザーがページを明示的に更新した場合にのみ、これらの再検証リクエストが表示されます。ブラウザーのキャッシュをどのように動作させるかについて非常に特別な要件がない限り、この動作は完全に合理的です。

GoogleMozilla の両方にHTTPキャッシングに関するドキュメントがあります(MSDNまたはApple Developersサイト)で同等のものは見つかりませんが、ただし、ブラウザが再検証のタイミングを選択するために使用するルールを変更するために使用できるベンダー固有のキャッシュヘッダーの存在を示唆するものでもありません。

この動作を本当に制御する必要がある場合は、 HTML5アプリケーションキャッシュ を調べるか、 basket.js のように、HTML5ローカルストレージを使用して独自のキャッシュロジックをロールします。

89
Mark Amery

Expires: または Cache-Control: max-age=動作するはずです。ブラウザが実際にネットワーク呼び出しを行っていることをサーバーログで確認しましたか?たとえば、firebugには、キャッシュを実際にヒットしているときにリモート呼び出しを行っていることを示唆するわかりにくい出力があることがわかりました。

0
James Scriven

私のボートにいて、AngularアプリをIISにデプロイしている場合、次のように、web.configがURLを正しく書き換えるように構成されていることを確認してください。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <rules>
                <rule name="Angular Routes" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />
                </rule>
            </rules>
        </rewrite>
  </system.webServer>
</configuration>

<action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />のurlの値に特に注意してください

0
Adam Cox