2013-05-21 27 views
10

Come posso abilitare la compressione per i dati POST caricati su un WebService .NET (SOAP, non WCF)? Ho pensato che sarebbe una semplice questione di enabling dynamic compression in IIS, ma dopo l'attivazione, è solo comprimere la risposta , non la richiesta POST .Come abilitare la compressione GZIP per le richieste POST (upload) a un servizio Web SOAP su IIS 7?

L'ho aggiunto come riferimento di servizio e non riesco a trovare alcuna impostazione sul SOAPClient generato per abilitare la compressione delle richieste.

Sembra che potrebbe mancare un'impostazione di configurazione o un codice sul lato client per comprimere la richiesta prima di inviarla al server? O è quello che sto cercando di fare (dati GZipping POST) non ancora supportato?

Ulteriori informazioni: sto usando .NET 4.0 sul client e sul server.

+0

Si prega di fare riferimento a questo SO messaggio (http://stackoverflow.com/questions/4416177/how-to-compress-http-requests-from-wcf-net-at-the-transport-level) – Rajesh

risposta

13

ho bloggato su che 4 anni fa

http://netpl.blogspot.com/2009/07/aspnet-webservices-two-way-response-and.html

mi chiedo perché non hai trovato questo googling. Ad ogni modo, questo dovrebbe funzionare per voi, lo abbiamo fatto lavorando in un ambiente di produzione per 4 anni.

+0

In realtà stavo già usando quel codice ma aveva un paio di bug che ho faticato a risolvere. Tuttavia ho trascorso più tempo su questo e ora ho risolto i bug. La mia versione corregge i seguenti problemi: Imposta intestazione gzip di codifica del contenuto quando si verifica un'eccezione sul server. Seconda correzione: non tentare di decodificare il flusso di richieste GZIP quando la richiesta non era GZIPed. Ho pubblicato la versione aggiornata del codice qui: http://pastebin.com/Aak9FUiw – NickG

+0

Mille grazie per la soluzione originale. Ti assegnerò la taglia :) – NickG

+0

La terza correzione consisteva nell'eliminare il raddoppio dell'intestazione "content-encoding" in modo che diventasse "gzip, gzip". Non sono sicuro se questo è veramente necessario ma non è corretto. – NickG

6

Alla fine, ho usato la risposta di Wiktor Zychla, ma ho trovato un paio di bug (citato anche nei commenti del suo articolo). Per completezza, posterò la mia versione fissa del modulo HttpCompression qui, ma il resto del codice (e le linee guida di implementazione) di cui hai bisogno sono in Wiktor's article.

UPDATE:

realtà ho dovuto smettere di usare questo codice in quanto ha un bug non riesco a risolvere (anche con la mia versione migliorata di seguito). Per molte persone dietro i server proxy viene visualizzato un errore che dice "il numero magico nell'intestazione gzip non è corretto" e non riesco a capire come risolvere questo problema. Penso che sia perché i server proxy decomprimono GZIP e questo codice non consente di ricevere le risposte sia zippate che non compresse nella sua forma attuale.

using System; 
using System.IO.Compression; 
using System.Web; 
using System.Web.Security; 

/// <summary> 
/// Implement two way HTTP compression for the SOAP API 
/// Code taken from: http://netpl.blogspot.co.uk/2009/07/aspnet-webservices-two-way- response-and.html 
/// Fix: Set Content-encoding: gzip header when an Exception occurs on the server. 
/// Fix: Do not attempt to decrypt GZIP request stream when request was not GZIPed. 
/// </summary> 
public class HttpCompressionModule : IHttpModule 
{ 
    private bool isDisposed = false; 

    ~HttpCompressionModule() 
    { 
      Dispose(false); 
    } 

    public void Init(HttpApplication context) 
    { 
      context.BeginRequest += new EventHandler(Context_BeginRequest); 
      context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders); 
    } 

    void context_PreSendRequestHeaders(object sender, EventArgs e) 
    { 
      // Fix headers having been lost if an exception occurred. 
      HttpApplication app = sender as HttpApplication; 
      HttpContext ctx = app.Context; 
      if (app.Response.Filter is GZipStream) SetEncoding("gzip"); 
      else if (app.Response.Filter is DeflateStream) SetEncoding("deflate"); 

      // Fix double header 
      if (ctx.Response.Headers["Content-encoding"] == "gzip,gzip") 
        ctx.Response.Headers.Set("Content-encoding", "gzip"); 
    } 

    public void Context_BeginRequest(object sender, EventArgs e) 
    { 
      HttpApplication app = sender as HttpApplication; 
      HttpContext ctx = app.Context; 

      // Currently only enable for the Uploader API webservice 
      if (!ctx.Request.Url.PathAndQuery.ToLower().Contains("uploaderapi.asmx")) 
      { 
        return; 
      } 

      // Add request filter if request was GZIP encoded 
      string requestEncoding = ctx.Request.Headers["Content-encoding"]; 
      if (requestEncoding != null && requestEncoding == "gzip") 
      { 
       app.Request.Filter = 
        new System.IO.Compression.GZipStream(app.Request.Filter, CompressionMode.Decompress); 
      } 

      // Add response compression filter if the client accepts compressed responses 
      if (IsEncodingAccepted("gzip")) 
      { 
        app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress); 
        SetEncoding("gzip"); 
      } 
      else if (IsEncodingAccepted("deflate")) 
      { 
        app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress); 
        SetEncoding("deflate"); 
      } 
    } 

    private bool IsEncodingAccepted(string encoding) 
    { 
      return HttpContext.Current.Request.Headers["Accept-encoding"] != null && 
        HttpContext.Current.Request.Headers["Accept-encoding"].Contains(encoding); 
    } 

    private void SetEncoding(string encoding) 
    { 
      HttpContext ctx = HttpContext.Current; 
      string responseEncodings = ctx.Response.Headers.Get("Content-encoding"); 
      if (responseEncodings == null || !responseEncodings.Contains(encoding)) 
        HttpContext.Current.Response.AppendHeader("Content-encoding", encoding); 
    } 

    public void Dispose() 
    { 
      Dispose(true); 
    } 

    private void Dispose(bool dispose) 
    { 
      isDisposed = dispose; 
    } 
} 
+2

Nick, ricorda che questa non è una risposta completa, sono richiesti anche HttpResponseDecompressed e HttpRequestCompressed –

+0

@WiktorZychla Grazie - Ho aggiornato la mia risposta per chiarire che il tuo articolo contiene tutto il codice/le istruzioni.La mia risposta è solo per correggere quei bug/problemi di compatibilità che ho trovato (e sarà ridondante se deciderai di incorporarli nel tuo articolo) – NickG

+0

Nick, a causa della tua chiara spiegazione, non ho intenzione di apportare alcuna modifica alla voce. Suppongo che chiunque cerchi di farne uso troverà i tuoi commenti e seguirà il tuo aggiornamento aggiornato ch. Sono contento che la soluzione sia stata d'aiuto e grazie per le tue correzioni. –