6

次のように、出力圧縮を手動で有効にするカスタムHttpHandlerがあります。

context.Response.AppendHeader("Content-encoding", "gzip");
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);

これはほとんどのリクエストでうまく機能しますが、例外が発生すると、「Content-encoding」ヘッダーが応答から消え、圧縮フィルターはそのまま残ります。その結果、エラーページはgzipで圧縮されますが、ブラウザはその事実を示すヘッダーを受け取りません。次に、ブラウザはまだ圧縮されているデータをテキストとして表示しようとします。これはgobbledygookです。

完全なテストケースコードを以下に示します。代わりに、圧縮を無効にするか、例外をスローしないようにしてください。

「Content-encoding」ヘッダーが消える理由を誰かが明らかにすることはできますか?

ハンドラーが最後に行うように単純に圧縮を有効にできると思います。そのため、例外が発生した場合、圧縮フィルターが追加されるポイントに到達することはありません。しかし、私が見ている振る舞いはバグとして私を襲います。誰でも確認できますか?

public class TestHandler : IHttpHandler 
{
    public void ProcessRequest(HttpContext context)
    {
        CompressResponse(context);
        context.Response.Write("Hello world");

        // Throw an exception for testing purposes
        throw new Exception("Just testing...");
    }

    private void CompressResponse(HttpContext context)
    {
        string acceptEncoding = context.Request.Headers["Accept-Encoding"];
        if (String.IsNullOrEmpty(acceptEncoding))
        {
            return;
        }

        // gzip or wildcard
        if (acceptEncoding.ToLower().Contains("gzip") || acceptEncoding.Contains("*"))
        {
            context.Response.AppendHeader("Content-encoding", "gzip");
            context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
            return;
        }

        // Also handles deflate (not shown here)
        // <snip>
    }

    public bool IsReusable
    {
        get { return true; }
    }
}

編集:テストケースで見たまだエンコードされた応答のスクリーンショット:http://i.imgur.com/49Vcl.png

4

4 に答える 4

1

WebFormsアプリケーションで gzip を強制すると、同じことが起こりました。それを修正するために、Global.asax.csのApplication_Errorメソッドでフィルターをクリアする必要がありました。

protected void Application_Error(Object sender, EventArgs e)
{
    Response.Filter = null;
}

これが発生する理由は、アプリにエラーが発生する前にフィルターが設定されているためです。また、何らかの理由で、イエロー スクリーンのエラー メッセージは Content-encoding ヘッダーをクリアしますが、応答フィルターには何もしません。

于 2014-05-05T17:38:52.010 に答える
0

私もこの問題に遭遇しました。追跡するのは複雑でした。この状況全体の正確な詳細はわかりませんが、メモリ リークが発生していると思われます。

最初にこれを行うとき:

context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);

アンマネージ リソースを に割り当てていますFilter。通常、これはステートメントでラップされるため、問題が発生した場合usingに適切に破棄されます。

ですから、何かがうまくいかないときは、問題があります。Filterには、黄色の死の画面で応答が書き込まれているにもかかわらず、まだ開いているストリームが含まれています。結果として生じるのは狂気です (スクリーン ショットに示されているように)。

恐れるな!実は、この問題を解決する簡単な方法があります。フィルターを廃棄します。幸いなことに、フィルターの破棄にこのグローバル チェックを適用する場所が既にあります。

global.asax.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
        filters.Add(new HandleErrorAttribute());//default handler
        filters.Add(new HandleErrorEncodingAttribute());//extra check for filter disposal
}

エラー ハンドラの名前空間

public class HandleErrorEncodingAttribute : FilterAttribute, IExceptionFilter
{
    public virtual void OnException(ExceptionContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }
        if (filterContext.IsChildAction)
        {
            return;
        }
        // If custom errors are disabled, we need to let the normal ASP.NET exception handler
        // execute so that the user can see useful debugging information.
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
        {
            filterContext.HttpContext.Response.Filter.Dispose();//fixes response stream
            return;
        }
    }
}
于 2013-11-27T21:13:06.993 に答える
0

例外がある場合、サーバーは現在設定されているヘッダーとコンテンツをフラッシュします。これは、例外がある場合と同様に、それらが間違っているためです。

少なくとも、送信しようとしていた 200 ステータスが間違っていることは明らかですが (ステータスを変更しないすべての成功した応答は 200 を送信し、未処理の例外が発生すると、それはもはや成功していないため)、他のすべての関連するものは間違っています。あなたがやろうとしていたのに達成できなかったことに対して、それはすべて間違っていて、すべてがうまくいきます。

ただし、フィルターはリセットされません。

必要に応じてエラー ページのヘッダーをリセットするか、すべてをフラッシュする準備ができていることを確認できない限り、フィルターを設定しないでください。エラーページも圧縮できない理由はありません。

を呼び出した場合は、ヘッダーを送信できませんFlush()。フラッシュしたからです。ヘッダーはどこに行きますか?

于 2012-01-13T02:14:19.010 に答える
-1

コードをテストしましたが、問題は見つかりませんでした。はい、gzipは設定されていませんが、フィルターも設定されておらず、aspが制御を取得してエラーを送信します。

ヘッダーを強制的にフラッシュすると、実際の問題が発生します

 CompressResponse(context);
 context.Response.Flush(); 

gzipヘッダーを強制すると、ページが正しくレンダリングされません。

ここで2人はおそらくあなたの問題だと思います。ページエンコーディングを設定していません

context.Response.ContentEncoding = new UTF8Encoding();

ContentTypeを設定していません

context.Response.ContentType = "text/plain";

たぶん、これのいくつかはあなたが修正されていないページレンダリングを得る理由です。しかし、それでも私のテストでは、あなたが説明する問題は現れません。

于 2012-01-13T00:03:20.950 に答える