/// <summary> /// Selects the <see cref="IOutputFormatter"/> to write the response based on the content type values /// present in <paramref name="sortedAcceptableContentTypes"/> and <paramref name="possibleOutputContentTypes"/>. /// </summary> /// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param> /// <param name="formatters"> /// The list of <see cref="IOutputFormatter"/> instances to consider. /// </param> /// <param name="sortedAcceptableContentTypes"> /// The ordered content types from the <c>Accept</c> header, sorted by descending q-value. /// </param> /// <param name="possibleOutputContentTypes"> /// The ordered content types from <see cref="ObjectResult.ContentTypes"/> in descending priority order. /// </param> /// <returns> /// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response. /// </returns> protected virtual IOutputFormatter SelectFormatterUsingSortedAcceptHeadersAndContentTypes( OutputFormatterWriteContext formatterContext, IList <IOutputFormatter> formatters, IList <MediaTypeSegmentWithQuality> sortedAcceptableContentTypes, MediaTypeCollection possibleOutputContentTypes) { for (var i = 0; i < sortedAcceptableContentTypes.Count; i++) { var acceptableContentType = new MediaType(sortedAcceptableContentTypes[i].MediaType); for (var j = 0; j < possibleOutputContentTypes.Count; j++) { var candidateContentType = new MediaType(possibleOutputContentTypes[j]); if (candidateContentType.IsSubsetOf(acceptableContentType)) { for (var k = 0; k < formatters.Count; k++) { var formatter = formatters[k]; formatterContext.ContentType = new StringSegment(possibleOutputContentTypes[j]); if (formatter.CanWriteResult(formatterContext)) { return(formatter); } } } } } return(null); }
public IActionResult GetBookForAuthor(Guid authorId, Guid id, [FromHeader(Name = Headers.Accept)] string mediaType) { if (!_libraryRepository.AuthorExists(authorId)) { return(NotFound()); } var loadedBook = _libraryRepository.GetBookForAuthor(authorId, id); if (loadedBook == null) { return(NotFound()); } var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); var book = Mapper.Map <Book>(loadedBook); if (includeLinks) { return(Ok(CreateLinks(book))); } else { return(Ok(book)); } }
private bool isFileAllowedType(IFormFile file) { if (FileTypes.Length == 0) { return(true); } string fileType = file.ContentType.ToLower(); var parsedContentType = new MediaType(fileType); for (var i = 0; i < FileTypes.Length; i++) { // For supported media types that are not wildcard patterns, confirm that this formatter // supports a more specific media type than requested e.g. OK if "text/*" requested and // formatter supports "text/plain". // contentType is typically what we got in an Accept header. var supportedMediaType = new MediaType(FileTypes[i]); if (parsedContentType.IsSubsetOf(supportedMediaType)) { return(true); } } return(false); }
/// <summary> /// Tests if the media type qualifies for XML deserialization /// </summary> /// <param name="mediaType">The media type to test</param> /// <returns><see langword="true"/> when the media type might be an XML type</returns> public static bool IsXml(string mediaType) { var contentType = new MediaType(mediaType); var isXml = XmlMediaTypes.Any(x => contentType.IsSubsetOf(x)); return(isXml); }
public IActionResult CreateAuthor([FromBody] CreateAuthor author, [FromHeader(Name = Headers.Accept)] string mediaType) { if (author == null) { return(BadRequest()); } var newAuthor = Mapper.Map <Entities.Author>(author); _repo.AddAuthor(newAuthor); if (!_repo.Save()) { throw new Exception("Failed to Create new author"); } var createdAuthor = Mapper.Map <Author>(newAuthor); var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); if (includeLinks) { var links = CreateLinks(createdAuthor.Id, null); var linkedResourceToReturn = createdAuthor.ShapeData(null) as IDictionary <string, object>; linkedResourceToReturn.Add("links", links); return(CreatedAtRoute(nameof(GetAuthor), new { id = linkedResourceToReturn[nameof(Author.Id)] }, linkedResourceToReturn)); } return(CreatedAtRoute(nameof(GetAuthor), new { id = createdAuthor.Id }, createdAuthor)); }
public IActionResult GetAuthor(Guid id, [FromQuery] string fields, [FromHeader(Name = Headers.Accept)] string mediaType) { if (!_typeHelperService.TypeHasProperties <Author>(fields)) { return(BadRequest()); } var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); var author = _repo.GetAuthor(id); if (author == null) { return(NotFound()); } var result = Mapper.Map <Author>(author); if (includeLinks) { var links = CreateLinks(id, fields); var linkedResourceToReturn = result.ShapeData(fields) as IDictionary <string, object>; linkedResourceToReturn.Add("links", links); return(Ok(linkedResourceToReturn)); } else { return(Ok(result)); } }
/// <inheritdoc /> public virtual IReadOnlyList <string>?GetSupportedContentTypes( string contentType, Type objectType) { if (SupportedMediaTypes.Count == 0) { var message = Resources.FormatFormatter_NoMediaTypes( GetType().FullName, nameof(SupportedMediaTypes)); throw new InvalidOperationException(message); } if (!CanWriteType(objectType)) { return(null); } List <string>?mediaTypes = null; var parsedContentType = contentType != null ? new MediaType(contentType) : default(MediaType); foreach (var mediaType in SupportedMediaTypes) { var parsedMediaType = new MediaType(mediaType); if (parsedMediaType.HasWildcard) { // For supported media types that are wildcard patterns, confirm that the requested // media type satisfies the wildcard pattern (e.g., if "text/entity+json;v=2" requested // and formatter supports "text/*+json"). // Treat contentType like it came from a [Produces] attribute. if (contentType != null && parsedContentType.IsSubsetOf(parsedMediaType)) { if (mediaTypes == null) { mediaTypes = new List <string>(SupportedMediaTypes.Count); } mediaTypes.Add(contentType); } } else { // Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*" // requested and formatter supports "text/plain". Treat contentType like it came from an Accept header. if (contentType == null || parsedMediaType.IsSubsetOf(parsedContentType)) { if (mediaTypes == null) { mediaTypes = new List <string>(SupportedMediaTypes.Count); } mediaTypes.Add(mediaType); } } } return(mediaTypes); }
public IActionResult GetAuthors([FromQuery] AuthorsResourceParameters parameters, [FromHeader(Name = Headers.Accept)] string mediaType) { if (!_propertyMappingService.ValidMappingExistsFor <Author, Entities.Author>(parameters.OrderBy)) { return(BadRequest()); } if (!_typeHelperService.TypeHasProperties <Author>(parameters.Fields)) { return(BadRequest()); } var authors = _repo.GetAuthors(parameters); var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); var prev = authors.HasPrevious ? CreateAuthorsResourceUri(parameters, ResourceUriType.Previous) : null; var next = authors.HasNext ? CreateAuthorsResourceUri(parameters, ResourceUriType.Next) : null; var result = Mapper.Map <IEnumerable <Author> >(authors); var pagination = new Pagination() { IncludeLinks = !includeLinks, TotalCount = authors.TotalCount, PageSize = authors.PageSize, CurrentPage = authors.CurrentPage, TotalPages = authors.TotalPages, NextPageLink = next, PreviousPageLink = prev, }; Pagination.AddHeader(Response, pagination); if (includeLinks) { var links = CreateLinks(parameters, authors.HasNext, authors.HasPrevious); var shapedAuthors = result.ShapeData(parameters.Fields); var shapedAuthorsWithLinks = shapedAuthors.Select(a => { var authorDictionary = a as IDictionary <string, object>; var authorLinks = CreateLinks((Guid)authorDictionary[nameof(Author.Id)], parameters.Fields); authorDictionary.Add("links", authorLinks); return(authorDictionary); } ); var linkCollection = new { value = shapedAuthorsWithLinks, links }; return(Ok(linkCollection)); } return(Ok(result)); }
public void IsSubsetOf_ReturnsFalseWhenExpected(string set, string subset) { // Arrange var setMediaType = new MediaType(set); var subSetMediaType = new MediaType(subset); // Act var result = subSetMediaType.IsSubsetOf(setMediaType); // Assert Assert.False(result); }
private static bool IsSubsetOfAny( this StringValues requestedMediaType, MediaTypeCollection mediaTypes) { if (requestedMediaType == default(StringValues)) { return(false); } var requested = new MediaType(requestedMediaType); return(mediaTypes.Any(mediaType => requested.IsSubsetOf(new MediaType(mediaType)))); }
private bool IsSubsetOfAnySupportedContentType(string contentType) { var parsedContentType = new MediaType(contentType); for (var i = 0; i < SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(SupportedMediaTypes[i]); if (parsedContentType.IsSubsetOf(supportedMediaType)) { return(true); } } return(false); }
private bool IsSubsetOfAnyContentType(string requestMediaType) { var parsedRequestMediaType = new MediaType(requestMediaType); for (var i = 0; i < ContentTypes.Count; i++) { var contentTypeMediaType = new MediaType(ContentTypes[i]); if (parsedRequestMediaType.IsSubsetOf(contentTypeMediaType)) { return(true); } } return(false); }
private async Task <Job> GetJobAsync(string targetTypeName, string targetMethodName) { var context = _httpContextAccessor.HttpContext; if (context == null) { return(null); } var jobEntry = _jobEntryResolver.GetJobEntry(targetTypeName, targetMethodName); if (jobEntry == null) { return(null); } FormCollection form = FormCollection.Empty; MediaType parsedContentType = new MediaType(context.Request.ContentType); if (parsedContentType.IsSubsetOf(_jobEntryResolver.SupportedMediaType)) { context.Request.Body.Position = 0; var body = await context.Request.BodyReader.ReadAsync(); var jsonString = Encoding.UTF8.GetString(body.Buffer.ToArray()); var dict = new Dictionary <string, StringValues>(); using (JsonDocument document = JsonDocument.Parse(jsonString)) { JsonElement root = document.RootElement; if (root.ValueKind.Equals(JsonValueKind.Object)) { foreach (JsonProperty jsonProperty in root.EnumerateObject()) { dict.Add(jsonProperty.Name, new StringValues(jsonProperty.Value.ToString())); } } } form = new FormCollection(dict); } Expression instance = null; if (!jobEntry.IsStaticMethod) { // 获取对象实例 var TargetInstance = ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, jobEntry.TargetType); instance = Expression.Constant(TargetInstance, jobEntry.TargetType); } var job = jobEntry.GetJob(instance, form); return(job); }
private static bool IsSuperSetOfAnySupportedMediaType(string contentType, MediaTypeCollection supportedMediaTypes) { var parsedContentType = new MediaType(contentType); for (var i = 0; i < supportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(supportedMediaTypes[i]); if (supportedMediaType.IsSubsetOf(parsedContentType)) { return(true); } } return(false); }
/// <inheritdoc /> public virtual bool CanWriteResult(OutputFormatterCanWriteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (SupportedMediaTypes.Count == 0) { var message = Resources.FormatFormatter_NoMediaTypes( GetType().FullName, nameof(SupportedMediaTypes)); throw new InvalidOperationException(message); } if (!CanWriteType(context.ObjectType)) { return false; } if (!context.ContentType.HasValue) { // If the desired content type is set to null, then the current formatter can write anything // it wants. context.ContentType = new StringSegment(SupportedMediaTypes[0]); return true; } else { // Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*" // requested and formatter supports "text/plain". contentType is typically what we got in an Accept // header. var parsedContentType = new MediaType(context.ContentType); for (var i = 0; i < SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(SupportedMediaTypes[i]); if (supportedMediaType.IsSubsetOf(parsedContentType)) { context.ContentType = new StringSegment(SupportedMediaTypes[i]); return true; } } } return false; }
public IActionResult GetRoot([FromHeader(Name = Headers.Accept)] string mediaType) { var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); if (includeLinks) { var links = new List <Link> { new Link(_urlHelper.Link(nameof(GetRoot), new { }), "self", "GET"), new Link(_urlHelper.Link(nameof(AuthorsController.GetAuthors), new { }), "authors", "GET"), new Link(_urlHelper.Link(nameof(AuthorsController.CreateAuthor), new { }), "create_author", "POST") }; return(Ok(links)); } return(NoContent()); }
public IActionResult CreateBookForAuthor(Guid authorId, [FromBody] CreateBook book, [FromHeader(Name = Headers.Accept)] string mediaType) { if (book == null) { return(BadRequest()); } if (book.Description == book.Title) { ModelState.AddModelError(nameof(CreateBook), "The description should differ from the title."); } if (!ModelState.IsValid) { return(UnprocessableEntity(ModelState)); } if (!_libraryRepository.AuthorExists(authorId)) { return(NotFound()); } var newBook = Mapper.Map <Entities.Book>(book); _libraryRepository.AddBookForAuthor(authorId, newBook); if (!_libraryRepository.Save()) { throw new Exception($"Couldn't save new book for Author {authorId}"); } var currentMediaType = new MediaType(mediaType); var includeLinks = currentMediaType.IsSubsetOf(VendorMediaType.HateoasLinksMediaType); var bookToReturn = Mapper.Map <Book>(newBook); if (includeLinks) { return(CreatedAtRoute(nameof(GetBookForAuthor), new { authorId, id = newBook.Id }, CreateLinks(bookToReturn))); } else { return(CreatedAtRoute(nameof(GetBookForAuthor), new { authorId, id = newBook.Id }, bookToReturn)); } }
/// <inheritdoc /> public virtual IReadOnlyList <string>?GetSupportedContentTypes(string contentType, Type objectType) { if (SupportedMediaTypes.Count == 0) { var message = Resources.FormatFormatter_NoMediaTypes( GetType().FullName, nameof(SupportedMediaTypes)); throw new InvalidOperationException(message); } if (!CanReadType(objectType)) { return(null); } if (contentType == null) { // If contentType is null, then any type we support is valid. return(SupportedMediaTypes); } else { var parsedContentType = new MediaType(contentType); List <string>?mediaTypes = null; // Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*" // requested and formatter supports "text/plain". Treat contentType like it came from an Content-Type header. foreach (var mediaType in SupportedMediaTypes) { var parsedMediaType = new MediaType(mediaType); if (parsedMediaType.IsSubsetOf(parsedContentType)) { if (mediaTypes == null) { mediaTypes = new List <string>(SupportedMediaTypes.Count); } mediaTypes.Add(mediaType); } } return(mediaTypes); } }
private static bool IsMediaTypeSupported(MediaTypeCollection mediaTypeCollection, MediaTypeCollection supportedMediaTypes) { foreach (var supportedMediaTypeString in supportedMediaTypes) { var supportedMediaType = new MediaType(supportedMediaTypeString); foreach (var mediaType in mediaTypeCollection) { var inputMediaType = new MediaType(mediaType); if (inputMediaType.IsSubsetOf(supportedMediaType)) { return(true); } } } return(false); }
public static bool HasAcceptHeader(this HttpRequest request, string mediaType) { var acceptHeader = request.Headers[HeaderNames.Accept]; if (string.IsNullOrWhiteSpace(acceptHeader)) { return(false); } var parsedRequestMediaType = new MediaType(acceptHeader); if (parsedRequestMediaType.IsSubsetOf(new MediaType(mediaType))) { return(true); } return(false); }
public virtual bool CanWriteResult(WebSocketOutputFormatterCanWriteContext context) { if (context.ObjectType == null) { throw new ArgumentNullException(nameof(context.ObjectType)); } if (SupportedMediaTypes.Count == 0) { throw new InvalidOperationException("No media types supported"); } if (!CanWriteType(context.ObjectType)) { return(false); } if (!context.ContentType.HasValue) { // If the desired content type is set to null, then the current formatter can write anything // it wants. context.ContentType = new StringSegment(SupportedMediaTypes[0]); return(true); } // Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*" // requested and formatter supports "text/plain". contentType is typically what we got in an Accept // header. var parsedContentType = new MediaType(context.ContentType.Value); for (var i = 0; i < SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(SupportedMediaTypes[i]); if (supportedMediaType.IsSubsetOf(parsedContentType)) { context.ContentType = new StringSegment(SupportedMediaTypes[i]); return(true); } } return(false); }
private static bool InAcceptableMediaTypes(StringSegment mediaType, MediaTypeCollection acceptableMediaTypes) { if (acceptableMediaTypes.Count == 0) { return(true); } var parsedMediaType = new MediaType(mediaType); for (int i = 0; i < acceptableMediaTypes.Count; i++) { var acceptableMediaType = new MediaType(acceptableMediaTypes[i]); if (acceptableMediaType.IsSubsetOf(parsedMediaType)) { return(true); } } return(false); }
public IDeserializer GetDeserializer(string mediaType) { if (mediaType == null) { throw new ArgumentNullException(nameof(mediaType)); } var inputMediaType = new MediaType(mediaType); foreach (var deserializer in Deserializers) { foreach (var supportedMediaTypeString in deserializer.SupportedMediaTypes) { var supportedMediaType = new MediaType(supportedMediaTypeString); if (inputMediaType.IsSubsetOf(supportedMediaType)) { return(deserializer); } } } return(null); }
/// <inheritdoc /> public override async Task ExecuteResultAsync(ActionContext context) { var response = context.HttpContext.Response; // Sets the HTTP status code await base.ExecuteResultAsync(context).ConfigureAwait(false); // Sets the reason phrase var responseFeature = context.HttpContext.Features.Get <IHttpResponseFeature>(); if (responseFeature != null) { responseFeature.ReasonPhrase = _result.StatusCode.GetReasonPhrase(); } if (_logger?.IsEnabled(LogLevel.Debug) ?? false) { var loggingResponse = new LoggingWebDavResponse(_dispatcher); await _result.ExecuteResultAsync(loggingResponse, context.HttpContext.RequestAborted).ConfigureAwait(false); if (!string.IsNullOrEmpty(loggingResponse.ContentType)) { var mediaType = new MediaType(loggingResponse.ContentType); if (_supportedMediaTypes.Any(x => mediaType.IsSubsetOf(x))) { var doc = loggingResponse.Load(); if (doc != null) { _logger.LogDebug(doc.ToString(SaveOptions.OmitDuplicateNamespaces)); } } } } // Writes the XML response await _result.ExecuteResultAsync(new WebDavResponse(_dispatcher, response), context.HttpContext.RequestAborted).ConfigureAwait(false); }
private bool OutputFormatterSupportsMediaType(OutputFormatter outputForamtter, OutputFormatterCanWriteContext context) { var parsedContentType = new MediaType(context.ContentType); for (var i = 0; i < outputForamtter.SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(outputForamtter.SupportedMediaTypes[i]); if (supportedMediaType.HasWildcard) { // For supported media types that are wildcard patterns, confirm that the requested // media type satisfies the wildcard pattern (e.g., if "text/entity+json;v=2" requested // and formatter supports "text/*+json"). // We only do this when comparing against server-defined content types (e.g., those // from [Produces] or Response.ContentType), otherwise we'd potentially be reflecting // back arbitrary Accept header values. if (context.ContentTypeIsServerDefined && parsedContentType.IsSubsetOf(supportedMediaType)) { return(true); } } else { // For supported media types that are not wildcard patterns, confirm that this formatter // supports a more specific media type than requested e.g. OK if "text/*" requested and // formatter supports "text/plain". // contentType is typically what we got in an Accept header. if (supportedMediaType.IsSubsetOf(parsedContentType)) { context.ContentType = new StringSegment(outputForamtter.SupportedMediaTypes[i]); return(true); } } } return(false); }
/// <summary> /// 能否使用当前格式输出 /// </summary> /// <param name="context"></param> /// <returns></returns> public override bool CanWriteResult(OutputFormatterCanWriteContext context) { Assert.NotNull(context, nameof(context)); if (!context.ContentType.HasValue) { return(false); } var parsedContentType = new MediaType(context.ContentType); for (var i = 0; i < SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(SupportedMediaTypes[i]); if (supportedMediaType.IsSubsetOf(parsedContentType) && context.ObjectType.GetCustomAttribute(typeof(ProtoContractAttribute) ) != null ) { context.ContentType = new StringSegment(SupportedMediaTypes[i]); return(true); } } return(false); }
public IReadOnlyList <PolicyNodeEdge> GetEdges(IReadOnlyList <Endpoint> endpoints) { if (endpoints == null) { throw new ArgumentNullException(nameof(endpoints)); } // The algorithm here is designed to be preserve the order of the endpoints // while also being relatively simple. Preserving order is important. // First, build a dictionary of all of the content-type patterns that are included // at this node. // // For now we're just building up the set of keys. We don't add any endpoints // to lists now because we don't want ordering problems. var edges = new Dictionary <string, List <Endpoint> >(StringComparer.OrdinalIgnoreCase); for (var i = 0; i < endpoints.Count; i++) { var endpoint = endpoints[i]; var contentTypes = endpoint.Metadata.GetMetadata <IConsumesMetadata>()?.ContentTypes; if (contentTypes == null || contentTypes.Count == 0) { contentTypes = new string[] { AnyContentType, }; } for (var j = 0; j < contentTypes.Count; j++) { var contentType = contentTypes[j]; if (!edges.ContainsKey(contentType)) { edges.Add(contentType, new List <Endpoint>()); } } } // Now in a second loop, add endpoints to these lists. We've enumerated all of // the states, so we want to see which states this endpoint matches. for (var i = 0; i < endpoints.Count; i++) { var endpoint = endpoints[i]; var contentTypes = endpoint.Metadata.GetMetadata <IConsumesMetadata>()?.ContentTypes ?? Array.Empty <string>(); if (contentTypes.Count == 0) { // OK this means that this endpoint matches *all* content methods. // So, loop and add it to all states. foreach (var kvp in edges) { kvp.Value.Add(endpoint); } } else { // OK this endpoint matches specific content types -- we have to loop through edges here // because content types could either be exact (like 'application/json') or they // could have wildcards (like 'text/*'). We don't expect wildcards to be especially common // with consumes, but we need to support it. foreach (var kvp in edges) { // The edgeKey maps to a possible request header value var edgeKey = new MediaType(kvp.Key); for (var j = 0; j < contentTypes.Count; j++) { var contentType = contentTypes[j]; var mediaType = new MediaType(contentType); // Example: 'application/json' is subset of 'application/*' // // This means that when the request has content-type 'application/json' an endpoint // what consumes 'application/*' should match. if (edgeKey.IsSubsetOf(mediaType)) { kvp.Value.Add(endpoint); // It's possible that a ConsumesMetadata defines overlapping wildcards. Don't add an endpoint // to any edge twice break; } } } } } // If after we're done there isn't any endpoint that accepts */*, then we'll synthesize an // endpoint that always returns a 415. if (!edges.TryGetValue(AnyContentType, out var anyEndpoints)) { edges.Add(AnyContentType, new List <Endpoint>() { CreateRejectionEndpoint(), }); // Add a node to use when there is no request content type. // When there is no content type we want the policy to no-op edges.Add(string.Empty, endpoints.ToList()); } else { // If there is an endpoint that accepts */* then it is also used when there is no content type edges.Add(string.Empty, anyEndpoints.ToList()); } return(edges .Select(kvp => new PolicyNodeEdge(kvp.Key, kvp.Value)) .ToArray()); }
private static bool InAcceptableMediaTypes(StringSegment mediaType, MediaTypeCollection acceptableMediaTypes) { if (acceptableMediaTypes.Count == 0) { return true; } var parsedMediaType = new MediaType(mediaType); for (int i = 0; i < acceptableMediaTypes.Count; i++) { var acceptableMediaType = new MediaType(acceptableMediaTypes[i]); if (acceptableMediaType.IsSubsetOf(parsedMediaType)) { return true; } } return false; }
/// <summary> /// Selects the <see cref="IOutputFormatter"/> to write the response based on the content type values /// present in <paramref name="sortedAcceptableContentTypes"/> and <paramref name="possibleOutputContentTypes"/>. /// </summary> /// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param> /// <param name="formatters"> /// The list of <see cref="IOutputFormatter"/> instances to consider. /// </param> /// <param name="sortedAcceptableContentTypes"> /// The ordered content types from the <c>Accept</c> header, sorted by descending q-value. /// </param> /// <param name="possibleOutputContentTypes"> /// The ordered content types from <see cref="ObjectResult.ContentTypes"/> in descending priority order. /// </param> /// <returns> /// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response. /// </returns> protected virtual IOutputFormatter SelectFormatterUsingSortedAcceptHeadersAndContentTypes( OutputFormatterWriteContext formatterContext, IList<IOutputFormatter> formatters, IList<MediaTypeSegmentWithQuality> sortedAcceptableContentTypes, MediaTypeCollection possibleOutputContentTypes) { for (var i = 0; i < sortedAcceptableContentTypes.Count; i++) { var acceptableContentType = new MediaType(sortedAcceptableContentTypes[i].MediaType); for (var j = 0; j < possibleOutputContentTypes.Count; j++) { var candidateContentType = new MediaType(possibleOutputContentTypes[j]); if (candidateContentType.IsSubsetOf(acceptableContentType)) { for (var k = 0; k < formatters.Count; k++) { var formatter = formatters[k]; formatterContext.ContentType = new StringSegment(possibleOutputContentTypes[j]); if (formatter.CanWriteResult(formatterContext)) { return formatter; } } } } } return null; }
private bool IsSubsetOfAnyContentType(string requestMediaType) { var parsedRequestMediaType = new MediaType(requestMediaType); for (var i = 0; i < ContentTypes.Count; i++) { var contentTypeMediaType = new MediaType(ContentTypes[i]); if (parsedRequestMediaType.IsSubsetOf(contentTypeMediaType)) { return true; } } return false; }
private bool IsSuperSetOfAnySupportedMediaType(string contentType, MediaTypeCollection supportedMediaTypes) { var parsedContentType = new MediaType(contentType); for (var i = 0; i < supportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(supportedMediaTypes[i]); if (supportedMediaType.IsSubsetOf(parsedContentType)) { return true; } } return false; }
public void IsSubsetOf(string set, string subset, bool expectedResult) { // Arrange var setMediaType = new MediaType(set); var subSetMediaType = new MediaType(subset); // Act var result = subSetMediaType.IsSubsetOf(setMediaType); // Assert Assert.Equal(expectedResult, result); }
private async Task ExecuteAsync(HttpContext context, ISchemaFactory schemaService) { var schema = await schemaService.GetSchema(); AbpGraphQLRequest request = null; if (HttpMethods.IsPost(context.Request.Method)) { var mediaType = new MediaType(context.Request.ContentType); try { if (mediaType.IsSubsetOf(JsonMediaType)) { using (var sr = new StreamReader(context.Request.Body)) { using (var jsonTextReader = new JsonTextReader(sr)) { request = Serializer.Deserialize <AbpGraphQLRequest>(jsonTextReader); } } } else if (mediaType.IsSubsetOf(GraphQLMediaType)) { request = new AbpGraphQLRequest(); using (var sr = new StreamReader(context.Request.Body)) { request.Query = await sr.ReadToEndAsync(); } } else if (context.Request.Query.ContainsKey("query")) { request = new AbpGraphQLRequest { Query = context.Request.Query["query"] }; if (context.Request.Query.ContainsKey("variables")) { request.Variables = JObject.Parse(context.Request.Query["variables"]); } if (context.Request.Query.ContainsKey("operationName")) { request.OperationName = context.Request.Query["operationName"]; } } } catch (Exception e) { await WriteErrorAsync(context, "An error occured while processing the GraphQL query", e); return; } } else if (HttpMethods.IsGet(context.Request.Method)) { if (!context.Request.Query.ContainsKey("query")) { await WriteErrorAsync(context, "The 'query' query string parameter is missing"); return; } request = new AbpGraphQLRequest { Query = context.Request.Query["query"] }; } var queryToExecute = request.Query; if (!string.IsNullOrEmpty(request.NamedQuery)) { var namedQueries = context.RequestServices.GetServices <INamedQueryProvider>(); var queries = namedQueries .SelectMany(dict => dict.Resolve()) .ToDictionary(pair => pair.Key, pair => pair.Value); queryToExecute = queries[request.NamedQuery]; } var result = await _executor.ExecuteAsync(_ => { _.Schema = schema; _.Query = queryToExecute; _.OperationName = request.OperationName; _.Inputs = request.Variables.ToInputs(); _.UserContext = _options.BuildUserContext?.Invoke(context); #if DEBUG _.ExposeExceptions = true; #endif }); var httpResult = result.Errors?.Count > 0 ? HttpStatusCode.BadRequest : HttpStatusCode.OK; context.Response.StatusCode = (int)httpResult; context.Response.ContentType = "application/json"; await _writer.WriteAsync(context.Response.Body, result); }
/// <inheritdoc /> public virtual IReadOnlyList<string> GetSupportedContentTypes( string contentType, Type objectType) { if (SupportedMediaTypes.Count == 0) { var message = Resources.FormatFormatter_NoMediaTypes( GetType().FullName, nameof(SupportedMediaTypes)); throw new InvalidOperationException(message); } if (!CanWriteType(objectType)) { return null; } if (contentType == null) { // If contentType is null, then any type we support is valid. return SupportedMediaTypes; } else { List<string> mediaTypes = null; var parsedContentType = new MediaType(contentType); // Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*" // requested and formatter supports "text/plain". Treat contentType like it came from an Accept header. foreach (var mediaType in SupportedMediaTypes) { var parsedMediaType = new MediaType(mediaType); if (parsedMediaType.IsSubsetOf(parsedContentType)) { if (mediaTypes == null) { mediaTypes = new List<string>(); } mediaTypes.Add(mediaType); } } return mediaTypes; } }
/// <inheritdoc /> public virtual bool CanWriteResult(OutputFormatterCanWriteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (SupportedMediaTypes.Count == 0) { var message = Resources.FormatFormatter_NoMediaTypes( GetType().FullName, nameof(SupportedMediaTypes)); throw new InvalidOperationException(message); } if (!CanWriteType(context.ObjectType)) { return(false); } if (!context.ContentType.HasValue) { // If the desired content type is set to null, then the current formatter can write anything // it wants. context.ContentType = new StringSegment(SupportedMediaTypes[0]); return(true); } else { var parsedContentType = new MediaType(context.ContentType); for (var i = 0; i < SupportedMediaTypes.Count; i++) { var supportedMediaType = new MediaType(SupportedMediaTypes[i]); if (supportedMediaType.HasWildcard) { // For supported media types that are wildcard patterns, confirm that the requested // media type satisfies the wildcard pattern (e.g., if "text/entity+json;v=2" requested // and formatter supports "text/*+json"). // We only do this when comparing against server-defined content types (e.g., those // from [Produces] or Response.ContentType), otherwise we'd potentially be reflecting // back arbitrary Accept header values. if (context.ContentTypeIsServerDefined && parsedContentType.IsSubsetOf(supportedMediaType)) { return(true); } } else { // For supported media types that are not wildcard patterns, confirm that this formatter // supports a more specific media type than requested e.g. OK if "text/*" requested and // formatter supports "text/plain". // contentType is typically what we got in an Accept header. if (supportedMediaType.IsSubsetOf(parsedContentType)) { context.ContentType = new StringSegment(SupportedMediaTypes[i]); return(true); } } } } return(false); }
private async Task ExecuteAsync(HttpContext context, ISchemaFactory schemaService) { var schema = await schemaService.GetSchemaAsync(); GraphQLRequest request = null; // c.f. https://graphql.org/learn/serving-over-http/#post-request if (HttpMethods.IsPost(context.Request.Method)) { var mediaType = new MediaType(context.Request.ContentType); try { if (mediaType.IsSubsetOf(_jsonMediaType)) { using (var sr = new StreamReader(context.Request.Body)) { // Asynchronous read is mandatory. var json = await sr.ReadToEndAsync(); request = JObject.Parse(json).ToObject <GraphQLRequest>(); } } else if (mediaType.IsSubsetOf(_graphQlMediaType)) { request = new GraphQLRequest(); using (var sr = new StreamReader(context.Request.Body)) { request.Query = await sr.ReadToEndAsync(); } } else if (context.Request.Query.ContainsKey("query")) { request = new GraphQLRequest { Query = context.Request.Query["query"] }; if (context.Request.Query.ContainsKey("variables")) { request.Variables = JObject.Parse(context.Request.Query["variables"]); } if (context.Request.Query.ContainsKey("operationName")) { request.OperationName = context.Request.Query["operationName"]; } } } catch (Exception e) { await WriteErrorAsync(context, "An error occurred while processing the GraphQL query", e); return; } } else if (HttpMethods.IsGet(context.Request.Method)) { if (!context.Request.Query.ContainsKey("query")) { await WriteErrorAsync(context, "The 'query' query string parameter is missing"); return; } request = new GraphQLRequest { Query = context.Request.Query["query"] }; } var queryToExecute = request.Query; if (!String.IsNullOrEmpty(request.NamedQuery)) { var namedQueries = context.RequestServices.GetServices <INamedQueryProvider>(); var queries = namedQueries .SelectMany(dict => dict.Resolve()) .ToDictionary(pair => pair.Key, pair => pair.Value); queryToExecute = queries[request.NamedQuery]; } var dataLoaderDocumentListener = context.RequestServices.GetRequiredService <IDocumentExecutionListener>(); var result = await _executer.ExecuteAsync(_ => { _.Schema = schema; _.Query = queryToExecute; _.OperationName = request.OperationName; _.Inputs = request.Variables.ToInputs(); _.UserContext = _settings.BuildUserContext?.Invoke(context); _.ExposeExceptions = _settings.ExposeExceptions; _.ValidationRules = DocumentValidator.CoreRules() .Concat(context.RequestServices.GetServices <IValidationRule>()); _.ComplexityConfiguration = new ComplexityConfiguration { MaxDepth = _settings.MaxDepth, MaxComplexity = _settings.MaxComplexity, FieldImpact = _settings.FieldImpact }; _.Listeners.Add(dataLoaderDocumentListener); }); context.Response.StatusCode = (int)(result.Errors == null || result.Errors.Count == 0 ? HttpStatusCode.OK : result.Errors.Any(x => x.Code == RequiresPermissionValidationRule.ErrorCode) ? HttpStatusCode.Unauthorized : HttpStatusCode.BadRequest); context.Response.ContentType = "application/json"; // Asynchronous write to the response body is mandatory. var encodedBytes = _utf8Encoding.GetBytes(JObject.FromObject(result).ToString()); await context.Response.Body.WriteAsync(encodedBytes, 0, encodedBytes.Length); }