[Patch] Enable content compression for sync via HTTP
-
2011年10月27日 10:26
I'd like to share my solution to enable content compression for sync via HTTP.
With just a few lines of code we can enable the sync client to leverage gzip compression for downloads if the server supports it, too. For the actual decompression you have to utilize any compression library. I have decided for well-known SharpZipLib.
WP7Client: Microsoft.Syncronization.ClientServices.HttpCacheRequestHandler
void ProcessRequest(AsyncArgsWrapper wrapper) { ... // Set the method type webRequest.Method = "POST"; webRequest.Accept = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json"; webRequest.ContentType = (base.SerializationFormat == SerializationFormat.ODataAtom) ? "application/atom+xml" : "application/json"; try { // Enable compression webRequest.Headers[HttpRequestHeader.AcceptEncoding] = "gzip"; } catch (ArgumentException) { // Pre-Mango OS throws: ArgumentException - The 'Accept-Encoding' header cannot be modified directly. } ... void OnUploadGetResponseCompleted(IAsyncResult asyncResult) { ... if (response.StatusCode == HttpStatusCode.OK) { Stream responseStream = response.GetResponseStream(); // Decompress if required if (response.Headers[HttpRequestHeader.ContentEncoding] != null && response.Headers[HttpRequestHeader.ContentEncoding].Contains("gzip")) { responseStream = new GZipInputStream(responseStream); } // Create the SyncReader ... void OnDownloadGetResponseCompleted(IAsyncResult asyncResult) { ... if (response.StatusCode == HttpStatusCode.OK) { Stream responseStream = response.GetResponseStream(); // Decompress if required if (response.Headers[HttpRequestHeader.ContentEncoding] != null && response.Headers[HttpRequestHeader.ContentEncoding].Contains("gzip")) { responseStream = new GZipInputStream(responseStream); } // Create the SyncReader ...
There are plenty of good tutorials on how to enable IIS to do compression like the one from Scott Hanselmann about Enabling dynamic compression
It is even possible to enable compression for uploads. All it takes is a little more patching of the client and a little patching of the server library.
WP7Client: Microsoft.Syncronization.ClientServices.HttpCacheRequestHandler
void OnUploadGetRequestStreamCompleted(IAsyncResult asyncResult) { ... Stream requestStream = wrapper.WebRequest.EndGetRequestStream(asyncResult); // Compress wrapper.WebRequest.Headers[HttpRequestHeader.ContentEncoding] = "gzip"; requestStream = new GZipOutputStream(requestStream); ... void OnDownloadGetRequestStreamCompleted(IAsyncResult asyncResult) { ... Stream requestStream = wrapper.WebRequest.EndGetRequestStream(asyncResult); // Compress wrapper.WebRequest.Headers[HttpRequestHeader.ContentEncoding] = "gzip"; requestStream = new GZipOutputStream(requestStream); ...
SyncServiceLib: Microsoft.Synchronization.Services.RequestParser
/// <summary> /// Read request details for Download/upload operations. /// </summary> private void ReadIncomingRequestDetails() { ... SyncTracer.Info("Request HTTP method is POST"); if (null != _serviceHost.RequestHeaders[HttpRequestHeader.ContentEncoding] && _serviceHost.RequestHeaders[HttpRequestHeader.ContentEncoding].Contains("gzip")) { SyncTracer.Info("Request payload is gzipped"); ReadIncomingRequestStreamForPost(true); } else // Parse request stream and populate members. ReadIncomingRequestStreamForPost(); ... private void ReadIncomingRequestStreamForPost(bool isGzipped = false) { ... try { Stream inputStream = (isGzipped) ? new GZipInputStream(_serviceHost.RequestStream) : _serviceHost.RequestStream; var reader = WebUtil.GetSyncReader(_serviceHost.GetRequestContentSerializationFormat(), inputStream, _configuration.TypeToTableGlobalNameMapping.Keys.ToArray()); ...
Let me know how it works for you.
Senior Jack of all trades