IIS 7は200ではなく304を返す


10

IIS 7で奇妙な問題があります。
時々、200ではなく304を返すようです。

以下は、Fiddlerでキャプチャされたサンプルリクエスト
です。

GET https://[mysite]/Content/js/jquery.form.js HTTP/1.1
Accept: */*
Referer: https://[mysite]/Welcome/News
Accept-Language: sv-SE
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: [mysite]
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ...

リクエストにIf-Modified-SinceまたはIf-None-Matchがないことに注意してください。
しかし、それでも応答は次のとおりです。

HTTP/1.1 304 Not Modified
Cache-Control: public
Expires: Tue, 02 Mar 2010 06:26:08 GMT
Last-Modified: Mon, 22 Feb 2010 21:58:44 GMT
ETag: "1CAB40A337D4200"
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Mon, 01 Mar 2010 17:06:34 GMT

誰かがここで何が間違っているのか手掛かりを持っていますか?

Windows Web Server 2008 R2でIIS 7を実行しています。

編集:

私は回避策を見つけました。キャッシュを有効にしてから、拡張レベルで無効にするとうまくいきました。

<configuration>
  <system.webServer>
    <caching enabled="true" enableKernelCache="true">
      <profiles>
        <add extension=".png" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".gif" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".css" policy="DisableCache" kernelCachePolicy="DisableCache" />
      </profiles>
    </caching>
    <staticContent>
      <clientCache cacheControlMode="NoControl" />
    </staticContent>
  </system.webServer>
</configuration>

私はまったく同じ問題を抱えていますが、非常にビジーなWebサーバーで多くの問題を引き起こしています。クライアントにまだリソースのコピーがない場合でも、IISは304を返します。
Philippe Leybaert、2010

@フィリップ、あなたはまだ解決策を見つけましたか?それ以外の場合は、回避策について上記の編集を確認し、以下の新しい回答を確認してください。
Ola Herrdahl

@OlaHerrdahl、あなたの回避策は完璧です:)私もこの問題を抱えていました。ありがとう!
Ardee Aram 2012

回答:


3

よるとHTTP1.1仕様のセクション14.9no-cacheのCache-Controlヘッダのディレクティブは、IISはリクエストのヘッダを無視されることを意味し、オリジンサーバによってのみimposableです。

キャッシュ制御ディレクティブは、次の一般的なカテゴリに分類できます。

  - Restrictions on what are cacheable; these may only be imposed

オリジンサーバーによって。

セクション14.9.1定義publicprivateおよびno-cacheサーバのみによって課すことができるキャッシュ可能であるものを規制指示、など。

.jsファイルをキャッシュしたくない場合no-cacheは、アプリ(つまりASP.NETコード)でディレクティブを設定するか、ディレクティブのCache-Controlヘッダーを変更して、no-storeディレクティブを使用する必要があります。の代わりにno-cache

編集:
あなたのコメントに基づいて-はい、私はあなたがファイルをキャッシュしたくないと思いました。304は、ファイルがIISの内部キャッシュの1つにあるために発生する可能性があります。これらを見てください:


ここで私の問題を誤解したと思います。ファイルはまだキャッシュにありません。しかし、それでもサーバーは304で応答します...これは、すべての主要なブラウザーでサイトを閲覧するときにランダムに発生するようです。
Ola Herrdahl、2010年

@Ola Herrdahl:私の編集を見てください。
squillman、2010年

IISでもキャッシュを無効にしてみましたが、違いはありません... :(
Ola Herrdahl

1

しばらく同じ問題が発生し、すべてのキャッシュがオフになっています...しかし、IIS7の圧縮モジュールをインストールしたところ、デフォルトで既存のサイトの静的ファイルの圧縮が有効になりました。影響を受けたサイトのすべての圧縮をオフにしたところ、今では細かいタッチの木材で動作しているようです。


1

このバグも発生していましたが、アセット管理ライブラリ(カセット)を使用していました。この問題を徹底的に調査した結果、この問題の根本的な原因はASP.NET、IIS、およびカセットの組み合わせにあることがわかりました。これが(APIではなくAPI を使用して)問題かどうかはわかりませんが、パターンは同じようです。HeadersCache

バグ#1

カセットは、Vary: Accept-Encodinggzip / deflateでコンテンツをエンコードできるため、バンドルへの応答の一部としてヘッダーを設定します。

ただし、ASP.NET出力キャッシュは常に最初にキャッシュされた応答を常に返します。たとえば、最初のリクエストAccept-Encoding: gzipでカセットがgzip圧縮されたコンテンツを返す場合、ASP.NET出力キャッシュはURLをとしてキャッシュしますContent-Encoding: gzip。同じURLへの次のリクエストで、受け入れ可能なエンコーディングが異なる(例:)場合Accept-Encoding: deflateは、でキャッシュされた応答が返されContent-Encoding: gzipます。

このバグは、カセットを使用してHttpResponseBase.CacheAPIを使用して出力キャッシュ設定(などCache-Control: publicHttpResponseBase.Headersを設定し、APIを使用してVary: Accept-Encodingヘッダーを設定したことが原因です。問題は、ASP.NET OutputCacheModuleが応答ヘッダーを認識しないことです。CacheAPI 経由でのみ機能します。つまり、開発者が標準のHTTPだけでなく、目に見えない密結合APIを使用することを期待しています。

バグ#2

IIS 7.5(Windows Server 2008 R2)を使用している場合、バグ#1はIISカーネルとユーザーキャッシュで別の問題を引き起こす可能性があります。たとえば、バンドルがで正常にキャッシュされるとContent-Encoding: gzip、それをでIISカーネルキャッシュに表示することができますnetsh http show cachestate。これは、200のステータスコードと「gzip」のコンテンツエンコーディングを含む応答を示しています。次の要求は、異なる許容されるエンコーディング(例えばている場合 Accept-Encoding: deflateIf-None-Matchバンドルのハッシュと一致するヘッダを、IISのカーネルとユーザモード・キャッシュに要求が考慮されるミス。したがって、304を返すカセットによって要求が処理されるようにします。

ただし、IISのカーネルモードとユーザーモードが応答を処理すると、URLの応答が変更されたことがわかり、キャッシュを更新する必要があります。IISカーネルキャッシュがnetsh http show cachestate再度チェックされると、キャッシュされた200応答は304応答に置き換えられます。バンドルへのすべての後続の要求に関係なく、Accept-EncodingかつIf-None-Match304応答を返します。このバグの壊滅的な影響を確認しました。予期しないAccept-Encodingとのランダムリクエストが原因で、すべてのユーザーにコアスクリプトの304が提供されましたIf-None-Match

問題は、IISカーネルとユーザーモードのキャッシュがAccept-Encodingヘッダーに基づいて変更できないことです。これの証拠としてCache、以下の回避策でAPIを使用することにより、IISカーネルとユーザーモードのキャッシュは常にスキップされるように見えます(ASP.NET出力キャッシュのみが使用されます)。これはnetsh http show cachestate、以下の回避策で空であることを確認することで確認できます。ASP.NETはIISワーカーと直接通信して、要求ごとにIISカーネルとユーザーモードキャッシュを選択的に有効または無効にします。

IISの新しいバージョン(IIS Express 10など)ではこのバグを再現できませんでした。ただし、バグ#1はまだ再現可能でした。

このバグに対する私たちの最初の修正は、言及された他のようなカセットリクエストに対してのみIISカーネル/ユーザーモードキャッシングを無効にすることでした。そうすることで、Webサーバーの前に追加のキャッシングレイヤーをデプロイするときに、バグ#1を発見しました。ので、クエリ文字列ハックが働いたことの理由は、あるOutputCacheModule場合には、キャッシュミスを記録するCacheAPIは、に基づいて変化させるために使用されていないQueryString の要求がある場合QueryString

回避策

私たちはとにかくカセットから離れることを計画していたので、カセットの独自のフォークを維持する(またはPRをマージしようとする)代わりに、この問題を回避するためにHTTPモジュールを使用することを選びました。

public class FixCassetteContentEncodingOutputCacheBugModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostRequestHandlerExecute += Context_PostRequestHandlerExecute;
    }

    private void Context_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        var httpContext = HttpContext.Current;

        if (httpContext == null)
        {
            return;
        }

        var request = httpContext.Request;
        var response = httpContext.Response;

        if (request.HttpMethod != "GET")
        {
            return;
        }

        var path = request.Path;

        if (!path.StartsWith("/cassette.axd", StringComparison.InvariantCultureIgnoreCase))
        {
            return;
        }

        if (response.Headers["Vary"] == "Accept-Encoding")
        {
            httpContext.Response.Cache.VaryByHeaders.SetHeaders(new[] { "Accept-Encoding" });
        }
    }

    public void Dispose()
    {

    }
}

これが誰かに役立つことを願っています😄!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.