PageRenderTime 15ms CodeModel.GetById 1ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 1ms

/BlogEngine/DotNetSlave.BusinessLogic/Web/HttpModules/WwwSubDomainModule.cs

#
C# | 151 lines | 79 code | 22 blank | 50 comment | 14 complexity | 7588da0abdc0891250dc29d116aade21 MD5 | raw file
  1namespace BlogEngine.Core.Web.HttpModules
  2{
  3    using System;
  4    using System.Text.RegularExpressions;
  5    using System.Web;
  6
  7    /// <summary>
  8    /// Removes or adds the www subdomain from all requests
  9    ///     and makes a permanent redirection to the new location.
 10    /// </summary>
 11    public class WwwSubDomainModule : IHttpModule
 12    {
 13        #region Constants and Fields
 14
 15        /// <summary>
 16        /// The link regex.
 17        /// </summary>
 18        private static readonly Regex LinkRegex = new Regex(
 19            "(http|https)://www\\.", RegexOptions.IgnoreCase | RegexOptions.Compiled);
 20
 21        #endregion
 22
 23        #region Implemented Interfaces
 24
 25        #region IHttpModule
 26
 27        /// <summary>
 28        /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
 29        /// </summary>
 30        public void Dispose()
 31        {
 32            // Nothing to dispose
 33        }
 34
 35        /// <summary>
 36        /// Initializes a module and prepares it to handle requests.
 37        /// </summary>
 38        /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param>
 39        public void Init(HttpApplication context)
 40        {
 41            context.BeginRequest += ContextBeginRequest;
 42        }
 43
 44        #endregion
 45
 46        #endregion
 47
 48        #region Methods
 49
 50        /// <summary>
 51        /// Adds the www subdomain to the request and redirects.
 52        /// </summary>
 53        /// <param name="context">
 54        /// The context.
 55        /// </param>
 56        private static void AddWww(HttpContext context)
 57        {
 58            var url = context.Request.Url.ToString().Replace("://", "://www.");
 59            PermanentRedirect(url, context);
 60        }
 61
 62        /// <summary>
 63        /// Sends permanent redirection headers (301)
 64        /// </summary>
 65        /// <param name="url">
 66        /// The url to redirect to.
 67        /// </param>
 68        /// <param name="context">
 69        /// The HTTP context.
 70        /// </param>
 71        private static void PermanentRedirect(string url, HttpContext context)
 72        {
 73            if (url.EndsWith("default.aspx", StringComparison.OrdinalIgnoreCase))
 74            {
 75                url = url.ToLowerInvariant().Replace("default.aspx", string.Empty);
 76            }
 77
 78            context.Response.Clear();
 79            context.Response.StatusCode = 301;
 80            context.Response.AppendHeader("location", url);
 81            context.Response.End();
 82        }
 83
 84        /// <summary>
 85        /// Removes the www subdomain from the request and redirects.
 86        /// </summary>
 87        /// <param name="context">
 88        /// The context.
 89        /// </param>
 90        private static void RemoveWww(HttpContext context)
 91        {
 92            var url = context.Request.Url.ToString();
 93            if (!LinkRegex.IsMatch(url))
 94            {
 95                return;
 96            }
 97
 98            url = LinkRegex.Replace(url, "$1://");
 99            PermanentRedirect(url, context);
100        }
101
102        /// <summary>
103        /// Handles the BeginRequest event of the context control.
104        /// </summary>
105        /// <param name="sender">The source of the event.</param>
106        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
107        private static void ContextBeginRequest(object sender, EventArgs e)
108        {
109            // Clear the InstanceIdOverride to ensure any values are not
110            // carried over from previous times this thread from the thread
111            // pool was used.
112            //
113            // This should be done at the beginning of each HTTP request as
114            // early as possible.  It is being done here because in the
115            // list of HTTP modules defined in the web.config file, this
116            // module (WwwSubdomainModule) is the first defined one so will
117            // fire before any other modules.
118            Blog.InstanceIdOverride = Guid.Empty;
119
120            if (BlogSettings.Instance.HandleWwwSubdomain == "ignore" ||
121                string.IsNullOrEmpty(BlogSettings.Instance.HandleWwwSubdomain))
122            {
123                return;
124            }
125
126            var context = ((HttpApplication)sender).Context;
127            if (context.Request.HttpMethod != "GET" || context.Request.RawUrl.Contains("/admin/") ||
128                context.Request.IsLocal)
129            {
130                return;
131            }
132
133            if (context.Request.PhysicalPath.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase))
134            {
135                var url = context.Request.Url.ToString();
136
137                if (url.Contains("://www.") && BlogSettings.Instance.HandleWwwSubdomain == "remove")
138                {
139                    RemoveWww(context);
140                }
141
142                if (!url.Contains("://www.") && BlogSettings.Instance.HandleWwwSubdomain == "add")
143                {
144                    AddWww(context);
145                }
146            }
147        }
148
149        #endregion
150    }
151}