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()); }
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>()); }
/// <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); }
/// <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); }
/// <summary>Processes the HTTP response body writing.</summary> /// <param name="context">The context.</param> /// <param name="contextResolver">The context resolver.</param> /// <param name="formatterFactory">The formatter factory.</param> /// <returns></returns> internal static async Task <bool> ProcessHttpResponseBodyWriting(this ApiRequestContext context, IApiRequestContextResolver contextResolver, IDeepSleepMediaSerializerFactory formatterFactory) { if (!context.RequestAborted.IsCancellationRequested) { var isWriteableResponse = false; if (context.Response.ResponseObject != null && formatterFactory != null) { var accept = !string.IsNullOrWhiteSpace(context.Request.Accept) ? context.Request.Accept : AcceptHeader.All(); Encoding acceptEncoding = null; if (context.Request.AcceptCharset != null as string) { foreach (var value in context.Request.AcceptCharset.Values) { try { if (!string.IsNullOrWhiteSpace(value.Charset)) { acceptEncoding = Encoding.GetEncoding(value.Charset); } if (acceptEncoding != null) { break; } } catch { } } } IMediaSerializerOptions options = new MediaSerializerOptions { Culture = context.Request.AcceptCulture, Encoding = acceptEncoding ?? Encoding.UTF8 }; var returnType = context.Response.ResponseObject.GetType(); var formatter = await formatterFactory.GetAcceptableFormatter( objType : returnType, acceptHeader : context.Configuration?.ReadWriteConfiguration?.AcceptHeaderOverride ?? accept, writeableMediaTypes : context.Configuration?.ReadWriteConfiguration?.WriteableMediaTypes, formatterType : out var formatterType).ConfigureAwait(false); if (context.Configuration.ReadWriteConfiguration?.WriterResolver != null) { var overrides = await context.Configuration.ReadWriteConfiguration.WriterResolver(context?.RequestServices).ConfigureAwait(false); if (overrides?.Formatters != null) { formatter = await formatterFactory.GetAcceptableFormatter( objType : returnType, acceptHeader : context.Configuration?.ReadWriteConfiguration?.AcceptHeaderOverride ?? accept, writeableMediaTypes : context.Configuration?.ReadWriteConfiguration?.WriteableMediaTypes, writeableFormatters : overrides.Formatters, formatterType : out formatterType).ConfigureAwait(false); } } if (formatter != null) { isWriteableResponse = true; context.Response.ResponseWriter = formatter; context.Response.ResponseWriterOptions = options; context.Response.ContentType = formatterType; } } if (!isWriteableResponse) { if (context.Response.HasSuccessStatus() && context.Response.StatusCode != 202 && !(context.Runtime?.Internals?.IsOverridingStatusCode ?? false)) { context.Response.StatusCode = 204; } } } return(true); }