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);
}
}
}
}
}