2010-12-07 3 views
9

타사 도구의 요청을 처리하기 위해 asp.net .asmx webservice를 작성했습니다. 타사 도구는 사용자 정보를 얻기 위해 웹 서비스에 http POST 요청을합니다. IIS7을 사용하고 있습니다.asp.net webservice handling gzip 압축 요청

"모든 인코딩 제거"가 선택된 피들러를 실행하면 웹 서비스 호출 및 모든 기능이 제대로 작동하는 것을 볼 수 있습니다. "Remove All Encodings"의 선택을 취소하면 400 잘못된 요청으로 webservice 호출이 실패합니다. 내가보기에 차이점은 헤더 "Content-Encoding : gzip"이 Fiddler에 의해 제거되고 내용이 압축 해제된다는 것입니다.

따라서 Content-Encoding 헤더가 제거되고 콘텐츠가 압축 해제되면 내 웹 서비스가 완벽하게 작동합니다. 헤더가 존재하고 컨텐츠가 압축되면 웹 서비스가 실패합니다.

어떻게 I 중 하나를

  1. 는 압축 요청을 수락 (그리고 타사 도구가 존중되기를 바랍니다)
  2. 압축 해제 컨텐츠 초기에하지 않을 것을 클라이언트에게 내 웹 서비스 구성 asp.net
  3. 가 압축 된 데이터

업데이트와 함께 작동하도록 내 웹 서비스를 수정 처리 : 명확하게하기 위해, 내가 필요하지 않습니다 응답에서 gzip 인코딩을 구성하려면 gzip으로 인코딩 된 요청에 대한 내 웹 서비스를 처리해야합니다.

업데이트 2 : 타사 도구는 Salesforce.com Outlook 플러그인입니다. 따라서 수정할 필요가 없으며 많은 다른 회사에서 문제없이 사용하고 있습니다. 그것은 내가 3

업데이트하고 (또는 일을하지 않음)하고있어 무언가있을거야 : 나는 IIS가 압축 된 데이터를 수신 POST 요청을 지원하지 않는다고 한 후 here을 발견, 그것은 단지 압축 된 응답을 지원합니다. 여전히 사실 일 수 있습니까?

답변

1

부분 응답 here을 찾았습니다. 지금은 들어오는 요청을 처리 할 수 ​​있지만, 응답 "는 점점 때문에 나는 부분 답을 말할

void Application_BeginRequest(object sender, EventArgs e) 
    { 
     string contentEncoding = Request.Headers["Content-Encoding"]; 
     Stream prevCompressedStream = Request.Filter; 

     if(contentEncoding == null || contentEncoding.Length == 0) 
      return; 

     contentEncoding = contentEncoding.ToLower(); 

     if(contentEncoding.Contains("gzip")) 
     { 
      Request.Filter = new DecompressStream(Request.Filter); 
     } 
    } 

:

class DecompressStream : Stream 
{ 
    ... 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     GZipStream test = new GZipStream(_sink, CompressionMode.Decompress); 

     int c = test.Read(buffer, offset, count); 

     return c; 
    } 

    ... 
} 

것은

나는 다음과 같은 요청 객체에 필터를 지정할 수 있습니다 Content-Encoding : gzip "헤더가 포함되어 있습니다. Fiddler에서 해당 콘텐츠가 인코딩되지 않았 음을 확인할 수 있습니다.

응답을 인코딩하면 웹 서비스의 클라이언트가 실패합니다. "Accept-Encoding : gzip"을 보내더라도 실제로 gzip 압축 응답을 받아들이지는 않습니다. Fiddler에서 응답이 압축되어 있고 Fiddler가 성공적으로 압축을 풀 것이라고 확인할 수 있습니다.

그래서 지금은 길잃은 "Content-Encoding : gzip"헤더가 응답에서 제거되었습니다. 압축, 응용 프로그램, web.config 및 IIS에서 찾을 수있는 모든 참조를 제거했습니다.

+0

저는 몇 년 동안 ASP 웹 서비스 (.asmx) 웹 서비스를 사용하지는 않았지만 HttpContext.Current.Response.Headers를 사용하여 응답 헤더에 액세스 할 수 없었습니까? –

+0

@Florin, 정확합니다. PostRequestHandlerExecute 함수에서 잘못된 헤더를 제거하고 BeginRequest 함수에서 들어오는 요청에서 Accelpt-Encoding 헤더를 제거 할 수있었습니다. 작동시키기 위해서 두 가지를 모두해야했습니다. – Geoff

1

GZIP 압축은 서버의 기능입니다.

IIS6을 사용하는 경우 this link을 참조하십시오.

IIS7을 사용하는 경우 ISAPI_Rewrite를 사용하여 gzip을 비활성화 할 수 있습니다. this link을 참조하십시오.

gzip은 IIS의 기능이기 때문에 웹 서비스 (IIS는 압축 해제 및 압축 요청을 처리해야 함)와 작동하도록 "특별한"작업을 수행하지 않아도됩니다. 이 정보를 통해 문제 해결 및 문제 해결에 도움이 될 수 있기를 바랍니다.

+0

감사합니다,하지만 너무 멀리는 도움이되지 않습니다. 구성 설정에서 상자를 선택 취소하여 IIS7에서 압축을 해제 할 수 있지만 다시 서버의 응답에만 영향을 미치는 것으로 보입니다. 나는 압축 된 서버 요청에 대처해야한다. – Geoff

+0

다음은 gzip 클라이언트/서버 대화의 정상 작동 방식입니다. http://www.websiteoptimization.com/speed/tweak/compress/ –

+0

타사 도구가 좋지 않을 수 있습니다. –

2

제 3 자 서비스가 단지 당신에게 POST를 보내고 있기 때문에 나는 압축하지 말 것을 그들에게 말하는 것이 가능하다고 생각하지 않습니다.

당신은 GetWebRequest을 무시하고 내가 IIS가 들어오는 요청을 압축 해제 지원하는지 확실하지 않다

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol 

{ 
protected override WebRequest GetWebRequest(Uri uri) 
{ 
    base.GetWebRequest(uri);request.AutomaticDecompression = System.Net.DecompressionMethods.GZip; 
    return request; 
} 
} 
+0

감사합니다. 불행히도, 요청은 결코 그것을 멀리 만들지 않습니다. 당신의 대답은 내가 성공하게 된 체인의 마지막 호출이 PreRequestHandlerExecute 인 것을 알게되었고, 그것은 저의 답변에 설명 된대로 입력을 필터링하려고했습니다. – Geoff

1

방식에 압축을 시도 할 수 있었다, 그래서 이것은 파이프 아래로 더 수행해야 할 수도 있습니다.

쉬라즈의 대답은 일할 잠재력이 있으며, 내가 시도 할 첫 번째 일이 될 것입니다.

그래도 작동하지 않으면 서버 .asmx 서비스를 WCF로 전환하는 것을 고려할 수 있습니다.이 서비스를 설정하기가 다소 어려울지라도 더 많은 유연성을 제공합니다.

WCF 쪽에서 내가 제안 할 수있는 두 가지 사항이 있습니다. 첫 번째 구현은 매우 쉽고 WCF에서 자동으로 압축을 허용하는 WebRequest 개체를 설정하는 것을 기반으로합니다. 세부 사항은 here입니다. 이것은 Shiraz가 제안한 솔루션과 동일한 WCF입니다.

두 번째 메시지는 사용자 지정 메시지 인코더를 만드는 작업을 포함하기 때문에 더 복잡하지만 위의 방법 중 어느 것도 작동하지 않으면 문제가 해결됩니다. 메시지 압축 인코더 생성은 here으로 설명됩니다. 메시지 엔코더의 샘플 구성을 나타내는 here의 대답을 확인하는 것이 좋습니다.

도움이 필요한 경우 또는 도움이 필요한 경우 알려주십시오.

5

가장 간단한 방법은 요청 필터를 대체하는 HttpModule을 만드는 것입니다. 더 재사용 가능하며 Global.asax를 피할 수 있습니다. GZipStream이 준비되었으므로 새로운 압축 풀기 스트림 클래스를 만들 필요가 없습니다.

public class GZipRequestDecompressingModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.BeginRequest += (sender, e) => 
     { 
      var request = (sender as HttpApplication).Request; 

      string contentEncoding = request.Headers["Content-Encoding"]; 

      if (string.Equals(contentEncoding, "gzip", 
       StringComparison.OrdinalIgnoreCase)) 
      { 
       request.Filter = new GZipStream(request.Filter, 
        CompressionMode.Decompress); 
       request.Headers.Remove("Content-Encoding"); 
      } 
     }; 
    } 
    public void Dispose() 
    { 
    } 
} 

이 모듈을 활성화하려면, 당신의 Web.config에 다음 섹션을 추가 : 여기에 또한 더 하나가 필요하지 않은 Content-Encoding: gzip 제거하는 전체 코드입니다

<system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"> 
     <add name="AnyUniqueName" 
      type="YourNamespace.GZipRequestDecompressingModule, YourAssembly" 
      preCondition="integratedMode" /> 
    </modules> 
</system.webServer> 
+0

부작용을 피하기 위해 특정 경로에서만이 모듈을 활성화 할 수 있습니까? 즉, ASMX 파일에서만 사용할 수 있습니까? – NickG

+1

물론 경로 속성을 지정하는 web.config 파일의 [location 요소] (http://msdn.microsoft.com/en-us/library/b6x6shw7(v=vs.100).aspx)를 사용하십시오. 필요합니다. – Mart

+0

BTW : string.Equals (contentEncoding, "gzip", StringComparison.OrdinalIgnoreCase) 대신 contentEncoding.ToLower() == "gzip"을 입력하면 훨씬 빠르게 입력 할 수 있습니다. :) – NickG