/// <summary> /// Initializes a new instance of the MatchedRoute class. /// </summary> /// <param name="route">The existing route to create this instance from.</param> public MatchedRoute(MatchedRoute route) { if (route == null) { throw new ArgumentNullException("route", "route cannot be null."); } this.RouteType = route.RouteType; this.ReaderType = route.ReaderType; this.WriterType = route.WriterType; }
/// <summary> /// Gets the <see cref="IResponseWriter"/> to use when writing the given HTTP context's response. /// </summary> /// <param name="context">The HTTP context to get the writer for.</param> /// <param name="route">The Kayson route to get the writer for.</param> /// <param name="configuredWriters">A dictionary of writers defined in the current configuration.</param> /// <returns>An <see cref="IResponseWriter"/> that can write the given HTTP context's response.</returns> /// <exception cref="System.InvalidOperationException"></exception> protected virtual IResponseWriter GetResponseWriter(HttpContextBase context, MatchedRoute route, IDictionary<string, Type> configuredWriters) { if (route != null && route.WriterType != null) { return (IResponseWriter)Activator.CreateInstance(route.WriterType); } else { foreach (string acceptType in context.Request.AcceptTypes) { string at = acceptType.ToUpperInvariant(); int separator = at.IndexOf(';'); if (separator > 0) { at = at.Substring(0, separator); } if (at.Equals("*/*", StringComparison.Ordinal)) { return new JsonResponseWriter(); } else if (configuredWriters.ContainsKey(at)) { return (IResponseWriter)Activator.CreateInstance(configuredWriters[at]); } } throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "The request does not specify an Accept type ({0}) that is in the configured writer list.", String.Join("; ", context.Request.AcceptTypes))); } }
/// <summary> /// Gets a Kayson route for a request. /// </summary> /// <param name="context">The request to get the route for.</param> /// <returns>The target of a Kayson route or null if none was found.</returns> protected virtual MatchedRoute GetRoute(HttpContext context) { MatchedRoute routesTo = null; string virtualUrl = context.Request.RawUrl.Substring(context.Request.ApplicationPath.Length).ToUpperInvariant(); if (!virtualUrl.StartsWith("/", StringComparison.Ordinal)) { virtualUrl = "/" + virtualUrl; } virtualUrl = "~" + virtualUrl; // We need to syncronize the read/update of the route cache. lock (locker) { // Grab or instantiate the cache. Dictionary<string, MatchedRoute> cache = (Dictionary<string, MatchedRoute>)(context.Cache[RouteCacheKey] ?? new Dictionary<string, MatchedRoute>()); // If we have something, we're done. if (cache.ContainsKey(virtualUrl)) { routesTo = cache[virtualUrl]; } else { // Search for a matching route. foreach (RouteElement route in KaysonSettings.Section.Routes) { Match match = Regex.Match(virtualUrl, route.Pattern, RegexOptions.IgnoreCase); if (match.Success) { Type routeType = CreateTypeFromRouteString(match.Result(route.RoutesTo)); if (routeType != null) { routesTo = new MatchedRoute( routeType, CreateTypeFromRouteString(route.ReaderType), CreateTypeFromRouteString(route.WriterType)); } else { throw new InvalidRequestTypeException(); } break; } } // Update the cache. cache[virtualUrl] = routesTo; context.Cache[RouteCacheKey] = cache; } } return routesTo; }
/// <summary> /// Gets the <see cref="IRequestReader"/> to use when reading the given HTTP context's request. /// </summary> /// <param name="context">The HTTP context to get the reader for.</param> /// <param name="route">The Kayson route to get the reader for.</param> /// <param name="configuredReaders">A dictionary of readers defined in the current configuration.</param> /// <returns>An <see cref="IRequestReader"/> that can read the given HTTP context's request.</returns> /// <exception cref="System.InvalidOperationException"></exception> protected virtual IRequestReader GetRequestReader(HttpContextBase context, MatchedRoute route, IDictionary<string, Type> configuredReaders) { if (route != null && route.ReaderType != null) { return (IRequestReader)Activator.CreateInstance(route.ReaderType); } else { string ct = context.Request.ContentType.ToUpperInvariant(); int separator = ct.IndexOf(';'); if (separator > 0) { ct = ct.Substring(0, separator); } if (configuredReaders.ContainsKey(ct)) { return (IRequestReader)Activator.CreateInstance(configuredReaders[ct]); } throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "The request specifies a Content-Type ({0}) not in the configured reader list.", context.Request.ContentType)); } }
/// <summary> /// Rewrites the current request to the Kayson handler. /// </summary> /// <param name="context">The HttpContext to rewrite.</param> /// <param name="routesTo">The target Kayson route.</param> protected virtual void Rewrite(HttpContext context, MatchedRoute routesTo) { context.Items[TargetItemsKey] = routesTo; context.RewritePath(KaysonSettings.Section.HandlerUrl); }