2010-12-07 18 views
9

サードパーティのツールからのリクエストを処理するasp.net .asmx webserviceがあります。サードパーティのツールは、Webサービスにhttp POST要求を出してユーザー情報を取得します。私はIIS7を使用していますasp.net webservice handling gzip圧縮要求

"すべてのエンコーディングを削除"でFiddlerを実行すると、webserviceの呼び出しとすべての機能が正しく表示されます。 "Remove All Encodings"のチェックを外すと、Webサービス呼び出しは400 Bad Requestで失敗します。私が見る違いは、ヘッダー "Content-Encoding:gzip"がFiddlerによって削除され、コンテンツが解凍されていることです。

したがって、Content-Encodingヘッダーが削除され、コンテンツが解凍されると、私のWebサービスは完全に機能します。ヘッダーが存在し、コンテンツが圧縮されると、Webサービスは失敗します。

どのようにいずれかのことができます。

  1. は、それが圧縮された要求を受け入れ(およびサードパーティのツールがあることを尊重することを願っています)ではないだろうことをクライアントに伝えるために、私のWebサービスを設定し
  2. は、早期のコンテンツを解凍します
  3. を扱うasp.netは更新圧縮データ

で動作するように私のWebサービスを変更します。明確にするために、私は必要はありませんレスポンスでgzipエンコーディングを設定するには、gzipエンコードされたリクエストに私のwebサービスに対処する必要があります。

更新2:サードパーティツールは、Salesforce.com Outlookプラグインです。だから私はそれを変更するアクセス権がなく、他の多くの企業でも問題なく使用されています。それは、私が3

アップデートやって(またはやっていない)よ何かをする持っている:私はIISが圧縮されたデータの着信POSTリクエストをサポートしていないと言うつのポストhereを見つけ、それだけで圧縮された応答をサポートしています。これはまだ真実であることができますか?

答えて

1

私は部分的な答えhereを見つけました。

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

    ... 
} 

私は、このようなリクエストオブジェクトにフィルタを指定することができます

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

私は今、着信要求を処理できるにもかかわらず、応答は "を取得しているので、私は部分答えを言いますContent-Encoding:gzip "ヘッダーが返されます。 Fiddlerでは、コンテンツがエンコードされていないことを確認できます。

私がレスポンスをエンコードすると、Webサービスのクライアントが失敗します。 「Accept-Encoding:gzip」を送信しているにもかかわらず、実際にgzip圧縮応答を受け入れていないようです。私は、応答が圧縮され、Fiddlerがそれを正常に解凍することをFiddlerで検証できます。

これで、私は迷惑な "Content-Encoding:gzip"ヘッダーを応答から削除しようとしています。私は、アプリケーション、web.config、およびIISから圧縮することができるすべての参照を削除しました。

+0

私は、ASP Webサービス(.asmx)Webサービスで長年働いていませんでしたが、HttpContext.Current.Response.Headersで応答ヘッダーにアクセスできませんでしたか? –

+0

@Florin、あなたは正しいです。 PostRequestHandlerExecute関数で問題のヘッダーを削除し、BeginRequest関数で着信要求からAccelpt-Encodingヘッダーを削除できました。それを動作させるためには両方を行う必要がありました。 – Geoff

1

GZIP圧縮は、サーバーの機能です。

IIS6を使用している場合はthis linkに問い合わせてください。

IIS7を使用している場合は、ISAPI_Rewriteを使用してgzipを無効にすることができます。 this linkを参照してください。

gzipはIISの機能なので、Webサービス(IISは圧縮解除と圧縮要求を処理する必要があります)で動作させるには、「特別な」処理を行う必要はありません。うまくいけば、この情報により、トラブルシューティングと問題解決の道がいっそう拡大します。

+0

おかげで、しかし、そうこれははるかに役立ちません。私はIIS7で構成設定のチェックボックスをオフにして圧縮をオフにすることができますが、これはサーバーからの応答のみに影響するようです。私は、サーバーへのリクエストを処理する必要があります。 – Geoff

+0

gzipクライアント/サーバーの会話は正常に動作します:http://www.websiteoptimization.com/speed/tweak/compress/ –

+0

サードパーティのツールがうまく動作していない可能性があります。 –

2

サードパーティのサービスはあなたに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側には、私が提案できる2つのことがあります。最初は実装が非常に簡単で、WCFが自動的に圧縮を受け入れるために使用するWebRequestオブジェクトを設定することに基づいています。詳細はhereです。これはShirazが提案した解決策に相当するWCFです。

2番目はカスタムメッセージエンコーダーを作成する必要があるため、より複雑ですが、上記のいずれの方法でも問題が解決しない場合は、問題を解決する必要があります。メッセージ圧縮エンコーダの作成については、hereと記載されています。 hereでメッセージエンコーダのサンプル設定を表示することもできます。

これが役に立ったのか、さらにヘルプが必要な場合はお知らせください。

5

最も簡単な手法は、要求フィルタを置き換えるHttpModuleを作成することです。より再利用可能で、Global.asaxを避けることができます。 GZipStreamが準備ができているので、新しい解凍ストリームクラスを作成する必要もありません。ここでも、それ以上を必要とされていないContent-Encoding: gzipを削除する完全なコードは、次のとおりです。

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ファイルに次のセクションを追加するには:

<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)を使用します。ここでは、 'path'属性を必要です。 – Mart

+0

BTW:string.Equals(contentEncoding、 "gzip"、StringComparison.OrdinalIgnoreCase)の代わりにcontentEncoding.ToLower()== "gzip"を入力するともっと速くできます:) – NickG