Пример #1
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());
        }
Пример #2
0
        /// <summary>Processes the HTTP request body binding.</summary>
        /// <param name="context">The context.</param>
        /// <param name="contextResolver">The API request context resolver.</param>
        /// <param name="formatterFactory">The formatter factory.</param>
        /// <returns></returns>
        internal static async Task <bool> ProcessHttpRequestBodyBinding(this ApiRequestContext context, IApiRequestContextResolver contextResolver, IDeepSleepMediaSerializerFactory formatterFactory)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                if (context.Request.Method?.In(StringComparison.InvariantCultureIgnoreCase, "post", "patch", "put") ?? false)
                {
                    if (!context.Request.ContentLength.HasValue)
                    {
                        if (context.Configuration?.RequestValidation?.RequireContentLengthOnRequestBodyRequests ?? true)
                        {
                            context.Response.StatusCode = 411;
                            return(false);
                        }
                    }

                    if (context.Request.ContentLength > 0 && string.IsNullOrWhiteSpace(context.Request.ContentType))
                    {
                        context.Response.StatusCode = 415;
                        return(false);
                    }

                    if (context.Configuration?.RequestValidation?.MaxRequestLength > 0 && context.Request.ContentLength > 0)
                    {
                        if (context.Request.ContentLength > context.Configuration.RequestValidation.MaxRequestLength)
                        {
                            context.Response.StatusCode = 413;
                            return(false);
                        }
                    }

                    if (context.Request.ContentLength > 0 && context.Routing?.Route?.Location?.BodyParameterType == null)
                    {
                        if (!(context.Configuration?.RequestValidation?.AllowRequestBodyWhenNoModelDefined ?? false))
                        {
                            context.Response.StatusCode = 413;
                            return(false);
                        }
                    }

                    if (context.Routing.Route.Location.BodyParameterType != null && context.Request.ContentLength > 0 && !string.IsNullOrWhiteSpace(context.Request.ContentType))
                    {
                        IDeepSleepMediaSerializer formatter = null;

                        var formatterTypes = context.Configuration?.ReadWriteConfiguration?.ReadableMediaTypes
                                             ?? formatterFactory?.GetReadableTypes(objType: context.Routing.Route.Location.BodyParameterType, overridingFormatters: null)
                                             ?? new List <string>();

                        if (formatterFactory != null)
                        {
                            formatter = await formatterFactory.GetContentTypeFormatter(
                                contentTypeHeader : context.Request.ContentType,
                                objType : context.Routing.Route.Location.BodyParameterType,
                                formatterType : out var _,
                                readableMediaTypes : context.Configuration?.ReadWriteConfiguration?.ReadableMediaTypes).ConfigureAwait(false);
                        }

                        if (context.Configuration.ReadWriteConfiguration?.ReaderResolver != null)
                        {
                            var overrides = await context.Configuration.ReadWriteConfiguration.ReaderResolver(context?.RequestServices).ConfigureAwait(false);

                            if (overrides?.Formatters != null)
                            {
                                formatter = await formatterFactory.GetContentTypeFormatter(
                                    contentTypeHeader : context.Request.ContentType,
                                    objType : context.Routing.Route.Location.BodyParameterType,
                                    formatterType : out var _,
                                    readableFormatters : overrides.Formatters,
                                    readableMediaTypes : context.Configuration?.ReadWriteConfiguration?.ReadableMediaTypes).ConfigureAwait(false);

                                formatterTypes = overrides.Formatters
                                                 .Where(f => f != null)
                                                 .Where(f => f.SupportsRead)
                                                 .Where(f => f.ReadableMediaTypes != null)
                                                 .Where(f => f.CanHandleType(context.Routing.Route.Location.BodyParameterType))
                                                 .SelectMany(f => f.ReadableMediaTypes)
                                                 .Distinct()
                                                 .ToList();

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



                        if (formatter == null)
                        {
                            context.Response.StatusCode = 415;

                            context.Response.AddHeader(
                                name: "X-Allow-Content-Types",
                                value: string.Join(", ", formatterTypes),
                                append: false,
                                allowMultiple: false);

                            return(false);
                        }


                        Encoding contextTypeEncoding = null;

                        if (context.Request.ContentType != null as string)
                        {
                            if (!string.IsNullOrWhiteSpace(context.Request.ContentType.Charset))
                            {
                                try
                                {
                                    contextTypeEncoding = Encoding.GetEncoding(context.Request.ContentType.Charset);
                                }
                                catch { }
                            }
                        }


                        try
                        {
                            context.Request.InvocationContext.BodyModel = await formatter.ReadType(
                                stream : context.Request.Body,
                                objType : context.Routing.Route.Location.BodyParameterType,
                                options : new MediaSerializerOptions
                            {
                                Culture  = context.Request.AcceptCulture,
                                Encoding = contextTypeEncoding ?? Encoding.UTF8
                            }).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            context.AddInternalException(ex);

                            if (ex.GetType().Name.Contains("BadHttpRequestException"))
                            {
                                context.Response.StatusCode = 413;
                            }
                            else
                            {
                                context.AddValidationError(context.Configuration?.ValidationErrorConfiguration?.RequestDeserializationError);
                                context.Response.StatusCode = 400;
                            }

                            return(false);
                        }
                    }
                }

                return(true);
            }

            return(false);
        }