Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
David Murdoch committed May 9, 2011
1 parent a3c399d commit c88a77c
Show file tree
Hide file tree
Showing 9 changed files with 520 additions and 0 deletions.
210 changes: 210 additions & 0 deletions App_Code/Compression/CompressionConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
using System;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Configuration;

namespace Compression
{
public class CompressionConfiguration : ConfigurationSection
{
#region Constructors
static CompressionConfiguration()
{
PFormat = new ConfigurationProperty(
"format",
typeof(CompressionFormat),
CompressionFormat.deflate, // deflate is preferred
ConfigurationPropertyOptions.None
);

PStaticTypes = new ConfigurationProperty(
"staticTypes",
typeof(StaticTypesElementCollection),
null,
ConfigurationPropertyOptions.IsRequired
);

PProperties = new ConfigurationPropertyCollection {
PFormat,
PStaticTypes
};
}
#endregion

#region Enums

public enum CompressionFormat
{
// ReSharper disable InconsistentNaming
deflate,
gzip
// ReSharper restore InconsistentNaming
}

#endregion

#region Static Fields

private static readonly ConfigurationProperty PFormat;
private static readonly ConfigurationProperty PStaticTypes;

private static readonly ConfigurationPropertyCollection PProperties;

#endregion

#region Properties

/// <summary>
/// Gets the BooleanValue setting.
/// </summary>
[ConfigurationProperty("format", IsRequired = false)]
public CompressionFormat Format
{
get { return (CompressionFormat)base[PFormat]; }
}

/// <summary>
/// Override the Properties collection and return our custom one.
/// </summary>
protected override ConfigurationPropertyCollection Properties
{
get { return PProperties; }
}

/// <summary>
/// Gets the NestedElement element.
/// </summary>
[ConfigurationProperty("staticTypes")]
public StaticTypesElementCollection StaticTypes
{
get { return (StaticTypesElementCollection)base[PStaticTypes]; }
}
#endregion

#region GetSection Pattern
private static CompressionConfiguration _section;

/// <summary>
/// Gets the configuration section using the default element name.
/// </summary>
/// <remarks>
/// If an HttpContext exists, uses the WebConfigurationManager
/// to get the configuration section from web.config.
/// </remarks>
public static CompressionConfiguration GetSection()
{
return GetSection("httpCompression");
}

/// <summary>
/// Gets the configuration section using the specified element name.
/// </summary>
/// <exception cref="ConfigurationException"></exception>
/// <remarks>
/// If an HttpContext exists, uses the WebConfigurationManager
/// to get the configuration section from web.config.
/// </remarks>
public static CompressionConfiguration GetSection(string definedName)
{
if (_section == null)
{
string cfgFileName = ".config";
if (HttpContext.Current == null)
{
_section = ConfigurationManager.GetSection(definedName) as CompressionConfiguration;
}
else
{
_section = WebConfigurationManager.GetSection(definedName) as CompressionConfiguration;
cfgFileName = "web.config";
}

if (_section == null)
{
throw new ConfigurationErrorsException("The <" + definedName + "> section is not defined in your " + cfgFileName + " file!");
}
}

return _section;
}
#endregion

#region Methods

public bool IsContentTypeCompressed(string contentTypeStr)
{
try
{
foreach (var staticType in from sType in StaticTypes.OfType<MimeFormatElement>() let mimeFormat = sType.MimeFormat where mimeFormat.Matches(contentTypeStr) select sType)
{
return staticType.Enabled;
}
}
catch
{
return false;
}
return false;
}

public string GetCompressionType(string acceptEncoding)
{
bool foundDeflate = false;
bool foundGZip = false;

string[] formats = acceptEncoding.Split(',');

foreach (string acceptEncodingValue in formats.Select(t => t.Trim().ToLower()))
{
if (acceptEncodingValue.Contains("deflate") && CanAcceptQuality(acceptEncodingValue))
{
foundDeflate = true;
}
else if ((acceptEncodingValue.Contains("gzip") || acceptEncodingValue.StartsWith("x-gzip")) && CanAcceptQuality(acceptEncodingValue))
{
foundGZip = true;
}
else if (acceptEncodingValue.StartsWith("*") && CanAcceptQuality(acceptEncodingValue))
{
foundGZip = true;
foundDeflate = true;
}
}

if (Format == CompressionFormat.deflate && foundDeflate)
{
return "deflate";
}
if (Format == CompressionFormat.gzip && foundGZip)
{
return "gzip";
}

return foundDeflate ? "deflate" : (foundGZip ? "gzip" : null);
}

static bool CanAcceptQuality(string acceptEncodingValue)
{
int qParam = acceptEncodingValue.IndexOf("q=");

float val = 1.0f;

if (qParam >= 0)
{
try
{
val = float.Parse(acceptEncodingValue.Substring(qParam + 2,
acceptEncodingValue.Length - (qParam + 2)));
}
catch (FormatException)
{

}
}
return (val > 0.0f);
}

#endregion
}
}
48 changes: 48 additions & 0 deletions App_Code/Compression/MimeFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.ComponentModel;

namespace Compression
{
[TypeConverter(typeof(MimeFormatConverter))]
public struct MimeFormat
{
public string Format
{
get
{
return Type + "/" + SubType;
}
}
public string Type;
public string SubType;

public MimeFormat(string mimeFormatStr)
{
var parts = mimeFormatStr.Split('/');
if (parts.Length != 2)
{
throw new Exception("Invalid MimeFormat");
}

Type = parts[0];
SubType = parts[1];
}
public MimeFormat(string mimeType, string mimeSubType)
{
Type = mimeType;
SubType = mimeSubType;
}
public bool Matches(string mimeFormatStr)
{
try
{
var mimeFormat = new MimeFormat(mimeFormatStr);
return (Type == "*" || Type.Equals(mimeFormat.Type, StringComparison.CurrentCultureIgnoreCase)) && (SubType == "*" || SubType.Equals(mimeFormat.SubType, StringComparison.CurrentCultureIgnoreCase));
}
catch
{
return false;
}
}
}
}
28 changes: 28 additions & 0 deletions App_Code/Compression/MimeFormatConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.ComponentModel;
using System.Globalization;

namespace Compression
{
public class MimeFormatConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return new MimeFormat((string)value);
}

public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var val = (MimeFormat)value;
return val.Type + "/" + val.SubType;
}
}
}
74 changes: 74 additions & 0 deletions App_Code/Compression/MimeFormatElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.ComponentModel;
using System.Configuration;
using System.Web;

namespace Compression
{
public class MimeFormatElement: ConfigurationElement
{
#region Constructors
/// <summary>
/// Predefines the valid properties and prepares
/// the property collection.
/// </summary>
static MimeFormatElement()
{
// Predefine properties here
var mimeFormatType = typeof(MimeFormat);
PMimeFormat = new ConfigurationProperty(
"mimeFormat",
mimeFormatType,
"*/*",
ConfigurationPropertyOptions.IsRequired
);
PEnabled = new ConfigurationProperty(
"enabled",
typeof(bool),
false,
ConfigurationPropertyOptions.IsRequired
);

PProperties = new ConfigurationPropertyCollection {
PMimeFormat, PEnabled
};
}
#endregion

#region Static Fields

private static readonly ConfigurationProperty PMimeFormat;
private static readonly ConfigurationProperty PEnabled;
private static readonly ConfigurationPropertyCollection PProperties;

#endregion

#region Properties
/// <summary>
/// Gets the MimeFormat setting.
/// </summary>
[ConfigurationProperty("mimeFormat", IsRequired = true)]
public MimeFormat MimeFormat
{
get { return (MimeFormat)base[PMimeFormat]; }
}

/// <summary>
/// Gets the Enabled setting.
/// </summary>
[ConfigurationProperty("enabled")]
public bool Enabled
{
get { return (bool)base[PEnabled]; }
}

/// <summary>
/// Override the Properties collection and return our custom one.
/// </summary>
protected override ConfigurationPropertyCollection Properties
{
get { return PProperties; }
}
#endregion
}
}
Loading

0 comments on commit c88a77c

Please sign in to comment.