[Patch] Enable content compression for sync via HTTP

Discussion [Patch] Enable content compression for sync via HTTP

  • 27 octombrie 2011 10:26
     
      Are cod

    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

    • Tip modificat M.Bi 27 octombrie 2011 11:36
    • Editat de M.Bi 14 noiembrie 2011 07:56
    •