public override void PostMapRequestHandler(HttpContextBase context) { base.PostMapRequestHandler(context); var ri = context.Items["mubble_RequestItems"] as RequestItems; if (ri != null) { context.RewritePath(ri.OriginalPath); } //RequestData data = (RequestData)context.Items[_requestDataKey]; //if (data != null) //{ // context.RewritePath(data.OriginalPath); // context.Handler = data.HttpHandler; //} }
/// <summary> /// Implements the Early Url Localization logic. /// <see href="https://docs.google.com/drawings/d/1cH3_PRAFHDz7N41l8Uz7hOIRGpmgaIlJe0fYSIOSZ_Y/edit?usp=sharing"/> /// </summary> public void ProcessIncoming( HttpContextBase context) { // Is URL explicitly excluded from localization? if (!m_urlLocalizer.FilterIncoming(context.Request.Url)) { return; } // YES. Continue handling request. bool allowRedirect = context.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) || context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase); // NO. Is request URL localized? string urlNonlocalized; string langtag = m_urlLocalizer.ExtractLangTagFromUrl(context, context.Request.RawUrl, UriKind.Relative, true, out urlNonlocalized); if (langtag == null) { // NO. // langtag = best match between // 1. Inferred user languages (cookie and Accept-Language header) // 2. App Languages. LanguageTag lt = context.GetInferredLanguage(); // If redirection allowed...redirect user agent (browser) to localized URL. // The principle purpose of this redirection is to ensure the browser is showing the correct URL // in its address field. if (allowRedirect) { RedirectWithLanguage(context, lt.ToString(), m_urlLocalizer); return; } // Otherwise, handle the request under the language infered above but without doing the redirect. // NB: this will mean that the user agent (browser) won't have the correct URL displayed; // however, this typically won't be an issue because we are talking about POST, PUT and DELETE methods // here which are typically not shown to the user. else { context.SetPrincipalAppLanguageForRequest(lt); return; // Continue handling request. } } // YES. Does langtag EXACTLY match an App Language? LanguageTag appLangTag = LanguageHelpers.GetMatchingAppLanguage(langtag); if (appLangTag.IsValid() && appLangTag.Equals(langtag)) { // YES. Establish langtag as the PAL for the request. context.SetPrincipalAppLanguageForRequest(appLangTag); // Rewrite URL for this request. context.RewritePath(urlNonlocalized); // Continue handling request. return; } // NO. Does langtag LOOSELY match an App Language? else if (appLangTag.IsValid() && !appLangTag.Equals(langtag)) { // YES. Localize URL with matching App Language. // Conditionally redirect user agent to localized URL. if (allowRedirect) { RedirectWithLanguage(context, appLangTag.ToString(), m_urlLocalizer); return; } } // NO. Do nothing to URL; expect a 404 which corresponds to language not supported. // Continue handling request. }
public virtual void PostMapRequestHandler (HttpContextBase context) { #if !NET_4_0 if (context == null) throw new ArgumentNullException ("context"); // FIXME: find out what it actually does. IHttpHandler h = (IHttpHandler) context.Items [module_identity_key]; if (h != null) context.Handler = h; string original_path = context.Items [original_path_key] as string; if (!String.IsNullOrEmpty (original_path)) context.RewritePath (original_path); #endif }
public virtual void PostResolveRequestCache (HttpContextBase context) { if (context == null) throw new ArgumentNullException ("context"); var rd = RouteCollection.GetRouteData (context); if (rd == null) return; // do nothing if (rd.RouteHandler == null) throw new InvalidOperationException ("No IRouteHandler is assigned to the selected route"); if (rd.RouteHandler is StopRoutingHandler) return; //stop further processing var rc = new RequestContext (context, rd); IHttpHandler http = rd.RouteHandler.GetHttpHandler (rc); if (http == null) throw new InvalidOperationException ("The mapped IRouteHandler did not return an IHttpHandler"); #if NET_4_0 context.Request.RequestContext = rc; context.RemapHandler (http); #else // note: It does not resolve paths using GetVirtualPath(): //var vpd = RouteCollection.GetVirtualPath (rc, rd.Values); //context.RewritePath (vpd.VirtualPath); context.Items [original_path_key] = context.Request.Path; // default handler (forbidden in MVC/DynamicData projects) context.RewritePath ("~/UrlRouting.axd"); context.Items [module_identity_key] = http; #endif }
/// <summary> /// Returns information about the requested route. /// </summary> /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param> /// <returns> /// An object that contains the values from the route definition. /// </returns> public override RouteData GetRouteData(HttpContextBase httpContext) { if (DataSettingsHelper.DatabaseIsInstalled() && this.SeoFriendlyUrlsForLanguagesEnabled) { string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath; string applicationPath = httpContext.Request.ApplicationPath; if (virtualPath.IsLocalizedUrl(applicationPath, false)) { //In ASP.NET Development Server, an URL like "http://localhost/Blog.aspx/Categories/BabyFrog" will return //"~/Blog.aspx/Categories/BabyFrog" as AppRelativeCurrentExecutionFilePath. //However, in II6, the AppRelativeCurrentExecutionFilePath is "~/Blog.aspx" //It seems that IIS6 think we're process Blog.aspx page. //So, I'll use RawUrl to re-create an AppRelativeCurrentExecutionFilePath like ASP.NET Development Server. //UNDONE should we do path rewrting here? string rawUrl = httpContext.Request.RawUrl; var newVirtualPath = rawUrl.RemoveLocalizedPathFromRawUrl(applicationPath); if (string.IsNullOrEmpty(newVirtualPath)) newVirtualPath = "/"; newVirtualPath = newVirtualPath.RemoveApplicationPathFromRawUrl(applicationPath); newVirtualPath = "~" + newVirtualPath; httpContext.RewritePath(newVirtualPath, true); } } RouteData data = base.GetRouteData(httpContext); return data; }
// ensures Umbraco has at least one published node // if not, rewrites to splash and return false // if yes, return true bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext) { var store = context.RoutingContext.PublishedContentStore; if (!store.HasContent(context)) { LogHelper.Warn<UmbracoModule>("Umbraco has no content"); httpContext.Response.StatusCode = 503; var noContentUrl = "~/config/splashes/noNodes.aspx"; httpContext.RewritePath(UriUtility.ToAbsolute(noContentUrl)); return false; } else { return true; } }
// ensures Umbraco is ready to handle requests // if not, set status to 503 and transfer request, and return false // if yes, return true bool EnsureIsReady(HttpContextBase httpContext, Uri uri) { var ready = ApplicationContext.Current.IsReady; // ensure we are ready if (!ready) { LogHelper.Warn<UmbracoModule>("Umbraco is not ready"); if (!UmbracoSettings.EnableSplashWhileLoading) { // let requests pile up and wait for 10s then show the splash anyway ready = ApplicationContext.Current.WaitForReady(10 * 1000); } if (!ready) { httpContext.Response.StatusCode = 503; var bootUrl = UmbracoSettings.BootSplashPage; if (string.IsNullOrWhiteSpace(bootUrl)) bootUrl = "~/config/splashes/booting.aspx"; httpContext.RewritePath(UriUtility.ToAbsolute(bootUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); return false; } } return true; }
/// <summary> /// Ensures that the request is a document request (i.e. one that the module should handle) /// </summary> /// <param name="httpContext"></param> /// <param name="uri"></param> /// <returns></returns> bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri) { var maybeDoc = true; var lpath = uri.AbsolutePath.ToLowerInvariant(); // handle directory-urls used for asmx // legacy - what's the point really? if (maybeDoc && GlobalSettings.UseDirectoryUrls) { int asmxPos = lpath.IndexOf(".asmx/"); if (asmxPos >= 0) { // use uri.AbsolutePath, not path, 'cos path has been lowercased httpContext.RewritePath(uri.AbsolutePath.Substring(0, asmxPos + 5), // filePath uri.AbsolutePath.Substring(asmxPos + 5), // pathInfo uri.Query.TrimStart('?')); maybeDoc = false; } } // a document request should be // /foo/bar/nil // /foo/bar/nil/ // /foo/bar/nil.aspx // where /foo is not a reserved path // if the path contains an extension that is not .aspx // then it cannot be a document request if (maybeDoc && lpath.Contains('.') && !lpath.EndsWith(".aspx")) maybeDoc = false; // at that point, either we have no extension, or it is .aspx // if the path is reserved then it cannot be a document request if (maybeDoc && GlobalSettings.IsReservedPathOrUrl(lpath)) maybeDoc = false; //NOTE: No need to warn, plus if we do we should log the document, as this message doesn't really tell us anything :) //if (!maybeDoc) //{ // LogHelper.Warn<UmbracoModule>("Not a document"); //} return maybeDoc; }
/// <summary> /// Rewrites to the correct Umbraco handler, either WebForms or Mvc /// </summary> /// <param name="context"></param> /// <param name="pcr"> </param> private static void RewriteToUmbracoHandler(HttpContextBase context, PublishedContentRequest pcr) { // NOTE: we do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is // not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly // rewritten url, but this is not what we want! // read: http://forums.iis.net/t/1146511.aspx string query = pcr.Uri.Query.TrimStart(new[] { '?' }); string rewritePath; if (pcr.RenderingEngine == RenderingEngine.Unknown) { // Unkwnown means that no template was found. Default to Mvc because Mvc supports hijacking // routes which sometimes doesn't require a template since the developer may want full control // over the rendering. Can't do it in WebForms, so Mvc it is. And Mvc will also handle what to // do if no template or hijacked route is exist. pcr.RenderingEngine = RenderingEngine.Mvc; } switch (pcr.RenderingEngine) { case RenderingEngine.Mvc: // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) rewritePath = GlobalSettings.Path.TrimEnd(new[] { '/' }) + "/RenderMvc"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", query, false); //if it is MVC we need to do something special, we are not using TransferRequest as this will //require us to rewrite the path with query strings and then reparse the query strings, this would //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: // * Looks up the route based on the new rewritten URL // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink //a bunch of things! var urlRouting = new UrlRoutingModule(); urlRouting.PostResolveRequestCache(context); break; case RenderingEngine.WebForms: rewritePath = "~/default.aspx"; // rewrite the path to the path of the handler (i.e. default.aspx) context.RewritePath(rewritePath, "", query, false); break; default: throw new Exception("Invalid RenderingEngine."); } }
// ensures Umbraco has at least one published node // if not, rewrites to splash and return false // if yes, return true private static bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext) { if (context.ContentCache.HasContent()) return true; LogHelper.Warn<UmbracoModule>("Umbraco has no content"); httpContext.Response.StatusCode = 503; const string noContentUrl = "~/config/splashes/noNodes.aspx"; httpContext.RewritePath(UriUtility.ToAbsolute(noContentUrl)); return false; }
/// <summary> /// Returns information about the requested route. /// </summary> /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param> /// <returns>An object that contains the values from the route definition.</returns> public override RouteData GetRouteData(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } bool isResource = Regex.Match(httpContext.Request.Url.ToString(), @"\.\w{2,4}$").Success; if (isResource) { return base.GetRouteData(httpContext); } string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath; var parts = virtualPath.Substring(2).Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); Guid parseResult; if (parts.Length == 0 || parts[0].ToLower() == "bundles" || parts[0].ToLower() == "styles" || parts[0].ToLower() == "content" || parts[0].ToLower() == "areas" || Guid.TryParse(parts[0].ToLower(), out parseResult)) { return base.GetRouteData(httpContext); } var urlParts = this.Url.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); bool correctArea = parts.Count() >= 1 ? !urlParts[0].StartsWith("{") ? urlParts[0].ToLower() == parts[0].ToLower() : true : true; if (correctArea) { bool isArea = parts.Count() >= 1 ? urlParts[0].ToLower() == parts[0].ToLower() : false; var culturePattern = "/[a-zA-Z]{2}$|/[a-zA-Z]{2}/|/[a-zA-Z]{2}-[a-zA-Z]{2}/"; var match = Regex.Match(virtualPath.Substring(1), culturePattern); if (!match.Success) { var newPath = virtualPath.Substring(2).ToLower(); if (isArea) { newPath = newPath.IndexOf("/") > -1 ? newPath.Insert(newPath.IndexOf("/") + 1, _culture + "/") : newPath + "/" + _culture; } else { newPath = _culture + "/" + newPath; } newPath = "~/" + newPath; httpContext.RewritePath(newPath, true); } } return base.GetRouteData(httpContext); }
protected virtual bool VerifyNode(ISiteMap siteMap, ISiteMapNode node, HttpContextBase httpContext) { // Time to delve into the AuthorizeAttribute defined on the node. // Let's start by getting all metadata for the controller... var controllerType = siteMap.ResolveControllerType(node.Area, node.Controller); if (controllerType == null) return true; var originalPath = httpContext.Request.Path; // Find routes for the sitemap node's url var routes = this.FindRoutesForNode(node, originalPath, httpContext); try { if (routes == null) return true; // Static URL's will have no route data, therefore return true. return this.VerifyController(node, routes, controllerType); } finally { // Restore HttpContext httpContext.RewritePath(originalPath, true); } }
protected virtual RouteData FindRoutesForNode(ISiteMapNode node, string originalPath, HttpContextBase httpContext) { var routes = mvcContextFactory.GetRoutes(); var originalRoutes = routes.GetRouteData(httpContext); var nodeUrl = node.Url; httpContext.RewritePath(nodeUrl, true); RouteData routeData = node.GetRouteData(httpContext); if (routeData != null) { foreach (var routeValue in node.RouteValues) { routeData.Values[routeValue.Key] = routeValue.Value; } if (originalRoutes != null && (!routeData.Route.Equals(originalRoutes.Route) || originalPath != nodeUrl || node.Area == String.Empty)) { routeData.DataTokens.Remove("area"); //routeData.DataTokens.Remove("Namespaces"); //routeData.Values.Remove("area"); } } return routeData; }
public override void PostResolveRequestCache(HttpContextBase context) { /* * New routes: * Path.format */ // .html == html // .xml == xml var formats = new Dictionary<string, string> { { ".html", "html" }, { ".xml", "xml" }, { ".media", "media" } }; var format = (string)null; var contentPath = (string)null; var parameters = (string)null; var ci = (IContentItem)null; var ri = (RequestItems)null; var path = context.Request.AppRelativeCurrentExecutionFilePath.Substring(1); if (!path.StartsWith("/@")) { while (!char.IsLetterOrDigit(path[path.Length - 1])) { path = path.Substring(0, path.Length - 1); } if (!path.Contains('.')) path = path + ".html"; if ("/default.aspx".Equals(path, StringComparison.CurrentCultureIgnoreCase)) { ri = new RequestItems { Content = ContentItem.GetResolved("/"), Format = "html", OriginalPath = context.Request.Path }; } else { foreach (var key in formats.Keys) { var startIndex = path.IndexOf(key, StringComparison.CurrentCultureIgnoreCase); if (startIndex > -1) { format = formats[key]; contentPath = path.Substring(0, startIndex); ci = ContentItem.GetResolved(contentPath); parameters = path.Substring(startIndex + key.Length); ri = new RequestItems { Content = ci, Format = format, OriginalPath = context.Request.Path }; break; } } } if (ri != null) { context.Items["mubble_RequestItems"] = ri; var newPath = parameters; if (ci is Article) newPath = "/article" + newPath; else newPath = "/content" + newPath; if (format == "media") { newPath = "/file" + parameters; } context.RewritePath(newPath); } } base.PostResolveRequestCache(context); //RouteData routeData = this.RouteCollection.GetRouteData(context); //if (routeData != null) //{ // Type routeHandler = routeData.Route.RouteHandler; // if (routeHandler == null) // { // throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, AtlasWeb.UrlRoutingModule_NoRouteHandler, new object[] { routeData.Route.Url })); // } // IRouteHandler handler = (IRouteHandler)Activator.CreateInstance(routeHandler); // RequestContext requestContext = new RequestContext(context, routeData); // IHttpHandler httpHandler = handler.GetHttpHandler(requestContext); // if (httpHandler == null) // { // throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, AtlasWeb.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler })); // } // RequestData data2 = new RequestData(); // data2.OriginalPath = context.Request.Path; // data2.HttpHandler = httpHandler; // context.Items[_requestDataKey] = data2; // context.RewritePath("~/Mvc.axd"); //} }
/// <summary> /// Implements the Early Url Localization logic. /// <see href="https://docs.google.com/drawings/d/1cH3_PRAFHDz7N41l8Uz7hOIRGpmgaIlJe0fYSIOSZ_Y/edit?usp=sharing"/> /// </summary> public void ProcessIncoming( System.Web.HttpContextBase context) { // Is URL explicitly excluded from localization? if (!m_urlLocalizer.FilterIncoming(context.Request.Url)) { return; } // YES. Continue handling request. bool allowRedirect = context.Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) || context.Request.HttpMethod.Equals("HEAD", StringComparison.OrdinalIgnoreCase); // NO. Is request URL localized? string urlNonlocalized; string langtag = m_urlLocalizer.ExtractLangTagFromUrl(context, context.Request.RawUrl, UriKind.Relative, true, out urlNonlocalized); if (langtag == null) { // NO. // langtag = best match between // 1. Inferred user languages (cookie and Accept-Language header) // 2. App Languages. LanguageTag lt = context.GetInferredLanguage(); // If redirection allowed...redirect user agent (browser) to localized URL. // The principle purpose of this redirection is to ensure the browser is showing the correct URL // in its address field. if (allowRedirect) { RedirectWithLanguage(context, context.Request.RawUrl, lt.ToString(), m_urlLocalizer); return; } // Otherwise, handle the request under the language infered above but without doing the redirect. // NB: this will mean that the user agent (browser) won't have the correct URL displayed; // however, this typically won't be an issue because we are talking about POST, PUT and DELETE methods // here which are typically not shown to the user. else { context.SetPrincipalAppLanguageForRequest(lt); return; // Continue handling request. } } // YES. Does langtag EXACTLY match an App Language? LanguageTag appLangTag = LanguageHelpers.GetMatchingAppLanguage(langtag); if (appLangTag.IsValid() && appLangTag.Equals(langtag)) { // YES. Establish langtag as the PAL for the request. context.SetPrincipalAppLanguageForRequest(appLangTag); // Rewrite URL for this request. context.RewritePath(urlNonlocalized); // Continue handling request. return; } // NO. Does langtag LOOSELY match an App Language? else if (appLangTag.IsValid() && !appLangTag.Equals(langtag)) { // YES. Localize URL with matching App Language. // Conditionally redirect user agent to localized URL. if (allowRedirect) { RedirectWithLanguage(context, urlNonlocalized, appLangTag.ToString(), m_urlLocalizer); return; } } // NO. Do nothing to URL; expect a 404 which corresponds to language not supported. // Continue handling request. }
/// <summary> /// Rewrites to the default back office page. /// </summary> /// <param name="context"></param> private static void RewriteToBackOfficeHandler(HttpContextBase context) { // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) var rewritePath = GlobalSettings.Path.TrimEnd(new[] { '/' }) + "/Default"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", "", false); //if it is MVC we need to do something special, we are not using TransferRequest as this will //require us to rewrite the path with query strings and then reparse the query strings, this would //also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create //an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does: // * Looks up the route based on the new rewritten URL // * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route //we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal //so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink //a bunch of things! var urlRouting = new UrlRoutingModule(); urlRouting.PostResolveRequestCache(context); }