Example #1
0
        /// <summary>Gets the acceptable formatter.</summary>
        /// <param name="acceptHeader">The accept header.</param>
        /// <param name="objType">Type of the object.</param>
        /// <param name="formatterType">Type of the formatter.</param>
        /// <param name="writeableFormatters">The overriding formatters.</param>
        /// <param name="writeableMediaTypes">The writeable media types.</param>
        /// <returns></returns>
        public virtual Task <IDeepSleepMediaSerializer> GetAcceptableFormatter(
            AcceptHeader acceptHeader,
            Type objType,
            out string formatterType,
            IList <IDeepSleepMediaSerializer> writeableFormatters = null,
            IList <string> writeableMediaTypes = null)
        {
            formatterType = string.Empty;
            IDeepSleepMediaSerializer formatter = null;

            foreach (var mediaHeader in acceptHeader.Values.Where(m => m.Quality > 0))
            {
                formatter = this.Get(
                    contentType: $"{mediaHeader.Type}/{mediaHeader.SubType}",
                    objType: objType,
                    parameters: mediaHeader.ParameterString(),
                    forRead: false,
                    overridingFormatters: writeableFormatters,
                    overridingMediaTypes: writeableMediaTypes,
                    formatterType: out formatterType);

                if (formatter != null)
                {
                    break;
                }
            }

            return(Task.FromResult(formatter));
        }
Example #2
0
        /// <summary>Processes the HTTP request accept.</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> ProcessHttpRequestAccept(this ApiRequestContext context, IApiRequestContextResolver contextResolver, IDeepSleepMediaSerializerFactory formatterFactory)
        {
            if (!context.RequestAborted.IsCancellationRequested)
            {
                if (context.Request != null)
                {
                    var returnType = context.Routing.Route.Location.MethodReturnType;

                    if (returnType == typeof(void) || returnType == typeof(Task))
                    {
                        return(true);
                    }

                    var accept = !string.IsNullOrWhiteSpace(context.Request.Accept)
                        ? context.Request.Accept
                        : AcceptHeader.All();

                    IDeepSleepMediaSerializer         formatter            = null;
                    IList <IDeepSleepMediaSerializer> overridingFormatters = null;

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

                        overridingFormatters = overrides?.Formatters;
                    }

                    if (formatterFactory != null)
                    {
                        formatter = await formatterFactory.GetAcceptableFormatter(
                            acceptHeader : context.Configuration?.ReadWriteConfiguration?.AcceptHeaderOverride ?? accept,
                            objType : returnType,
                            writeableMediaTypes : context.Configuration?.ReadWriteConfiguration?.WriteableMediaTypes,
                            writeableFormatters : overridingFormatters,
                            formatterType : out var _).ConfigureAwait(false);


                        if (formatter == null && context.Configuration?.ReadWriteConfiguration?.AcceptHeaderFallback != null as AcceptHeader)
                        {
                            formatter = await formatterFactory.GetAcceptableFormatter(
                                acceptHeader : context.Configuration?.ReadWriteConfiguration.AcceptHeaderFallback,
                                objType : returnType,
                                writeableMediaTypes : context.Configuration?.ReadWriteConfiguration?.WriteableMediaTypes,
                                writeableFormatters : overridingFormatters,
                                formatterType : out var _).ConfigureAwait(false);
                        }
                    }

                    if (formatter == null)
                    {
                        var formatterTypes = formatterFactory != null
                            ? formatterFactory.GetWriteableTypes(objType : returnType, overridingFormatters : overridingFormatters) ?? new List <string>()
                            : new DeepSleepMediaSerializerWriterFactory(context.RequestServices).GetWriteableTypes(objType: returnType, overridingFormatters) ?? new List <string>();

                        var writeableMediaTypes = context.Configuration?.ReadWriteConfiguration?.WriteableMediaTypes ?? formatterTypes ?? new List <string>();

                        var acceptableTypes = writeableMediaTypes
                                              .Where(w => formatterTypes.Any(f => string.Equals(f, w, System.StringComparison.InvariantCultureIgnoreCase)))
                                              .ToList();

                        string acceptable = (acceptableTypes != null && acceptableTypes.Count > 0)
                            ? string.Join(", ", acceptableTypes)
                            : string.Empty;

                        context.Response.AddHeader("X-Allow-Accept", acceptable);
                        context.Response.StatusCode = 406;
                        return(false);
                    }
                }

                return(true);
            }

            return(false);
        }
Example #3
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);
        }