internal static string GetClosestClientMediaType(this IEnumerable <TextOutputFormatter> outputFormatters, ResourceFormat resourceFormat, IEnumerable <string> acceptHeaders)
        {
            // When overriding the MediaType with the query string parameter
            // some browsers don't display the response when returning "application/fhir+xml".
            // For this reason we try to match a media type from the OutputFormatter with the request Accept header.

            string closestClientMediaType = null;
            string preferred = resourceFormat.ToContentType();

            if (outputFormatters != null && acceptHeaders != null)
            {
                // Gets formatters that can write the desired format
                var validFormatters = outputFormatters
                                      .Where(x => x.GetSupportedContentTypes(preferred, typeof(Resource)) != null)
                                      .ToArray();

                var acceptHeadersArray = acceptHeaders.ToArray();

                // Using the valid formatters, select the correct content type header for the client
                closestClientMediaType = acceptHeadersArray
                                         .SelectMany(x => validFormatters.SelectMany(y => y.GetSupportedContentTypes(x, typeof(Resource)) ?? Enumerable.Empty <string>()))
                                         .Distinct()
                                         .Intersect(acceptHeadersArray)
                                         .FirstOrDefault();
            }

            return(closestClientMediaType ?? preferred);
        }
示例#2
0
        public async Task CheckRequestedContentTypeAsync(HttpContext httpContext)
        {
            var    acceptHeaders  = httpContext.Request.GetTypedHeaders().Accept;
            string formatOverride = GetFormatFromQueryString(httpContext);

            // Check the _format first since it takes precedence over the accept header.
            if (!string.IsNullOrEmpty(formatOverride))
            {
                ResourceFormat resourceFormat = ContentType.GetResourceFormatFromFormatParam(formatOverride);
                if (!await IsFormatSupportedAsync(resourceFormat))
                {
                    throw new NotAcceptableException(Api.Resources.UnsupportedFormatParameter);
                }

                string closestClientMediaType = _outputFormatters.GetClosestClientMediaType(resourceFormat.ToContentType(), acceptHeaders?.Select(x => x.MediaType.Value));

                // Overrides output format type
                httpContext.Response.ContentType = closestClientMediaType;
            }
            else
            {
                if (acceptHeaders != null && acceptHeaders.All(a => a.MediaType != "*/*"))
                {
                    var isAcceptHeaderValid = false;

                    foreach (MediaTypeHeaderValue acceptHeader in acceptHeaders)
                    {
                        isAcceptHeaderValid = await IsFormatSupportedAsync(acceptHeader.MediaType.ToString());

                        if (isAcceptHeaderValid)
                        {
                            break;
                        }
                    }

                    if (!isAcceptHeaderValid)
                    {
                        throw new NotAcceptableException(string.Format(Api.Resources.UnsupportedHeaderValue, HeaderNames.Accept));
                    }
                }
            }
        }