Created
September 22, 2012 13:07
-
-
Save woloski/3766125 to your computer and use it in GitHub Desktop.
HttpDomainRoute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class HttpDomainRoute | |
: HttpRoute | |
{ | |
private Regex domainRegex; | |
private Regex pathRegex; | |
public HttpDomainRoute(string domain, string routeTemplate, HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints) | |
: base(routeTemplate, defaults, constraints) | |
{ | |
this.Domain = domain; | |
} | |
public string Domain { get; set; } | |
public override IHttpRouteData GetRouteData(string virtualPathRoot, System.Net.Http.HttpRequestMessage request) | |
{ | |
// Build regex | |
domainRegex = CreateRegex(this.Domain); | |
pathRegex = CreateRegex(this.RouteTemplate); | |
// Request information | |
string requestDomain = request.Headers.Host; | |
if (!string.IsNullOrEmpty(requestDomain)) | |
{ | |
if (requestDomain.IndexOf(":") > 0) | |
{ | |
requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); | |
} | |
} | |
else | |
{ | |
requestDomain = request.RequestUri.Host; | |
} | |
var httpContext = HttpContext.Current; // TODO: replace this with something that works for selfhost | |
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; | |
// Match domain and route | |
Match domainMatch = domainRegex.Match(requestDomain); | |
Match pathMatch = pathRegex.Match(requestPath); | |
// Route data | |
HttpRouteData data = null; | |
if (domainMatch.Success && pathMatch.Success) | |
{ | |
data = new HttpRouteData(this); | |
// Add defaults first | |
if (Defaults != null) | |
{ | |
foreach (KeyValuePair<string, object> item in Defaults) | |
{ | |
data.Values[item.Key] = item.Value; | |
} | |
} | |
// Iterate matching domain groups | |
for (int i = 1; i < domainMatch.Groups.Count; i++) | |
{ | |
Group group = domainMatch.Groups[i]; | |
if (group.Success) | |
{ | |
string key = domainRegex.GroupNameFromNumber(i); | |
if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0)) | |
{ | |
if (!string.IsNullOrEmpty(group.Value)) | |
{ | |
data.Values[key] = group.Value; | |
} | |
} | |
} | |
} | |
// Iterate matching path groups | |
for (int i = 1; i < pathMatch.Groups.Count; i++) | |
{ | |
Group group = pathMatch.Groups[i]; | |
if (group.Success) | |
{ | |
string key = pathRegex.GroupNameFromNumber(i); | |
if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0)) | |
{ | |
if (!string.IsNullOrEmpty(group.Value)) | |
{ | |
data.Values[key] = group.Value; | |
} | |
} | |
} | |
} | |
} | |
return data; | |
} | |
public override IHttpVirtualPathData GetVirtualPath(System.Net.Http.HttpRequestMessage request, IDictionary<string, object> values) | |
{ | |
return base.GetVirtualPath(request, RemoveDomainTokens(values)); | |
} | |
public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values) | |
{ | |
// Build hostname | |
string hostname = Domain; | |
foreach (KeyValuePair<string, object> pair in values) | |
{ | |
hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString()); | |
} | |
// Return domain data | |
return new DomainData | |
{ | |
Protocol = "http", | |
HostName = hostname, | |
Fragment = "" | |
}; | |
} | |
private Regex CreateRegex(string source) | |
{ | |
// Perform replacements | |
source = source.Replace("/", @"\/?"); | |
source = source.Replace(".", @"\.?"); | |
source = source.Replace("-", @"\-?"); | |
source = source.Replace("{", @"(?<"); | |
source = source.Replace("}", @">([a-zA-Z0-9_-]*))"); | |
return new Regex("^" + source + "$"); | |
} | |
private IDictionary<string, object> RemoveDomainTokens(IDictionary<string, object> values) | |
{ | |
Regex tokenRegex = new Regex(@"({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?({[a-zA-Z0-9_-]*})*-?\.?\/?"); | |
Match tokenMatch = tokenRegex.Match(Domain); | |
for (int i = 0; i < tokenMatch.Groups.Count; i++) | |
{ | |
Group group = tokenMatch.Groups[i]; | |
if (group.Success) | |
{ | |
string key = group.Value.Replace("{", "").Replace("}", ""); | |
if (values.ContainsKey(key)) | |
values.Remove(key); | |
} | |
} | |
return values; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment