开发者

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

开发者 https://www.devze.com 2023-01-29 20:16 出处:网络
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 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 开发者_JAVA百科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?


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.


I would have thought that you could enable encryption to achieve compression. I think I'm right in saying that all common encryption algorithms also compress the data to avoid producing obvious patterns in the compressed data. As a side effect, your service will be more secure :)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号