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); }
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)); } } } }