2012-01-12 21 views
5

Tôi có một tùy chỉnh HttpHandler trong đó tôi tự cho phép nén đầu ra, như vậy:"Content-mã hóa" tiêu đề biến mất khỏi HttpHandler phản ứng nếu một ngoại lệ xảy ra

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

này hoạt động độc đáo đối với hầu hết các yêu cầu, nhưng khi một ngoại lệ gặp phải tiêu đề "Mã hóa nội dung" biến mất khỏi phản hồi, trong khi bộ lọc nén vẫn giữ nguyên. Kết quả là trang lỗi là gzip được nén, nhưng trình duyệt không nhận được tiêu đề cho biết thực tế đó. Sau đó trình duyệt sẽ cố gắng hiển thị dữ liệu vẫn được nén dưới dạng văn bản, là gobbledygook.

Mã trường hợp thử nghiệm đầy đủ được hiển thị bên dưới. Thử luân phiên tắt tính năng nén hoặc không loại trừ ngoại lệ.

Có ai có thể giải thích một chút về nguyên nhân khiến tiêu đề "Mã hóa nội dung" biến mất không?

Tôi cho rằng tôi có thể đơn giản cho phép nén dưới dạng điều cuối cùng mà trình xử lý thực hiện, để nếu ngoại lệ gặp phải, nó không bao giờ đạt đến điểm mà bộ lọc nén được thêm vào; nhưng hành vi mà tôi thấy đang gây cho tôi một lỗi. Có ai xác nhận không?

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; } 
    } 
} 

EDIT: Ảnh chụp màn hình của phản ứng vẫn mã hóa tôi nhìn thấy với trường hợp thử nghiệm của tôi: http://i.imgur.com/49Vcl.png

Trả lời

-1

tôi thử nghiệm mã của bạn và tôi không thể tìm thấy bất kỳ vấn đề. Có gzip chưa được đặt, nhưng bộ lọc cũng chưa được đặt và asp lấy điều khiển và gửi lỗi.

Buộc tiêu đề để tuôn làm cho một vấn đề thực sự

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

Nếu tôi buộc tiêu đề gzip thì trang đó không được làm một cách chính xác.

Hai suy nghĩ ở đây có thể là vấn đề của bạn. Bạn không có thiết lập mã hóa trang

context.Response.ContentEncoding = new UTF8Encoding(); 

và bạn không có thiết lập ContentType

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

Có lẽ một số những điều này là lý do mà bạn nhận được không điều chỉnh hiển thị trang. Làm thế nào bao giờ trong các bài kiểm tra của tôi ngay cả với vấn đề bạn mô tả không xuất hiện.

+0

Vì vậy, nếu bạn thực thi mã của tôi, bạn sẽ nhận được một màn hình màu xám chết, chứ không phải là gobbledygook thích hợp? –

+0

vâng, như-là, tôi tạo bản sao/dán và tôi nhận được một màn hình màu vàng-of-death thích hợp. Vấn đề xuất hiện khi tôi tuôn ra() !!!!!!!! Bạn có tuôn ra ở đâu đó trước lỗi không? Gzip không xuất hiện, nhưng bộ lọc cũng không được đặt. – Aristos

+0

Có thể một nơi khác bạn đã đặt lỗi tùy chỉnh? – Aristos

0

Nếu bạn có ngoại lệ, máy chủ sẽ xóa các tiêu đề và nội dung hiện được đặt, vì chúng sai, như bạn đã làm sau khi tất cả đều có ngoại lệ.

Ít nhất, rõ ràng là trạng thái 200 bạn sẽ gửi (vì tất cả các câu trả lời thành công không thay đổi trạng thái gửi 200 và khi ngoại lệ chưa được giải quyết thì không thành công) nhưng mọi thứ khác liên quan đến thứ gì đó bạn định làm nhưng không thành công, vì vậy mọi thứ đều sai và tất cả đều diễn ra.

Bộ lọc không được đặt lại.

Đặt lại tiêu đề trong trang lỗi nếu thích hợp hoặc không đặt bộ lọc trừ khi bạn có thể chắc chắn rằng mọi thứ đã sẵn sàng để tuôn ra. Tôi muốn đi cho các cựu, không có lý do tại sao các trang lỗi không thể được nén quá.

Bạn không thể gửi tiêu đề nếu bạn đã gọi Flush(), bởi vì tốt, bởi vì bạn đã đỏ mặt. Tiêu đề sẽ đi đâu?

+0

Vì vậy, khi xảy ra lỗi, trình xử lý xóa bất kỳ tiêu đề và nội dung nào đã được viết (nhưng chưa được xóa), nhưng bỏ qua để loại bỏ bộ lọc mà tôi đã đưa ra? –

+0

Có. Nó gây khó chịu, nhưng tôi nghĩ bộ lọc có nghĩa là ngồi ở mức cao hơn trong đường ống, vì vậy nó có ý nghĩa với một ai đó ... –

+0

Dường như với tôi rằng nếu trình xử lý lỗi loại bỏ các tiêu đề tôi đã viết thì nó cũng nên xóa các Bộ lọc tôi đã chỉ định. Tôi tự hỏi nếu đây là một lỗi, hoặc bằng cách thiết kế ... Nếu không, bạn có thể làm rõ những gì bạn có nghĩa là "tình trạng 200 bạn sẽ gửi là sai"? Trình xử lý ngoại lệ là điều đặt trạng thái 500. Tại sao tôi nên đặt trạng thái khác ngoài 200? –

0

Tôi cũng gặp sự cố này. Thật phức tạp để theo dõi. Tôi không chắc chắn về các chi tiết cụ thể của toàn bộ tình huống này, nhưng điều tôi nghĩ xảy ra là có rò rỉ bộ nhớ.

Khi bạn lần đầu tiên làm điều này:

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

bạn đang gán một không được quản lý tài nguyên để Filter. Thông thường điều này sẽ được gói trong một tuyên bố using để nó sẽ được xử lý đúng cách trong trường hợp bất cứ điều gì đã sai.

Vì vậy, khi có sự cố xảy ra, có sự cố. Filter chứa một luồng vẫn mở ngay cả khi phản ứng được ghi vào màn hình màu vàng của cái chết. Điều gì xảy ra sau đó là điên rồ (như thể hiện trong ảnh chụp màn hình của bạn).

Sợ hãi không! Có thực sự là một cách dễ dàng để khắc phục vấn đề này. Vứt bỏ bộ lọc. May mắn thay, đã có một nơi để áp dụng kiểm tra toàn cầu này cho việc loại bỏ bộ lọc.

global.asax.cs

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

lỗi xử lý namespace

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; 
     } 
    } 
} 
0

tôi đã điều tương tự xảy ra khi buộc gzip trên WebForms ứng dụng. Để khắc phục nó tôi đã phải xóa bộ lọc vào Application_Error phương pháp trong Global.asax.cs

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

Lý do điều này xảy ra là b/c bộ lọc đã được thiết lập trước khi ứng dụng có lỗi . Và vì lý do nào đó, thông báo lỗi màn hình màu vàng xóa tiêu đề Mã hóa nội dung nhưng không làm bất kỳ điều gì với bộ lọc phản hồi.

Các vấn đề liên quan