2012-01-12 2 views
5

은 내가 수동으로 출력 압축을 사용 그래서 같이있는 사용자 지정 HttpHandler를이 발생하면 HttpHandler를 응답에서 사라 :는 "콘텐츠 인코딩은"헤더는 예외가

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

이 대부분의 요청에 대해 잘 작동을하지만, 때 예외가 발생하면 압축 필터가 제 위치에있는 동안 응답에서 "내용 인코딩"헤더가 사라집니다. 결과적으로 오류 페이지는 gzip으로 압축되지만 브라우저는 사실을 나타내는 헤더를받지 못합니다. 그런 다음 브라우저는 여전히 압축 된 데이터를 텍스트 (gobbledygook)로 표시하려고 시도합니다.

전체 테스트 사례 코드는 다음과 같습니다. 교대로 압축을 해제하거나 예외를 발생시키지 않도록 시도하십시오.

누군가 "콘텐츠 인코딩"헤더가 사라지는 이유에 대해 조명 해줄 수 있습니까?

마지막으로 핸들러에서 압축을 사용하도록 설정할 수 있으므로 예외가 발생하면 압축 필터가 추가되는 지점에 도달하지 않게됩니다. 그러나 내가 보았던 행동은 나로 하여금 나를 버그로 친다. 누구든지 확인할 수 있습니까?

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

답변

-1

난 당신의 코드를 테스트하고 나는 어떤 문제를 찾을 수 없습니다. 예. gzip이 설정되지 않았지만 필터도 설정되지 않았고 asp가 제어를 가져오고 오류를 보냅니다. 내가 다음 페이지가 제대로 렌더링되지 않는 GZIP 헤더를 강제하면 진짜 문제를

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

을 플러시 헤더를 강제

.

2 명이 여기에 문제가 있다고 생각합니다. 당신은 페이지 인코딩

context.Response.ContentEncoding = new UTF8Encoding(); 

를 설정하지 않고 당신은 어쩌면이 중 일부는 당신이 페이지를 렌더링 수정되지받을 이유가

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

의 ContentType

설정하지 않습니다. 내 테스트에서 당신이 설명하는 문제가 나타나지 않는 경우에도

+0

그래서 코드를있는 그대로 실행하면 아직도 압축 된 gobbledygook 대신 적절한 노란색 화면이 생깁니 까? –

+0

예, 그대로 복사/붙여 넣기를하고 적절한 노란색 화면을 얻습니다. 내가 플러시() !!!!!!!! 때 문제가 나타납니다. 오류가 발생하기 전에 어딘가에 물을 내 보냅니 까? gzip이 나타나지 않지만 필터가 설정되지 않았습니다. – Aristos

+0

어쩌면 다른 곳에서 사용자 정의 오류를 설정했을 수 있습니까? – Aristos

0

예외가있는 경우 모두 예외가 발생한 것처럼 서버가 현재 설정된 헤더와 내용을 플러시합니다.

적어도 상태를 변경하지 않은 모든 성공한 응답은 200을 보내고 처리되지 않은 예외가되면 더 이상 성공하지 못했기 때문에 200 상태를 보냈음이 분명합니다. 하지만 그 밖의 모든 것들은 당신이하려고했지만 실패한 것들과 관련이 있습니다, 그래서 그것은 모두 잘못되었습니다.

필터는 재설정되지 않습니다.

오류 페이지의 헤더를 적절하게 재설정하거나 모든 것이 플러시 할 준비가되지 않았다면 필터를 설정하지 마십시오. 전, 오류 페이지가 너무 압축 할 수없는 이유는 전직에 갈거야.

Flush()을 호출 한 경우 머리글을 보낼 수 없습니다. 플러시했기 때문입니다. 헤더는 어디로 갈까요?

+0

그래서 오류가 발생하면 처리기는 쓰여졌지만 (아직 플러시되지 않은) 모든 머리글과 내용을 제거하지만 내가 지정한 필터를 제거하지 않습니까? –

+0

예. 그것은 짜증나지만, 필터는 개념적으로 파이프 라인의 상위 레벨에 앉아서, 그래서 누군가에게 이해가됐다고 생각했습니다. –

+0

오류 처리기가 내가 작성한 헤더를 제거하면 나에게도 보일 것입니다. 내가 지정한 필터를 제거하십시오. 이것이 버그인지 디자인인지 궁금합니다. 그렇지 않으면 "보내려는 200 개의 상태가 잘못되었습니다"라는 의미를 명확히 할 수 있습니까? 예외 처리기는 500 상태를 설정합니다. 200 이외의 상태를 수동으로 설정해야하는 이유는 무엇입니까? –

0

이 문제도 발생했습니다. 추적하는 것은 복잡했습니다. 나는이 모든 상황에 대해 정확히 모르겠다.하지만 내가 생각하는 것은 메모리 누수가 있다는 것이다.

처음이 작업을 수행 할 때 : 당신이 Filter관리되지 않는 자원를 할당하는

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

. 일반적으로 이것은 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; 
     } 
    } 
} 
0

은 내가 웹폼 응용 프로그램에 gzip을 강요 할 때 같은 일이 발생했다. 그것을 해결하기 위하여 I는 Global.asax.cs

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

이 앱에 오류가 발생하기 전에 필터가 설정되고, B/C이다 일어나는 이유를 함으로써 Application_Error 방법에서의 필터를 클리어했다 . 그리고 어떤 이유로 노란색 화면 오류 메시지가 Content-encoding 헤더를 지우지 만 응답 필터에는 아무런 영향을 미치지 않습니다.