示例#1
0
        /// <summary>Resolves the configuration.</summary>
        /// <param name="serviceProvider">The service provider.</param>
        /// <param name="config">The configuration.</param>
        /// <returns></returns>
        private static IDeepSleepRequestConfiguration GetNewConfiguration(IServiceProvider serviceProvider, IDeepSleepRequestConfiguration config)
        {
            if (config == null)
            {
                return(null);
            }

            IDeepSleepRequestConfiguration init = null;

            if (serviceProvider != null)
            {
                try
                {
                    init = serviceProvider.GetService(config.GetType()) as IDeepSleepRequestConfiguration;
                }
                catch { }
            }

            if (init == null)
            {
                init = Activator.CreateInstance(config.GetType()) as IDeepSleepRequestConfiguration;
            }

            return(init);
        }
示例#2
0
 /// <summary>Initializes a new instance of the <see cref="DeepSleepRouteRegistration"/> class.</summary>
 /// <param name="template">The template.</param>
 /// <param name="httpMethods">The HTTP methods.</param>
 /// <param name="controller">The controller.</param>
 /// <param name="endpoint">The endpoint.</param>
 /// <param name="config">The configuration.</param>
 /// <exception cref="System.Exception">
 /// Controller must be specified
 /// or
 /// Endpoint must be specified
 /// or
 /// </exception>
 /// <exception cref="System.MissingMethodException"></exception>
 public DeepSleepRouteRegistration(
     string template,
     IList <string> httpMethods,
     Type controller,
     string endpoint,
     IDeepSleepRequestConfiguration config)
     : this(template, httpMethods, controller, endpoint, null, config)
 {
 }
示例#3
0
 /// <summary>Initializes a new instance of the <see cref="DeepSleepRouteRegistration" /> class.</summary>
 /// <param name="template">The template.</param>
 /// <param name="httpMethods">The HTTP methods.</param>
 /// <param name="controller">The controller.</param>
 /// <param name="methodInfo">The method information.</param>
 /// <param name="config">The configuration.</param>
 /// <exception cref="Exception">Controller must be specified
 /// or
 /// Endpoint must be specified
 /// or</exception>
 public DeepSleepRouteRegistration(
     string template,
     IList <string> httpMethods,
     Type controller,
     MethodInfo methodInfo,
     IDeepSleepRequestConfiguration config)
     : this(template, httpMethods, controller, methodInfo?.Name, methodInfo, config)
 {
 }
示例#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);
        }
示例#5
0
        private DeepSleepRouteRegistration(
            string template,
            IList <string> httpMethods,
            Type controller,
            string endpoint,
            MethodInfo methodInfo,
            IDeepSleepRequestConfiguration config)
        {
            if (controller == null)
            {
                throw new Exception("Controller must be specified");
            }

            if (string.IsNullOrWhiteSpace(endpoint) && methodInfo == null)
            {
                throw new Exception($"{nameof(endpoint)} or {nameof(methodInfo)} must be specified");
            }

            if (httpMethods?.Count == 0)
            {
                throw new Exception($"Http methods not specified on endpoint {endpoint} in controller {controller.FullName}");
            }

            this.Template      = template ?? string.Empty;
            this.HttpMethods   = httpMethods.Select(m => m.ToUpperInvariant()).ToList();
            this.Configuration = config;
            this.Controller    = Type.GetType(controller.AssemblyQualifiedName);
            this.Endpoint      = endpoint;

            if (methodInfo != null)
            {
                var parameters = methodInfo.GetParameters();

                var methods = this.Controller
                              .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod)
                              .Where(m => m.Name == methodInfo.Name)
                              .ToList();

                if (methods.Count == 0)
                {
                    this.MethodInfo = null;
                }
                else if (methods.Count == 1)
                {
                    this.MethodInfo = methods[0];
                }
                else
                {
                    // TODO: Handle this for overloads
                }
            }

            this.MethodInfo = methodInfo;
        }
示例#6
0
        internal static async Task <IList <string> > GetRequestBodyContentTypes(
            Type requestBodyType,
            IServiceProvider serviceProvider,
            IDeepSleepRequestConfiguration routeConfiguration,
            IDeepSleepMediaSerializerFactory formatterFactory,
            OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0)
        {
            var formatterTypes = routeConfiguration?.ReadWriteConfiguration?.ReadableMediaTypes
                                 ?? formatterFactory?.GetReadableTypes(objType: requestBodyType, overridingFormatters: null)
                                 ?? new List <string>();


            if (routeConfiguration?.ReadWriteConfiguration?.ReaderResolver != null)
            {
                var overrides = await routeConfiguration.ReadWriteConfiguration.ReaderResolver(serviceProvider).ConfigureAwait(false);

                if (overrides?.Formatters != null)
                {
                    formatterTypes = overrides.Formatters
                                     .Where(f => f != null)
                                     .Where(f => f.CanHandleType(requestBodyType))
                                     .Where(f => f.SupportsRead)
                                     .Where(f => f.ReadableMediaTypes != null)
                                     .SelectMany(f => f.ReadableMediaTypes)
                                     .Distinct()
                                     .ToList();

                    formatterTypes = routeConfiguration?.ReadWriteConfiguration?.ReadableMediaTypes ?? formatterTypes ?? new List <string>();
                }
                else
                {
                    formatterTypes = routeConfiguration?.ReadWriteConfiguration?.ReadableMediaTypes ?? new List <string>();
                }
            }

            if (specVersion == OpenApiSpecVersion.OpenApi2_0)
            {
                formatterTypes = formatterTypes
                                 .Where(type => string.Compare(type, "application/x-www-form-urlencoded", true) != 0)
                                 .ToList();
            }

            return(formatterTypes.ToList());
        }
示例#7
0
        internal static async Task <IList <string> > GetResponseBodyContentTypes(
            Type responseBodyType,
            IServiceProvider serviceProvider,
            IDeepSleepRequestConfiguration routeConfiguration,
            IDeepSleepMediaSerializerFactory formatterFactory)
        {
            var formatterTypes = routeConfiguration?.ReadWriteConfiguration?.WriteableMediaTypes
                                 ?? formatterFactory?.GetWriteableTypes(objType: responseBodyType, overridingFormatters: null)
                                 ?? new List <string>();

            if (routeConfiguration?.ReadWriteConfiguration?.WriterResolver != null)
            {
                var overrides = await routeConfiguration.ReadWriteConfiguration.WriterResolver(serviceProvider).ConfigureAwait(false);

                if (overrides?.Formatters != null)
                {
                    formatterTypes = routeConfiguration?.ReadWriteConfiguration?.WriteableMediaTypes
                                     ?? formatterFactory?.GetWriteableTypes(objType: responseBodyType, overridingFormatters: overrides.Formatters)
                                     ?? new List <string>();
                }
            }

            return(formatterTypes?.ToList() ?? new List <string>());
        }
示例#8
0
        /// <summary>Adds the route.</summary>
        /// <param name="template">The template.</param>
        /// <param name="httpMethods">The HTTP methods.</param>
        /// <param name="controller">The controller.</param>
        /// <param name="endpoint">The endpoint.</param>
        /// <param name="config">The configuration.</param>
        /// <returns></returns>
        public StaticRouteDiscoveryStrategy AddRoute(string template, IList <string> httpMethods, Type controller, string endpoint, IDeepSleepRequestConfiguration config)
        {
            var registration = new DeepSleepRouteRegistration(
                template: template,
                httpMethods: httpMethods,
                controller: controller,
                endpoint: endpoint,
                config: config);

            registrations.Add(registration);
            return(this);
        }
示例#9
0
        /// <summary>Processes the HTTP response caching.</summary>
        /// <param name="context">The context.</param>
        /// <param name="defaultRequestConfiguration">The default request configuration.</param>
        /// <returns></returns>
        internal static Task <bool> ProcessHttpResponseCaching(this ApiRequestContext context, IDeepSleepRequestConfiguration defaultRequestConfiguration)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                var statusCode          = context.Response.StatusCode;
                var systemConfiguration = ApiRequestContext.GetDefaultRequestConfiguration();

                var expirationSeconds = context.Configuration?.CacheDirective?.ExpirationSeconds
                                        ?? defaultRequestConfiguration?.CacheDirective?.ExpirationSeconds
                                        ?? systemConfiguration.CacheDirective.ExpirationSeconds.Value;

                var cacheability = context.Configuration?.CacheDirective?.Cacheability
                                   ?? defaultRequestConfiguration?.CacheDirective?.Cacheability
                                   ?? systemConfiguration.CacheDirective.Cacheability.Value;

                var cacheLocation = context.Configuration?.CacheDirective?.CacheLocation
                                    ?? defaultRequestConfiguration?.CacheDirective?.CacheLocation
                                    ?? systemConfiguration.CacheDirective.CacheLocation.Value;

                var vary = context.Configuration?.CacheDirective?.VaryHeaderValue
                           ?? defaultRequestConfiguration?.CacheDirective?.VaryHeaderValue
                           ?? systemConfiguration.CacheDirective.VaryHeaderValue;

                if (statusCode >= 200 && statusCode <= 299 && statusCode != 204)
                {
                    // Don't add cache headers for pre-flight requests
                    // This is handled in the prflight pipeline component
                    if (context.Request.IsCorsPreflightRequest())
                    {
                        return(Task.FromResult(true));
                    }

                    if (cacheability == HttpCacheType.Cacheable)
                    {
                        var maxAgeSeconds = expirationSeconds < 0
                            ? 0
                            : expirationSeconds;

                        context.Response.AddHeader("Cache-Control", $"{cacheLocation.ToString().ToLower()}, max-age={maxAgeSeconds}");
                        context.Response.AddHeader("Expires", DateTime.UtcNow.AddSeconds(expirationSeconds).ToString("r"));

                        if (!string.IsNullOrWhiteSpace(vary))
                        {
                            // ADDING VARY HEADERS TO SPECIFY WHAT THE RESPONSE REPRESENTATION WAS GENERATED AGAINST.
                            context.Response.AddHeader(
                                name: "Vary",
                                value: vary,
                                append: true);
                        }

                        return(Task.FromResult(true));
                    }
                }

                var seconds = expirationSeconds > 0
                    ? -1
                    : expirationSeconds;

                context.Response.AddHeader("Cache-Control", $"no-store, max-age=0");

                // this gets updated when the response date is added to the headers.  THe value will
                // ultimately be the response date - expiration seconds.  Needs to be here though because the header is checked
                // for prior to updating it.
                context.Response.AddHeader("Expires", DateTime.UtcNow.AddSeconds(seconds).ToString("r"));
            }

            return(Task.FromResult(true));
        }
示例#10
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();
        }
示例#11
0
        /// <summary>Processes the API request.</summary>
        /// <param name="context">The context.</param>
        /// <param name="httpcontext">The httpcontext.</param>
        /// <param name="contextResolver">The context resolver.</param>
        /// <param name="requestPipeline">The request pipeline.</param>
        /// <param name="defaultRequestConfiguration">The default request configuration.</param>
        /// <returns></returns>
        internal static async Task <bool> ProcessApiRequest(
            this ApiRequestContext context,
            HttpContext httpcontext,
            IApiRequestContextResolver contextResolver,
            IApiRequestPipeline requestPipeline,
            IDeepSleepRequestConfiguration defaultRequestConfiguration)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                await requestPipeline.Run(contextResolver);

                context.SetThreadCulure();

                var responseDate = DateTimeOffset.UtcNow;
                context.Response.Date = responseDate;

                context.Response.AddHeader(
                    name: "Date",
                    value: responseDate.ToString("r"),
                    append: false,
                    allowMultiple: false);

                httpcontext.Response.Headers.Add("Date", responseDate.ToString("r"));

                // Sync up the expire header for nocache requests with the date header being used
                var contextExpiresHeader = context.Response.Headers.FirstOrDefault(h => h.Name == "Expires");

                var expirationSeconds = context.Configuration?.CacheDirective?.ExpirationSeconds
                                        ?? defaultRequestConfiguration?.CacheDirective?.ExpirationSeconds
                                        ?? ApiRequestContext.GetDefaultRequestConfiguration().CacheDirective.ExpirationSeconds.Value;

                var cacheability = context.Configuration?.CacheDirective?.Cacheability
                                   ?? defaultRequestConfiguration?.CacheDirective?.Cacheability
                                   ?? ApiRequestContext.GetDefaultRequestConfiguration().CacheDirective.Cacheability.Value;

                if (contextExpiresHeader != null)
                {
                    if (cacheability == HttpCacheType.NoCache && expirationSeconds > 0)
                    {
                        contextExpiresHeader.Value = responseDate.AddSeconds(-1).ToString("r");
                    }
                    else
                    {
                        contextExpiresHeader.Value = responseDate.AddSeconds(expirationSeconds).ToString("r");
                    }
                }

                // Merge status code to the http response
                httpcontext.Response.StatusCode = context.Response.StatusCode;

                if (context.Response.ResponseWriter != null && context.Response.ResponseWriterOptions != null)
                {
                    context.Response.AddHeader(
                        name: "Content-Type",
                        value: context.Response.ContentType.ToString(),
                        append: false,
                        allowMultiple: false);

                    if (!string.IsNullOrWhiteSpace(context.Response.ContentLanguage))
                    {
                        context.Response.AddHeader(
                            name: "Content-Language",
                            value: context.Response.ContentLanguage,
                            append: false,
                            allowMultiple: false);
                    }


                    if (!context.Request.IsHeadRequest())
                    {
                        var contentLength = await context.Response.ResponseWriter.WriteType(
                            stream : httpcontext.Response.Body,
                            obj : context.Response.ResponseObject,
                            context.Response.ResponseWriterOptions,
                            (l) =>
                        {
                            context.Response.ContentLength = l;

                            context.Response.AddHeader(
                                name: "Content-Length",
                                value: l.ToString(CultureInfo.InvariantCulture),
                                append: false,
                                allowMultiple: false);

                            AddHeadersToResponse(httpcontext, context);
                        }).ConfigureAwait(false);

                        context.Response.ContentLength = contentLength;
                    }
                    else
                    {
                        using (var ms = new MemoryStream())
                        {
                            await context.Response.ResponseWriter.WriteType(
                                ms,
                                context.Response.ResponseObject,
                                context.Response.ResponseWriterOptions).ConfigureAwait(false);

                            context.Response.ResponseObject = null;
                            context.Response.ContentLength  = ms.Length;

                            context.Response.AddHeader(
                                name: "Content-Length",
                                value: ms.Length.ToString(CultureInfo.InvariantCulture),
                                append: false,
                                allowMultiple: false);

                            AddHeadersToResponse(httpcontext, context);
                        }
                    }
                }
                else
                {
                    context.Response.ContentLength = 0;
                    context.Response.AddHeader("Content-Length", "0");
                    AddHeadersToResponse(httpcontext, context);
                }

                context.Runtime.Duration.UtcEnd = DateTime.UtcNow;
            }

            return(true);
        }
示例#12
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);
        }
示例#13
0
        /// <summary>Merges the configurations.</summary>
        /// <param name="serviceProvider">The service provider.</param>
        /// <param name="defaultConfig">The default configuration.</param>
        /// <param name="endpointConfig">The endpoint configuration.</param>
        /// <returns></returns>
        public static IDeepSleepRequestConfiguration MergeConfigurations(
            IServiceProvider serviceProvider,
            IDeepSleepRequestConfiguration defaultConfig,
            IDeepSleepRequestConfiguration endpointConfig)
        {
            IDeepSleepRequestConfiguration systemConfig = ApiRequestContext.GetDefaultRequestConfiguration();

            IDeepSleepRequestConfiguration requestConfig = (endpointConfig != null)
                ? GetNewConfiguration(serviceProvider, endpointConfig)
                : GetNewConfiguration(serviceProvider, defaultConfig);

            if (requestConfig == null)
            {
                return(systemConfig);
            }


            requestConfig.ApiErrorResponseProvider = endpointConfig?.ApiErrorResponseProvider
                                                     ?? defaultConfig?.ApiErrorResponseProvider
                                                     ?? systemConfig.ApiErrorResponseProvider;

            requestConfig.AllowAnonymous = endpointConfig?.AllowAnonymous
                                           ?? defaultConfig?.AllowAnonymous
                                           ?? systemConfig.AllowAnonymous;

            requestConfig.EnableHeadForGetRequests = endpointConfig?.EnableHeadForGetRequests
                                                     ?? defaultConfig?.EnableHeadForGetRequests
                                                     ?? systemConfig.EnableHeadForGetRequests;


            // ----------------------------
            // Authorization Components
            // ----------------------------
            if (endpointConfig?.AuthorizationProviders != null || defaultConfig?.AuthorizationProviders != null)
            {
                if (endpointConfig?.AuthorizationProviders != null)
                {
                    requestConfig.AuthorizationProviders = new List <IAuthorizationComponent>(endpointConfig.AuthorizationProviders);
                }
                else if (defaultConfig?.AuthorizationProviders != null)
                {
                    requestConfig.AuthorizationProviders = new List <IAuthorizationComponent>(defaultConfig.AuthorizationProviders);
                }
                else
                {
                    requestConfig.AuthorizationProviders = systemConfig.AuthorizationProviders;
                }
            }
            else
            {
                requestConfig.AuthorizationProviders = systemConfig.AuthorizationProviders;
            }


            // ----------------------------
            // Authentication Components
            // ----------------------------
            if (endpointConfig?.AuthenticationProviders != null || defaultConfig?.AuthenticationProviders != null)
            {
                if (endpointConfig?.AuthenticationProviders != null)
                {
                    requestConfig.AuthenticationProviders = new List <IAuthenticationComponent>(endpointConfig.AuthenticationProviders);
                }
                else if (defaultConfig?.AuthenticationProviders != null)
                {
                    requestConfig.AuthenticationProviders = new List <IAuthenticationComponent>(defaultConfig.AuthenticationProviders);
                }
                else
                {
                    requestConfig.AuthenticationProviders = systemConfig.AuthenticationProviders;
                }
            }
            else
            {
                requestConfig.AuthenticationProviders = systemConfig.AuthenticationProviders;
            }


            // ----------------------------
            // Validator Components
            // ----------------------------
            if (endpointConfig?.Validators != null || defaultConfig?.Validators != null)
            {
                if (endpointConfig?.Validators != null)
                {
                    requestConfig.Validators = new List <IEndpointValidatorComponent>(endpointConfig.Validators);
                }
                else if (defaultConfig?.Validators != null)
                {
                    requestConfig.Validators = new List <IEndpointValidatorComponent>(defaultConfig.Validators);
                }
                else
                {
                    requestConfig.Validators = systemConfig.Validators;
                }
            }
            else
            {
                requestConfig.Validators = systemConfig.Validators;
            }

            // ----------------------------
            // Pipeline Components
            // ----------------------------
            if (endpointConfig?.PipelineComponents != null || defaultConfig?.PipelineComponents != null)
            {
                if (endpointConfig?.PipelineComponents != null)
                {
                    requestConfig.PipelineComponents = new List <IRequestPipelineComponent>(endpointConfig.PipelineComponents);
                }
                else if (defaultConfig?.PipelineComponents != null)
                {
                    requestConfig.PipelineComponents = new List <IRequestPipelineComponent>(defaultConfig.PipelineComponents);
                }
                else
                {
                    requestConfig.PipelineComponents = systemConfig.PipelineComponents;
                }
            }
            else
            {
                requestConfig.PipelineComponents = systemConfig.PipelineComponents;
            }

            // ----------------------------
            // Language Support Validation
            // ----------------------------
            if (endpointConfig?.LanguageSupport != null || defaultConfig?.LanguageSupport != null)
            {
                requestConfig.LanguageSupport = new ApiLanguageSupportConfiguration
                {
                    FallBackLanguage = endpointConfig?.LanguageSupport?.FallBackLanguage
                                       ?? defaultConfig?.LanguageSupport?.FallBackLanguage
                                       ?? systemConfig.LanguageSupport?.FallBackLanguage,

                    SupportedLanguages = new List <string>(endpointConfig?.LanguageSupport?.SupportedLanguages
                                                           ?? defaultConfig?.LanguageSupport?.SupportedLanguages
                                                           ?? systemConfig.LanguageSupport?.SupportedLanguages),

                    UseAcceptedLanguageAsThreadCulture = endpointConfig?.LanguageSupport?.UseAcceptedLanguageAsThreadCulture
                                                         ?? defaultConfig?.LanguageSupport?.UseAcceptedLanguageAsThreadCulture
                                                         ?? systemConfig.LanguageSupport?.UseAcceptedLanguageAsThreadCulture,

                    UseAcceptedLanguageAsThreadUICulture = endpointConfig?.LanguageSupport?.UseAcceptedLanguageAsThreadUICulture
                                                           ?? defaultConfig?.LanguageSupport?.UseAcceptedLanguageAsThreadUICulture
                                                           ?? systemConfig.LanguageSupport?.UseAcceptedLanguageAsThreadUICulture
                };

                var endpointSupportedLanguages = endpointConfig?.LanguageSupport?.SupportedLanguages != null
                    ? new List <string>(endpointConfig.LanguageSupport.SupportedLanguages)
                    : null;

                var defaultSupportedLanguages = defaultConfig?.LanguageSupport?.SupportedLanguages != null
                    ? new List <string>(defaultConfig.LanguageSupport.SupportedLanguages)
                    : null;

                requestConfig.LanguageSupport.SupportedLanguages = endpointSupportedLanguages ?? defaultSupportedLanguages ?? systemConfig.LanguageSupport?.SupportedLanguages;
            }
            else
            {
                requestConfig.LanguageSupport = systemConfig.LanguageSupport;
            }

            // ----------------------------
            // Merge Request Validation
            // ----------------------------
            if (endpointConfig?.RequestValidation != null || defaultConfig?.RequestValidation != null)
            {
                requestConfig.RequestValidation = new ApiRequestValidationConfiguration
                {
                    MaxHeaderLength = endpointConfig?.RequestValidation?.MaxHeaderLength
                                      ?? defaultConfig?.RequestValidation?.MaxHeaderLength
                                      ?? systemConfig.RequestValidation?.MaxHeaderLength,
                    MaxRequestUriLength = endpointConfig?.RequestValidation?.MaxRequestUriLength
                                          ?? defaultConfig?.RequestValidation?.MaxRequestUriLength
                                          ?? systemConfig.RequestValidation?.MaxRequestUriLength,
                    MaxRequestLength = endpointConfig?.RequestValidation?.MaxRequestLength
                                       ?? defaultConfig?.RequestValidation?.MaxRequestLength
                                       ?? systemConfig.RequestValidation?.MaxRequestLength,
                    AllowRequestBodyWhenNoModelDefined = endpointConfig?.RequestValidation?.AllowRequestBodyWhenNoModelDefined
                                                         ?? defaultConfig?.RequestValidation?.AllowRequestBodyWhenNoModelDefined
                                                         ?? systemConfig.RequestValidation?.AllowRequestBodyWhenNoModelDefined,
                    RequireContentLengthOnRequestBodyRequests = endpointConfig?.RequestValidation?.RequireContentLengthOnRequestBodyRequests
                                                                ?? defaultConfig?.RequestValidation?.RequireContentLengthOnRequestBodyRequests
                                                                ?? systemConfig.RequestValidation?.RequireContentLengthOnRequestBodyRequests
                };
            }
            else
            {
                requestConfig.RequestValidation = systemConfig.RequestValidation;
            }

            // ----------------------------
            // Merge Cache Directive
            // ----------------------------
            if (endpointConfig?.CacheDirective != null || defaultConfig?.CacheDirective != null)
            {
                requestConfig.CacheDirective = new ApiCacheDirectiveConfiguration
                {
                    Cacheability = endpointConfig?.CacheDirective?.Cacheability
                                   ?? defaultConfig?.CacheDirective?.Cacheability
                                   ?? systemConfig.CacheDirective?.Cacheability,

                    CacheLocation = endpointConfig?.CacheDirective?.CacheLocation
                                    ?? defaultConfig?.CacheDirective?.CacheLocation
                                    ?? systemConfig.CacheDirective?.CacheLocation,

                    ExpirationSeconds = endpointConfig?.CacheDirective?.ExpirationSeconds
                                        ?? defaultConfig?.CacheDirective?.ExpirationSeconds
                                        ?? systemConfig.CacheDirective?.ExpirationSeconds,

                    VaryHeaderValue = endpointConfig?.CacheDirective?.VaryHeaderValue
                                      ?? defaultConfig?.CacheDirective?.VaryHeaderValue
                                      ?? systemConfig.CacheDirective?.VaryHeaderValue
                };
            }
            else
            {
                requestConfig.CacheDirective = systemConfig.CacheDirective;
            }


            // ----------------------------
            // Merge Cross Origin Configuration
            // ----------------------------
            if (endpointConfig?.CrossOriginConfig != null || defaultConfig?.CrossOriginConfig != null)
            {
                requestConfig.CrossOriginConfig = new ApiCrossOriginConfiguration
                {
                    AllowCredentials = endpointConfig?.CrossOriginConfig?.AllowCredentials
                                       ?? defaultConfig?.CrossOriginConfig?.AllowCredentials
                                       ?? systemConfig?.CrossOriginConfig?.AllowCredentials,
                    MaxAgeSeconds = endpointConfig?.CrossOriginConfig?.MaxAgeSeconds
                                    ?? defaultConfig?.CrossOriginConfig?.MaxAgeSeconds
                                    ?? systemConfig?.CrossOriginConfig?.MaxAgeSeconds
                };

                var endpointAllowedOrigins = endpointConfig?.CrossOriginConfig?.AllowedOrigins != null
                    ? new List <string>(endpointConfig.CrossOriginConfig.AllowedOrigins)
                    : null;

                var defaultAllowedOrigins = defaultConfig?.CrossOriginConfig?.AllowedOrigins != null
                    ? new List <string>(defaultConfig.CrossOriginConfig.AllowedOrigins)
                    : null;

                requestConfig.CrossOriginConfig.AllowedOrigins = endpointAllowedOrigins ?? defaultAllowedOrigins ?? systemConfig.CrossOriginConfig?.AllowedOrigins;

                var endpointExposeHeaders = endpointConfig?.CrossOriginConfig?.ExposeHeaders != null
                    ? new List <string>(endpointConfig.CrossOriginConfig.ExposeHeaders)
                    : null;

                var defaultExposeHeaders = defaultConfig?.CrossOriginConfig?.ExposeHeaders != null
                    ? new List <string>(defaultConfig.CrossOriginConfig.ExposeHeaders)
                    : null;

                requestConfig.CrossOriginConfig.ExposeHeaders = endpointExposeHeaders ?? defaultExposeHeaders ?? systemConfig.CrossOriginConfig?.ExposeHeaders;

                var endpointAllowedHeaders = endpointConfig?.CrossOriginConfig?.AllowedHeaders != null
                    ? new List <string>(endpointConfig.CrossOriginConfig.AllowedHeaders)
                    : null;

                var defaultAllowedHeaders = defaultConfig?.CrossOriginConfig?.AllowedHeaders != null
                    ? new List <string>(defaultConfig.CrossOriginConfig.AllowedHeaders)
                    : null;

                requestConfig.CrossOriginConfig.AllowedHeaders = endpointAllowedHeaders ?? defaultAllowedHeaders ?? systemConfig.CrossOriginConfig?.AllowedHeaders;
            }
            else
            {
                requestConfig.CrossOriginConfig = systemConfig.CrossOriginConfig;
            }


            // ----------------------------
            // Merge Read Write Configuration
            // ----------------------------
            if (endpointConfig?.ReadWriteConfiguration != null || defaultConfig?.ReadWriteConfiguration != null)
            {
                requestConfig.ReadWriteConfiguration = new ApiMediaSerializerConfiguration
                {
                    ReaderResolver = endpointConfig?.ReadWriteConfiguration?.ReaderResolver
                                     ?? defaultConfig?.ReadWriteConfiguration?.ReaderResolver
                                     ?? systemConfig.ReadWriteConfiguration?.ReaderResolver,

                    WriterResolver = endpointConfig?.ReadWriteConfiguration?.WriterResolver
                                     ?? defaultConfig?.ReadWriteConfiguration?.WriterResolver
                                     ?? systemConfig.ReadWriteConfiguration?.WriterResolver,

                    AcceptHeaderOverride = endpointConfig?.ReadWriteConfiguration?.AcceptHeaderOverride
                                           ?? defaultConfig?.ReadWriteConfiguration?.AcceptHeaderOverride
                                           ?? systemConfig.ReadWriteConfiguration?.AcceptHeaderOverride,
                };

                var endpointReadableMediaTypes = endpointConfig?.ReadWriteConfiguration?.ReadableMediaTypes != null
                    ? new List <string>(endpointConfig.ReadWriteConfiguration.ReadableMediaTypes)
                    : null;

                var defaultReadableMediaTypes = defaultConfig?.ReadWriteConfiguration?.ReadableMediaTypes != null
                    ? new List <string>(defaultConfig.ReadWriteConfiguration.ReadableMediaTypes)
                    : null;

                var endpointWriteableMediaTypes = endpointConfig?.ReadWriteConfiguration?.WriteableMediaTypes != null
                    ? new List <string>(endpointConfig.ReadWriteConfiguration.WriteableMediaTypes)
                    : null;

                var defaultWriteableMediaTypes = defaultConfig?.ReadWriteConfiguration?.WriteableMediaTypes != null
                    ? new List <string>(defaultConfig.ReadWriteConfiguration.WriteableMediaTypes)
                    : null;

                requestConfig.ReadWriteConfiguration.ReadableMediaTypes = endpointReadableMediaTypes
                                                                          ?? defaultReadableMediaTypes
                                                                          ?? systemConfig.ReadWriteConfiguration?.ReadableMediaTypes;

                requestConfig.ReadWriteConfiguration.WriteableMediaTypes = endpointWriteableMediaTypes
                                                                           ?? defaultWriteableMediaTypes
                                                                           ?? systemConfig.ReadWriteConfiguration?.WriteableMediaTypes;
            }
            else
            {
                requestConfig.ReadWriteConfiguration = systemConfig.ReadWriteConfiguration;
            }


            // ------------------------------------
            // Merge Validation Error Configuration
            // ------------------------------------
            if (endpointConfig?.ValidationErrorConfiguration != null || defaultConfig?.ValidationErrorConfiguration != null)
            {
                requestConfig.ValidationErrorConfiguration = new ApiValidationErrorConfiguration
                {
                    UriBindingError = endpointConfig?.ValidationErrorConfiguration?.UriBindingError
                                      ?? defaultConfig?.ValidationErrorConfiguration?.UriBindingError
                                      ?? systemConfig.ValidationErrorConfiguration?.UriBindingError,

                    UriBindingValueError = endpointConfig?.ValidationErrorConfiguration?.UriBindingValueError
                                           ?? defaultConfig?.ValidationErrorConfiguration?.UriBindingValueError
                                           ?? systemConfig.ValidationErrorConfiguration?.UriBindingValueError,

                    RequestDeserializationError = endpointConfig?.ValidationErrorConfiguration?.RequestDeserializationError
                                                  ?? defaultConfig?.ValidationErrorConfiguration?.RequestDeserializationError
                                                  ?? systemConfig.ValidationErrorConfiguration?.RequestDeserializationError,

                    HttpStatusMode = endpointConfig?.ValidationErrorConfiguration?.HttpStatusMode
                                     ?? defaultConfig?.ValidationErrorConfiguration?.HttpStatusMode
                                     ?? systemConfig.ValidationErrorConfiguration.HttpStatusMode
                };
            }
            else
            {
                requestConfig.ValidationErrorConfiguration = systemConfig.ValidationErrorConfiguration;
            }


            return(requestConfig);
        }
示例#14
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);
        }
示例#15
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);
        }