From 027d1724e5cde936845e26c147a04e497a95b090 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Thu, 9 Aug 2012 08:59:54 -0400 Subject: [PATCH] Added auto-detection of client-capabilities to determine whether to use gzip or deflate --- .../Net/Handlers/BaseHandler.cs | 80 ++++++++++++++++++- MediaBrowser.Common/Net/RequestContext.cs | 31 +------ 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs index 51d56719d9..42d2f81908 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.IO.Compression; +using System.Net; namespace MediaBrowser.Common.Net.Handlers { @@ -46,7 +47,7 @@ namespace MediaBrowser.Common.Net.Handlers /// /// The action to write the response to the output stream /// - public virtual Action WriteStream + public Action WriteStream { get { @@ -125,11 +126,84 @@ namespace MediaBrowser.Common.Net.Handlers } } + private bool ClientSupportsCompression + { + get + { + string enc = RequestContext.Request.Headers["Accept-Encoding"] ?? string.Empty; + + return enc.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1 || enc.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1; + } + } + + private string CompressionMethod + { + get + { + string enc = RequestContext.Request.Headers["Accept-Encoding"] ?? string.Empty; + + if (enc.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1) + { + return "deflate"; + } + if (enc.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1) + { + return "gzip"; + } + + return null; + } + } + + protected virtual void PrepareResponseBeforeWriteOutput(HttpListenerResponse response) + { + // Don't force this to true. HttpListener will default it to true if supported by the client. + if (!UseChunkedEncoding) + { + response.SendChunked = false; + } + + if (ContentLength.HasValue) + { + response.ContentLength64 = ContentLength.Value; + } + + if (CompressResponse && ClientSupportsCompression) + { + response.AddHeader("Content-Encoding", CompressionMethod); + } + + TimeSpan cacheDuration = CacheDuration; + + if (cacheDuration.Ticks > 0) + { + CacheResponse(response, cacheDuration, LastDateModified); + } + } + + private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified) + { + DateTime lastModified = dateModified ?? DateTime.Now; + + response.Headers[HttpResponseHeader.CacheControl] = "public, max-age=" + Convert.ToInt32(duration.TotalSeconds); + response.Headers[HttpResponseHeader.Expires] = DateTime.Now.Add(duration).ToString("r"); + response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); + } + private void WriteReponse(Stream stream) { - if (CompressResponse) + PrepareResponseBeforeWriteOutput(RequestContext.Response); + + if (CompressResponse && ClientSupportsCompression) { - CompressedStream = new DeflateStream(stream, CompressionLevel.Fastest, false); + if (CompressionMethod.Equals("deflate", StringComparison.OrdinalIgnoreCase)) + { + CompressedStream = new DeflateStream(stream, CompressionLevel.Fastest, false); + } + else + { + CompressedStream = new GZipStream(stream, CompressionLevel.Fastest, false); + } WriteResponseToOutputStream(CompressedStream); } diff --git a/MediaBrowser.Common/Net/RequestContext.cs b/MediaBrowser.Common/Net/RequestContext.cs index 544c54501c..461f286011 100644 --- a/MediaBrowser.Common/Net/RequestContext.cs +++ b/MediaBrowser.Common/Net/RequestContext.cs @@ -1,8 +1,8 @@ using System; using System.Linq; using System.Net; -using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Common.Logging; +using MediaBrowser.Common.Net.Handlers; namespace MediaBrowser.Common.Net { @@ -62,26 +62,6 @@ namespace MediaBrowser.Common.Net if (statusCode == 200 || statusCode == 206) { - // Don't force this to true. HttpListener will default it to true if supported by the client. - if (!handler.UseChunkedEncoding) - { - Response.SendChunked = false; - } - - if (handler.ContentLength.HasValue) - { - Response.ContentLength64 = handler.ContentLength.Value; - } - - if (handler.CompressResponse) - { - Response.AddHeader("Content-Encoding", "deflate"); - } - - if (cacheDuration.Ticks > 0) - { - CacheResponse(Response, cacheDuration, handler.LastDateModified); - } handler.WriteStream(Response.OutputStream); } else @@ -91,15 +71,6 @@ namespace MediaBrowser.Common.Net } } - private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified) - { - DateTime lastModified = dateModified ?? DateTime.Now; - - response.Headers[HttpResponseHeader.CacheControl] = "public, max-age=" + Convert.ToInt32(duration.TotalSeconds); - response.Headers[HttpResponseHeader.Expires] = DateTime.Now.Add(duration).ToString("r"); - response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); - } - private bool IsCacheValid(DateTime ifModifiedSince, TimeSpan cacheDuration, DateTime? dateModified) { if (dateModified.HasValue)