Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compress HTTP requests from WCF .NET at the transport level?

I have managed to enable inbound HTTP compression on ASP.NET (ie compression of HTTP requests, not just responses) but I am now struggling on the client side (C# / .NET 4.0 app).

I would like to:

  • add the HTTP header Content-Encoding: gzip
  • compress HTTP body with GZip

to all outbound HTTP requests emitted by a WCF channel.

Solutions that do not work so far:

  • with IClientMessageInspector I can compress the message, but it does not account for the whole HTTP body as the envelop is not compressed.
  • same for a custom message encoder, compress the message not the envelop, no impact on the HTTP request headers.

Any idea how to mimic the IHttpModule behavior (see initial response) on the client side?

like image 614
Joannes Vermorel Avatar asked Dec 11 '10 09:12

Joannes Vermorel


People also ask

How do I compress a HTTP request body?

To compress the HTTP request body, you must attach the HTTP header indicating the sending of HTTP request body compressed in gzip format while sending the request message from the Web Service client. Implement the processing for attaching the HTTP header in the client application.

Does ASP net Core support response compression?

When you're unable to use the compression features of web servers (IIS, Apache, Nginx), ASP.NET Core provides an alternate option, Response Compression middleware.

What is response compression?

The response compression middleware allows adding additional compression providers for custom Accept-Encoding header values.


1 Answers

The message encoder described here should do the job.

I have tested using the sample downloaded from the link available in the above article (the InstallDrive\WF_WCF_Samples\WCF\Extensibility\MessageEncoder\Compression project from this) and Fiddler.

Please note that the MSDN sample has a bug which you will need to fix in order to make it properly work. In the GZipMessageEncoderFactory class, CompressBuffer method, the following line

ArraySegment<byte> byteArray = new ArraySegment<byte>(bufferedBytes, messageOffset, bufferedBytes.Length - messageOffset);

should be replaced with

ArraySegment<byte> byteArray = new ArraySegment<byte>(bufferedBytes, messageOffset, totalLength);

After applying the above fix the entire message body would be compressed.

In order to check that the compression is correct you can use the AutoDecode option from Fiddler. However, AutoDecode will only decompress the message if it has a Content-Encoding: gzip HTTP header.

Adding HTTP headers to WCF message calls is not strait forward, since WCF was designed to be transport agnostic and WCF applications should not handle elements specific to a certain transport method.

However, for the purpose of this application I was able to do it using the following piece of code:

public string Echo(string input)
{
    using (OperationContextScope opScope = new OperationContextScope((IContextChannel)base.Channel))
    {
        HttpRequestMessageProperty reqProps = new HttpRequestMessageProperty();
        reqProps.Headers["Content-Encoding"] = "gzip";
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = reqProps;

        return base.Channel.Echo(input);
    }
}

Echo is one of the client methods from the MSDN sample and inside it I am accessing the current operation context to add a HTTP header.

Please let me know if you need additional help.

like image 104
Florin Dumitrescu Avatar answered Oct 26 '22 23:10

Florin Dumitrescu