HttpCacheability.Private が ETag を抑制するのはなぜですか?
質問
カスタム IHttpHandler を作成しているときに、HttpCachePolicy オブジェクトに関して予期しない動作に遭遇しました。
私のハンドラーは、エンティティ タグを計算して設定します (現在の応答オブジェクトに関連付けられた HttpCachePolicy の SetETag メソッドを使用します)。SetCacheability メソッドを使用してキャッシュ コントロールを public に設定すると、すべてが魔法のように機能し、サーバーは e-tag ヘッダーに沿って送信します。プライベートに設定すると、e-tag ヘッダーが抑制されます。
私が十分に調べていないだけかもしれませんが、HTTP/1.1 仕様にはこの動作を正当化するものは何も見つかりませんでした。プロキシによるデータの保存を禁止しながら、ブラウザに E-Tag を送信しないのはなぜでしょうか?
using System;
using System.Web;
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext ctx) {
ctx.Response.Cache.SetCacheability(HttpCacheability.Private);
ctx.Response.Cache.SetETag("\"static\"");
ctx.Response.ContentType = "text/plain";
ctx.Response.Write("Hello World");
}
public bool IsReusable { get { return true; } }
}
戻ります
Cache-Control: private Content-Type: text/plain; charset=utf-8 Content-Length: 11
ただし、パブリックに変更すると元に戻ります
Cache-Control: public Content-Type: text/plain; charset=utf-8 Content-Length: 11 Etag: "static"
これまでのところ、ASP.NET開発サーバーとIIS6でこれを実行しましたが、同じ結果が得られました。また、ETagを使用して明示的に設定することもできません
Response.AppendHeader("ETag", "static")
アップデート:IIS7 で実行する場合、ETag ヘッダーを手動で追加することができます。これは、ASP.NET と IIS7 パイプライン間の緊密な統合が原因であると思われます。
説明:長い質問ですが、核心的な質問は次のとおりです。 ASP.NET はなぜこのようなことを行うのでしょうか?どうすれば回避できますか?また回避する必要がありますか?
アップデート:受け入れます トニーの答え それは本質的に正しいからです(トニー行け!)。HttpCacheability.Private を完全にエミュレートしたい場合は、キャッシュ可能性を ServerAndPrivate に設定できますが、呼び出しキャッシュも使用できることがわかりました。SetOmitVaryStar(true) それ以外の場合、キャッシュは 変化する:* ヘッダーを出力に追加しますが、それは望ましくありません。編集権限を取得したら、それを回答に編集します (または、この Tony を見た場合は、その呼び出しを含めるように回答を編集できますか?)
解決
HttpCacheability.ServerAndPrivate を使用する必要があると思います
これにより、キャッシュを制御できるようになります。ヘッダーに private を追加し、ETag を設定できるようにします。
それに関するドキュメントはもう少し改善する必要があります。
編集: Markus は、cache.SetOmitVaryStar(true) の呼び出しもあることを発見しました。そうでない場合、キャッシュは Vary を追加します。* ヘッダーを出力に追加しますが、それは望ましくありません。
他のヒント
残念ながら見てみると System.Web.HttpCachePolicy.UpdateCachedHeaders()
.NET Reflector では、ETag 処理を実行する前に Cacheability が Private ではないことを特にチェックする if ステートメントがあることがわかります。いずれにせよ、私はいつもそれを見つけました Last-Modified/If-Modified-Since
私たちのデータにはうまく機能し、とにかく Fiddler で監視するのが少し簡単です。
私と同じように、ここで説明した Cacheability.ServerAndPrivate を使用する回避策に不満があり、代わりに Private を使用したい場合は、おそらくユーザーごとにページを個別にカスタマイズしており、サーバーにキャッシュするのは意味がないためです。 .NET 3.5 では、Response.Headers.Add を通じて ETag を設定でき、これは正常に機能します。
注:これを行う場合は、クライアント ヘッダーと HTTP 304 応答処理の比較を自分で実装する必要があります。通常の状況で .NET がこれを処理してくれるかどうかはわかりません。