private ResolveResults Resolve(string path, NancyContext context, IRouteCache routeCache) { if (routeCache.IsEmpty()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No routes available")); return(new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null) }); } var routes = routeCache.GetRouteCandidates(); // Condition routes = routes.Filter(context, "Invalid condition", (ctx, route) => { var validCondition = ((route.Item3.Condition == null) || (route.Item3.Condition(ctx))); return(new Tuple <bool, RouteCandidate>( validCondition, route )); }); if (!routes.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No route had a valid condition")); return(new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }); } // Path routes = routes.Filter(context, "Path did not match", (ctx, route) => { var validationResult = this.routePatternMatcher.Match(path, route.Item3.Path, route.Item3.Segments, context); var routeToReturn = (validationResult.IsMatch) ? new RouteCandidate(route.Item1, route.Item2, route.Item3, validationResult) : route; return(new Tuple <bool, RouteCandidate>( validationResult.IsMatch, routeToReturn )); }); if (!routes.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No route matched the requested path")); return(new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }); } // Method routes = routes.Filter(context, "Request method did not match", (ctx, route) => { var routeMethod = route.Item3.Method.ToUpperInvariant(); var requestMethod = ctx.Request.Method.ToUpperInvariant(); var methodIsValid = routeMethod.Equals(requestMethod) || (routeMethod.Equals("GET") && requestMethod.Equals("HEAD")); return(new Tuple <bool, RouteCandidate>( methodIsValid, route )); }); if (!routes.Item1.Any()) { var allowedMethods = routes.Item2.Values.SelectMany(x => x.Select(y => y.Item3.Method)).Distinct(); if (context.Request.Method.Equals("OPTIONS")) { return(new ResolveResults { Selected = new ResolveResult(new OptionsRoute(context.Request.Path, allowedMethods), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }); } context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Route Matched But Method Not Allowed")); return(new ResolveResults { Selected = new ResolveResult(new MethodNotAllowedRoute(path, context.Request.Method, allowedMethods), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }); } // Exact match var exactMatchResults = routes.Filter(context, "No exact match", (ctx, route) => { var routeIsExactMatch = !route.Item4.Parameters.GetDynamicMemberNames().Any(); return(new Tuple <bool, RouteCandidate>( routeIsExactMatch, route )); }); if (exactMatchResults.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Found exact match route")); return(new ResolveResults { Selected = this.CreateRouteAndParametersFromMatch(context, exactMatchResults.Item1.First()), Rejected = exactMatchResults.Item2 }); } // First match out of multiple candidates var selected = GetTopRouteMatchesNew(routes).First(); context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Selected best match")); return(new ResolveResults { Selected = this.CreateRouteAndParametersFromMatch(context, selected), Rejected = exactMatchResults.Item2 }); }
private ResolveResults Resolve(string path, NancyContext context, IRouteCache routeCache) { if (routeCache.IsEmpty()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No routes available")); return new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null) }; } var routes = routeCache.GetRouteCandidates(); // Condition routes = routes.Filter(context, "Invalid condition", (ctx, route) => { var validCondition = ((route.Item3.Condition == null) || (route.Item3.Condition(ctx))); return new Tuple<bool, RouteCandidate>( validCondition, route ); }); if (!routes.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No route had a valid condition")); return new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }; } // Path routes = routes.Filter(context, "Path did not match", (ctx, route) => { var validationResult = this.routePatternMatcher.Match(path, route.Item3.Path, route.Item3.Segments, context); var routeToReturn = (validationResult.IsMatch) ? new RouteCandidate(route.Item1, route.Item2, route.Item3, validationResult) : route; return new Tuple<bool, RouteCandidate>( validationResult.IsMatch, routeToReturn ); }); if (!routes.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] No route matched the requested path")); return new ResolveResults { Selected = new ResolveResult(new NotFoundRoute(context.Request.Method, path), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }; } // Method routes = routes.Filter(context, "Request method did not match", (ctx, route) => { var routeMethod = route.Item3.Method.ToUpperInvariant(); var requestMethod = ctx.Request.Method.ToUpperInvariant(); var methodIsValid = routeMethod.Equals(requestMethod) || (routeMethod.Equals("GET") && requestMethod.Equals("HEAD")); return new Tuple<bool, RouteCandidate>( methodIsValid, route ); }); if (!routes.Item1.Any()) { var allowedMethods = routes.Item2.Values.SelectMany(x => x.Select(y => y.Item3.Method)).Distinct(); if (context.Request.Method.Equals("OPTIONS")) { return new ResolveResults { Selected = new ResolveResult(new OptionsRoute(context.Request.Path, allowedMethods), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }; } context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Route Matched But Method Not Allowed")); return new ResolveResults { Selected = new ResolveResult(new MethodNotAllowedRoute(path, context.Request.Method, allowedMethods), DynamicDictionary.Empty, null, null, null), Rejected = routes.Item2 }; } // Exact match var exactMatchResults = routes.Filter(context, "No exact match", (ctx, route) => { var routeIsExactMatch = !route.Item4.Parameters.GetDynamicMemberNames().Any(); return new Tuple<bool, RouteCandidate>( routeIsExactMatch, route ); }); if (exactMatchResults.Item1.Any()) { context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Found exact match route")); return new ResolveResults { Selected = this.CreateRouteAndParametersFromMatch(context, exactMatchResults.Item1.First()), Rejected = exactMatchResults.Item2 }; } // First match out of multiple candidates var selected = GetTopRouteMatchesNew(routes).First(); context.Trace.TraceLog.WriteLog(s => s.AppendLine("[DefaultRouteResolver] Selected best match")); return new ResolveResults { Selected = this.CreateRouteAndParametersFromMatch(context, selected), Rejected = exactMatchResults.Item2 }; }