using System; using System.Text.RegularExpressions; using System.Web; namespace SiteCore.URLRewriter { public class RewriterModule : IHttpModule { public void Init(HttpApplication app) { // WARNING! This does not work with Windows authentication! // If you are using Windows authentication, change to app.BeginRequest //app.BeginRequest += new EventHandler(app_BeginRequest); app.AuthorizeRequest += this.URLRewriter; } protected void URLRewriter(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; string requestedPath = app.Request.Path; // get the configuration rules UrlsCollection rules = UrlsConfig.GetConfig().Urls; for (int i = 0; i < rules.Count; i++) { // get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory) string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].VirtualUrl) + "$"; Regex re = new Regex(lookFor, RegexOptions.IgnoreCase); if (re.IsMatch(requestedPath)) { string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].DestinationUrl)); //if (city != "") //{ // if(sendToUrl.IndexOf("?")==-1)sendToUrl = sendToUrl + "?city=" + city; // else sendToUrl = sendToUrl + "&city=" + city; //} RewriterUtils.RewriteUrl(app.Context, sendToUrl); break; } } } public void Dispose() { } } /// /// Provides utility helper methods for the rewriting HttpModule and HttpHandler. /// /// This class is marked as internal, meaning only classes in the same assembly will be /// able to access its methods. internal class RewriterUtils { #region RewriteUrl /// /// Rewrite's a URL using HttpContext.RewriteUrl(). /// /// The HttpContext object to rewrite the URL to. /// The URL to rewrite to. internal static void RewriteUrl(HttpContext context, string sendToUrl) { string x, y; RewriteUrl(context, sendToUrl, out x, out y); } /// /// Rewrite's a URL using HttpContext.RewriteUrl(). /// /// The HttpContext object to rewrite the URL to. /// The URL to rewrite to. /// Returns the value of sendToUrl stripped of the querystring. /// Returns the physical file path to the requested page. internal static void RewriteUrl(HttpContext context, string sendToUrl, out string sendToUrlLessQString, out string filePath) { // see if we need to add any extra querystring information if (context.Request.QueryString.Count > 0) { if (sendToUrl.IndexOf('?') != -1) sendToUrl += "&" + context.Request.QueryString; else sendToUrl += "?" + context.Request.QueryString; } // first strip the querystring, if any string queryString = String.Empty; sendToUrlLessQString = sendToUrl; if (sendToUrl.IndexOf('?') > 0) { sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf('?')); queryString = sendToUrl.Substring(sendToUrl.IndexOf('?') + 1); } // grab the file's physical path filePath = string.Empty; filePath = context.Server.MapPath(sendToUrlLessQString); // rewrite the path... context.RewritePath(sendToUrlLessQString, String.Empty, queryString); } #endregion /// /// Converts a URL into one that is usable on the requesting client. /// /// Converts ~ to the requesting application path. Mimics the behavior of the /// Control.ResolveUrl() method, which is often used by control developers. /// The application path. /// The URL, which might contain ~. /// A resolved URL. If the input parameter url contains ~, it is replaced with the /// value of the appPath parameter. internal static string ResolveUrl(string appPath, string url) { if (url.Length == 0 || url[0] != '~') return url; // there is no ~ in the first character position, just return the url else { if (url.Length == 1) return appPath; // there is just the ~ in the URL, return the appPath if (url[1] == '/' || url[1] == '\\') { // url looks like ~/ or ~\ if (appPath.Length > 1) return appPath + "/" + url.Substring(2); else return "/" + url.Substring(2); } else { // url looks like ~something if (appPath.Length > 1) return appPath + "/" + url.Substring(1); else return appPath + url.Substring(1); } } } } }