Example #1
0
        /// <summary>Matches the route.</summary>
        /// <param name="routes">The routes.</param>
        /// <param name="method">The method.</param>
        /// <param name="requestPath">The request path.</param>
        /// <returns></returns>
        public async Task <ApiRoutingItem> MatchRoute(
            IApiRoutingTable routes,
            string method,
            string requestPath)
        {
            var potentialRoutes = routes?.GetRoutes()
                                  .Where(r => r.Location != null)
                                  .Where(r => string.Compare(r.HttpMethod, method, true) == 0);

            potentialRoutes = potentialRoutes ?? new List <ApiRoutingItem>();

            RouteMatch result;

            foreach (var route in potentialRoutes)
            {
                result = await this.ResolveRoute(route.Template, requestPath).ConfigureAwait(false);

                if (result?.IsMatch ?? false)
                {
                    var newRoute = CloneRoutingItem(route);
                    newRoute.RouteVariables = result.RouteVariables;
                    return(newRoute);
                }
            }

            return(null);
        }
Example #2
0
        /// <summary>Discovers the routes.</summary>
        /// <param name="builder">The builder.</param>
        /// <param name="routingTable">The routing table.</param>
        /// <param name="config">The configuration.</param>
        private static void DiscoverRoutes(IApplicationBuilder builder, IApiRoutingTable routingTable, IDeepSleepServiceConfiguration config)
        {
            var discoveryStrategies = config?.DiscoveryStrategies == null || config.DiscoveryStrategies.Count == 0
                ? DiscoveryStrategies.Default()
                : config.DiscoveryStrategies.Where(d => d != null).ToList();

            foreach (var strategy in discoveryStrategies)
            {
                if (strategy == null)
                {
                    continue;
                }

                var task = Task.Run(async() =>
                {
                    using (var scope = builder.ApplicationServices.CreateScope())
                    {
                        return(await strategy.DiscoverRoutes(scope.ServiceProvider).ConfigureAwait(false));
                    }
                });

                var registrations = task.Result;

                foreach (var registration in registrations)
                {
                    if (registration == null)
                    {
                        continue;
                    }

                    routingTable.AddRoute(registration);
                }
            }
        }
Example #3
0
        /// <summary>Gets the template information.</summary>
        /// <param name="context">The context.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="routes">The routes.</param>
        /// <returns></returns>
        private static async Task <ApiRoutingTemplate> GetRoutingTemplate(
            this ApiRequestContext context,
            IUriRouteResolver resolver,
            IApiRoutingTable routes)
        {
            RouteMatch         result;
            ApiRoutingTemplate template = null;

            foreach (var route in routes.GetRoutes())
            {
                result = await resolver.ResolveRoute(route.Template, context.Request.Path).ConfigureAwait(false);

                if (result?.IsMatch ?? false)
                {
                    if (template == null)
                    {
                        template = new ApiRoutingTemplate(route.Template);
                    }

                    template.Locations.Add(new ApiEndpointLocation(
                                               controller: route.Location.Controller,
                                               methodInfo: route.Location.MethodInfo,
                                               httpMethod: route.Location.HttpMethod,
                                               bodyParameterType: route.Location.BodyParameterType,
                                               uriParameterType: route.Location.UriParameterType,
                                               simpleParameters: route.Location.SimpleParameters,
                                               methodReturnType: route.Location.MethodReturnType));
                }
            }

            return(template);
        }
Example #4
0
        /// <summary>Processes the HTTP request method.</summary>
        /// <param name="context">The context.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="defaultRequestConfiguration">The default request configuration.</param>
        /// <returns></returns>
        internal static async Task <bool> ProcessHttpRequestMethod(this ApiRequestContext context,
                                                                   IApiRoutingTable routes,
                                                                   IUriRouteResolver resolver,
                                                                   IDeepSleepRequestConfiguration defaultRequestConfiguration)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                // Templates exist for thies route
                if ((context.Routing?.Template?.Locations?.Count ?? 0) > 0)
                {
                    // A route was not found for the template
                    if (context.Routing.Route == null)
                    {
                        var methods = context.Routing.Template.Locations
                                      .Where(e => !string.IsNullOrWhiteSpace(e?.HttpMethod))
                                      .Select(e => e.HttpMethod.ToUpper())
                                      .Distinct()
                                      .ToList();

                        if (methods.Contains("GET") && !methods.Contains("HEAD"))
                        {
                            if (resolver != null)
                            {
                                var match = await resolver.MatchRoute(
                                    routes,
                                    "GET",
                                    context.Request.Path).ConfigureAwait(false);

                                if (match != null)
                                {
                                    var enableHeadForGetRequests = match.Configuration?.EnableHeadForGetRequests
                                                                   ?? defaultRequestConfiguration?.EnableHeadForGetRequests
                                                                   ?? ApiRequestContext.GetDefaultRequestConfiguration().EnableHeadForGetRequests
                                                                   ?? true;

                                    if (enableHeadForGetRequests)
                                    {
                                        methods.Add("HEAD");
                                    }
                                }
                            }
                        }

                        context.Runtime.Internals.IsMethodNotFound = true;
                        context.Response.AddHeader("Allow", string.Join(", ", methods));
                        context.Response.StatusCode = 405;

                        return(false);
                    }
                }

                return(true);
            }

            return(false);
        }
Example #5
0
        /// <summary>Writes the deepsleep to console.</summary>
        /// <param name="routingTable">The routing table.</param>
        /// <param name="defaultConfiguration">The default configuration.</param>
        internal static void WriteDeepSleepToConsole(IApiRoutingTable routingTable, IDeepSleepRequestConfiguration defaultConfiguration)
        {
            var systemConfiguration = ApiRequestContext.GetDefaultRequestConfiguration();
            var existingColor       = Console.ForegroundColor;

            var deepSleepAssemblyInfo        = GetAssemplyInfo(typeof(ApiRequestContext));
            var deepSleepWebAssemblyInfo     = GetAssemplyInfo(typeof(ApiCoreHttpExtensionMethods));
            var deepSleepOpenApiAssemblyInfo = GetAssemplyInfo(Type.GetType("DeepSleep.OpenApi.DeepSleepOasGenerator, deepsleep.openapi", false, false));

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($@"");
            Console.WriteLine($@" ____                  _             ");
            Console.WriteLine($@"|    \ ___ ___ ___ ___| |___ ___ ___ ");
            Console.WriteLine($@"|  |  | -_| -_| . |_ -| | -_| -_| . |");
            Console.WriteLine($@"|____/|___|___|  _|___|_|___|___|  _|");
            Console.Write($@"              |_|               |_|  ");
            Console.ForegroundColor = existingColor;

            Console.WriteLine($"   v{deepSleepAssemblyInfo.version}");
            Console.WriteLine($"");

            if (!string.IsNullOrWhiteSpace(deepSleepWebAssemblyInfo.framework))
            {
                Console.WriteLine($"");
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"Target(s): ");
                Console.ForegroundColor = existingColor;
                Console.WriteLine($"------------------------------------------------");
                Console.ForegroundColor = existingColor;
                Console.WriteLine($"           {deepSleepAssemblyInfo.name}, {deepSleepAssemblyInfo.version}, {deepSleepAssemblyInfo.framework}");

                if (!string.IsNullOrWhiteSpace(deepSleepOpenApiAssemblyInfo.name))
                {
                    Console.WriteLine($"           {deepSleepOpenApiAssemblyInfo.name}, {deepSleepOpenApiAssemblyInfo.version}, {deepSleepOpenApiAssemblyInfo.framework}");
                }

                Console.WriteLine($"           {deepSleepWebAssemblyInfo.name}, {deepSleepWebAssemblyInfo.version}, {deepSleepWebAssemblyInfo.framework}");
                Console.WriteLine($"");
            }


            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write($"Endpoints: ");
            Console.ForegroundColor = existingColor;
            Console.WriteLine($"{routingTable?.GetRoutes()?.Count ?? 0}");
            Console.WriteLine($"------------------------------------------------");
            Console.WriteLine($"");

            var routes = (routingTable?.GetRoutes() ?? new List <ApiRoutingItem>())
                         .OrderBy(r => r.Template)
                         .ToList();

            Action <string, string, bool> writeRoute = (string method, string template, bool isAutoHead) =>
            {
                existingColor = Console.ForegroundColor;

                Console.ForegroundColor = isAutoHead ? ConsoleColor.Gray : ConsoleColor.Yellow;
                Console.Write($"  {method.ToUpper(),-9}");
                Console.ForegroundColor = existingColor;

                WriteEndpointTemplate(template, isAutoHead);
            };

            routes.ForEach(r =>
            {
                writeRoute(r.HttpMethod, r.Template, false);

                if (string.Compare(r.HttpMethod, "GET", true) == 0)
                {
                    var enableGet = r.Configuration?.EnableHeadForGetRequests
                                    ?? defaultConfiguration?.EnableHeadForGetRequests
                                    ?? systemConfiguration?.EnableHeadForGetRequests
                                    ?? true;

                    if (enableGet)
                    {
                        var matchingHead = routes
                                           .Where(m => m.HttpMethod.ToLowerInvariant() == "head")
                                           .Where(m => m.Template.ToLowerInvariant() == r.Template.ToLowerInvariant())
                                           .FirstOrDefault();

                        if (matchingHead == null)
                        {
                            writeRoute("HEAD", r.Template, true);
                        }
                    }
                }
            });

            Console.WriteLine("");

            var now = DateTime.Now;

            if (now.Month == 5 && now.Day == 4)
            {
                MayTheFourth();
            }

            Console.WriteLine();
        }
Example #6
0
        /// <summary>Processes the HTTP request routing.</summary>
        /// <param name="context">The context.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="defaultRequestConfig">The default request configuration.</param>
        /// <returns></returns>
        internal static async Task <bool> ProcessHttpRequestRouting(this ApiRequestContext context,
                                                                    IApiRoutingTable routes,
                                                                    IUriRouteResolver resolver,
                                                                    IDeepSleepRequestConfiguration defaultRequestConfig)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                if (routes != null && resolver != null)
                {
                    context.Routing.Route = await context.GetRoutingItem(resolver, routes, defaultRequestConfig).ConfigureAwait(false);

                    context.Routing.Template = await context.GetRoutingTemplate(resolver, routes).ConfigureAwait(false);
                }

                context.Configuration = MergeConfigurations(
                    serviceProvider: context?.RequestServices,
                    defaultConfig: defaultRequestConfig,
                    endpointConfig: context.Routing?.Route?.Configuration);

                if (context.Routing.Route?.Location?.MethodInfo != null)
                {
                    var attributes = context.Routing.Route.Location.MethodInfo.GetCustomAttributes();

                    // Find any attribute request pipeline components
                    // and add the to the final configuration of the request.
                    attributes
                    .Where(a => a as IRequestPipelineComponent != null)
                    .Select(a => a as IRequestPipelineComponent)
                    .ToList()
                    .ForEach(p => context.Configuration.PipelineComponents.Add(p));

                    // Find any attribute validator components
                    // and add the to the final configuration of the request.
                    attributes
                    .Where(a => a as IEndpointValidatorComponent != null)
                    .Select(a => a as IEndpointValidatorComponent)
                    .ToList()
                    .ForEach(v => context.Configuration.Validators.Add(v));

                    // Find any authentication components
                    // and add the to the final configuration of the request.
                    var authenticationComponents = attributes
                                                   .Where(a => a as IAuthenticationComponent != null)
                                                   .Select(a => a as IAuthenticationComponent)
                                                   .ToList();

                    if (authenticationComponents.Count > 0)
                    {
                        context.Configuration.AuthenticationProviders = authenticationComponents;
                    }

                    // Find any authorization components
                    // and add the to the final configuration of the request.
                    var authorizationComponents = attributes
                                                  .Where(a => a as IAuthorizationComponent != null)
                                                  .Select(a => a as IAuthorizationComponent)
                                                  .ToList();

                    if (authorizationComponents.Count > 0)
                    {
                        context.Configuration.AuthorizationProviders = authorizationComponents;
                    }
                }


                if (context.Configuration?.RequestValidation?.MaxRequestLength != null && context.ConfigureMaxRequestLength != null)
                {
                    try
                    {
                        context.ConfigureMaxRequestLength(context.Configuration.RequestValidation.MaxRequestLength.Value);
                    }
                    catch { }
                }

                return(true);
            }

            return(false);
        }
Example #7
0
        /// <summary>Gets the route information.</summary>
        /// <param name="context">The context.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="defaultRequestConfiguration">The default request configuration.</param>
        /// <returns></returns>
        private static async Task <ApiRoutingItem> GetRoutingItem(this ApiRequestContext context,
                                                                  IUriRouteResolver resolver,
                                                                  IApiRoutingTable routes,
                                                                  IDeepSleepRequestConfiguration defaultRequestConfiguration)
        {
            // -----------------------------------------------------------------
            // We want to trick the routing engine to treat HEAD requests as GET
            // http://tools.ietf.org/html/rfc7231#section-4.3.2
            // -----------------------------------------------------------------
            ApiRoutingItem routeInfo;

            if (context.Request.Method.In(StringComparison.InvariantCultureIgnoreCase, "HEAD"))
            {
                routeInfo = await resolver.MatchRoute(
                    routes,
                    "HEAD",
                    context.Request.Path).ConfigureAwait(false);

                if (routeInfo == null)
                {
                    routeInfo = await resolver.MatchRoute(
                        routes,
                        "GET",
                        context.Request.Path).ConfigureAwait(false);

                    if (routeInfo != null)
                    {
                        var enableHeadForGetRequests = routeInfo.Configuration?.EnableHeadForGetRequests
                                                       ?? defaultRequestConfiguration?.EnableHeadForGetRequests
                                                       ?? ApiRequestContext.GetDefaultRequestConfiguration().EnableHeadForGetRequests
                                                       ?? true;

                        if (!enableHeadForGetRequests)
                        {
                            routeInfo = null;
                        }
                    }
                }
            }
            else if (context.Request.IsCorsPreflightRequest())
            {
                if (context.Request.CrossOriginRequest.AccessControlRequestMethod.In(StringComparison.InvariantCultureIgnoreCase, "HEAD"))
                {
                    routeInfo = await resolver.MatchRoute(
                        routes,
                        context.Request.CrossOriginRequest.AccessControlRequestMethod,
                        context.Request.Path).ConfigureAwait(false);

                    if (routeInfo == null)
                    {
                        routeInfo = await resolver.MatchRoute(
                            routes,
                            "GET",
                            context.Request.Path).ConfigureAwait(false);

                        if (routeInfo != null)
                        {
                            var enableHeadForGetRequests = routeInfo.Configuration?.EnableHeadForGetRequests
                                                           ?? defaultRequestConfiguration?.EnableHeadForGetRequests
                                                           ?? ApiRequestContext.GetDefaultRequestConfiguration().EnableHeadForGetRequests
                                                           ?? true;

                            if (!enableHeadForGetRequests)
                            {
                                routeInfo = null;
                            }
                        }
                    }
                }
                else
                {
                    routeInfo = await resolver.MatchRoute(
                        routes,
                        context.Request.CrossOriginRequest.AccessControlRequestMethod,
                        context.Request.Path).ConfigureAwait(false);
                }
            }
            else
            {
                routeInfo = await resolver.MatchRoute(
                    routes,
                    context.Request.Method,
                    context.Request.Path).ConfigureAwait(false);
            }

            return(routeInfo);
        }
Example #8
0
        /// <summary>Processes the HTTP request cross origin resource sharing preflight.</summary>
        /// <param name="context">The context.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="defaultRequestConfiguration">The default request configuration.</param>
        /// <returns></returns>
        internal static async Task <bool> ProcessHttpRequestCrossOriginResourceSharingPreflight(
            this ApiRequestContext context,
            IApiRoutingTable routes,
            IUriRouteResolver resolver,
            IDeepSleepRequestConfiguration defaultRequestConfiguration)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                if (context.Request?.IsCorsPreflightRequest() ?? false)
                {
                    var methods = (context.Routing?.Template?.Locations ?? new List <ApiEndpointLocation>())
                                  .Where(r => !string.IsNullOrWhiteSpace(r.HttpMethod))
                                  .Select(r => r.HttpMethod.ToUpper())
                                  .Distinct()
                                  .ToList();

                    // Need to include the auto-enabled HEAD method if configured on the get endpoint (if available)
                    var hasGet = methods.FirstOrDefault(m => m.Equals("GET", StringComparison.InvariantCultureIgnoreCase)) != null;
                    if (hasGet)
                    {
                        var hasHead = methods.FirstOrDefault(m => m.Equals("HEAD", StringComparison.InvariantCultureIgnoreCase)) != null;
                        if (!hasHead)
                        {
                            if (resolver != null)
                            {
                                var getMatch = await resolver.MatchRoute(
                                    routes,
                                    "GET",
                                    context.Request.Path).ConfigureAwait(false);

                                if (getMatch != null)
                                {
                                    var enableHeadForGetRequests = getMatch.Configuration?.EnableHeadForGetRequests
                                                                   ?? defaultRequestConfiguration?.EnableHeadForGetRequests
                                                                   ?? ApiRequestContext.GetDefaultRequestConfiguration().EnableHeadForGetRequests
                                                                   ?? true;

                                    if (enableHeadForGetRequests)
                                    {
                                        methods.Add("HEAD");
                                    }
                                }
                            }
                        }
                    }


                    context.Response.StatusCode = 200;

                    context.Response.AddHeader("Access-Control-Allow-Methods", string.Join(", ", methods).Trim());

                    if (!string.IsNullOrWhiteSpace(context.Request?.CrossOriginRequest?.AccessControlRequestHeaders))
                    {
                        var allowHeaders = (context.Configuration?.CrossOriginConfig?.AllowedHeaders ?? new string[] { })
                                           .Distinct()
                                           .Where(i => !string.IsNullOrWhiteSpace(i))
                                           .Select(i => i.Trim())
                                           .ToList();

                        if (allowHeaders.Count > 0 && allowHeaders.Contains("*"))
                        {
                            context.Response.AddHeader("Access-Control-Allow-Headers", context.Request.CrossOriginRequest.AccessControlRequestHeaders);
                        }
                        else
                        {
                            context.Response.AddHeader("Access-Control-Allow-Headers", string.Join(", ", allowHeaders));
                        }
                    }

                    if (context.Configuration?.CrossOriginConfig?.MaxAgeSeconds.HasValue ?? false)
                    {
                        context.Response.AddHeader("Access-Control-Max-Age", $"{context.Configuration.CrossOriginConfig.MaxAgeSeconds.Value}");
                    }


                    return(false);
                }

                return(true);
            }

            return(false);
        }