Merge branch '1.3.x'

This commit is contained in:
rstoyanchev
2025-03-11 18:23:17 +00:00
14 changed files with 229 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.graphql.test.tester;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -34,6 +35,7 @@ import org.springframework.graphql.GraphQlRequest;
import org.springframework.graphql.GraphQlResponse;
import org.springframework.graphql.ResponseError;
import org.springframework.graphql.client.AbstractGraphQlClientBuilder;
import org.springframework.graphql.client.ClientGraphQlRequest;
import org.springframework.graphql.client.GraphQlClient;
import org.springframework.graphql.client.GraphQlTransport;
import org.springframework.graphql.support.DocumentSource;
@@ -167,6 +169,8 @@ public abstract class AbstractGraphQlTesterBuilder<B extends AbstractGraphQlTest
.document(request.getDocument())
.operationName(request.getOperationName())
.variables(request.getVariables())
.extensions(request.getExtensions())
.attributes((map) -> copyAttributes(map, request))
.execute()
.cast(GraphQlResponse.class);
}
@@ -177,9 +181,17 @@ public abstract class AbstractGraphQlTesterBuilder<B extends AbstractGraphQlTest
.document(request.getDocument())
.operationName(request.getOperationName())
.variables(request.getVariables())
.extensions(request.getExtensions())
.attributes((map) -> copyAttributes(map, request))
.executeSubscription()
.cast(GraphQlResponse.class);
}
private static void copyAttributes(Map<String, Object> map, GraphQlRequest request) {
if (request instanceof ClientGraphQlRequest clientGraphQlRequest) {
map.putAll(clientGraphQlRequest.getAttributes());
}
}
};
}

View File

@@ -309,12 +309,15 @@ final class DefaultGraphQlTester implements GraphQlTester {
*/
private static final class DefaultResponse implements Response, Errors {
private final GraphQlResponse response;
private final ResponseDelegate delegate;
private DefaultResponse(
GraphQlResponse response, @Nullable Predicate<ResponseError> errorFilter,
Consumer<Runnable> assertDecorator, Configuration jsonPathConfig) {
this.response = response;
this.delegate = new ResponseDelegate(response, errorFilter, assertDecorator, jsonPathConfig);
}
@@ -335,6 +338,11 @@ final class DefaultGraphQlTester implements GraphQlTester {
return this;
}
@Override
public GraphQlResponse returnResponse() {
return this.response;
}
@Override
public Errors filter(Predicate<ResponseError> predicate) {
this.delegate.filterErrors(predicate);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
import reactor.core.publisher.Flux;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.graphql.GraphQlResponse;
import org.springframework.graphql.ResponseError;
import org.springframework.graphql.client.GraphQlTransport;
import org.springframework.graphql.support.DocumentSource;
@@ -262,6 +263,13 @@ public interface GraphQlTester {
*/
Errors errors();
/**
* Return the underlying {@link GraphQlResponse} for direct access.
* @since 1.3.5
*/
GraphQlResponse returnResponse();
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import org.springframework.core.ParameterizedTypeReference;
import org.springframework.graphql.ExecutionGraphQlRequest;
import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.graphql.GraphQlRequest;
import org.springframework.graphql.GraphQlResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
@@ -500,4 +501,14 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport {
assertThat(getActualRequestDocument()).contains(document);
}
@Test
void returnGraphQlResponse() {
String document = "{me {name, friends}}";
getGraphQlService().setDataAsJson(document, "{\"me\": {\"name\":\"Luke Skywalker\", \"friends\":[]}}");
GraphQlResponse response = graphQlTester().documentName("me").execute().returnResponse();
String value = response.field("me.name").getValue();
assertThat(value).isEqualTo("Luke Skywalker");
}
}

View File

@@ -21,6 +21,7 @@ import java.util.List;
import graphql.ExecutionInput;
import graphql.GraphQLContext;
import graphql.TrivialDataFetcher;
import graphql.execution.DataFetcherResult;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.FieldCoordinates;
@@ -39,6 +40,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.graphql.ExecutionGraphQlRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -74,7 +76,6 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
}
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
@Override
public Object get(DataFetchingEnvironment env) throws Exception {
@@ -83,10 +84,33 @@ final class ContextDataFetcherDecorator implements DataFetcher<Object> {
ContextSnapshot snapshot = (env.getLocalContext() instanceof GraphQLContext localContext) ?
snapshotFactory.captureFrom(graphQlContext, localContext) :
snapshotFactory.captureFrom(graphQlContext);
Mono<Void> cancelledRequest = graphQlContext.get(ExecutionGraphQlRequest.CANCEL_PUBLISHER_CONTEXT_KEY);
Object value = snapshot.wrap(() -> this.delegate.get(env)).call();
if (value instanceof DataFetcherResult<?> dataFetcherResult) {
Object adapted = updateValue(dataFetcherResult.getData(), snapshot, cancelledRequest);
value = DataFetcherResult.newResult()
.data(adapted)
.errors(dataFetcherResult.getErrors())
.localContext(dataFetcherResult.getLocalContext()).build();
}
else {
value = updateValue(value, snapshot, cancelledRequest);
}
return value;
}
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
private @Nullable Object updateValue(
@Nullable Object value, ContextSnapshot snapshot, @Nullable Mono<Void> cancelledRequest) {
if (value == null) {
return null;
}
if (this.subscription) {
Flux<?> subscriptionResult = ReactiveAdapterRegistryHelper.toSubscriptionFlux(value)
.onErrorResume((exception) -> {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.graphql.server.support.SerializableGraphQlRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.lang.Nullable;
@@ -102,7 +103,15 @@ public abstract class AbstractGraphQlHttpHandler {
private Mono<SerializableGraphQlRequest> readRequest(ServerRequest serverRequest) {
if (this.codecDelegate != null) {
MediaType contentType = serverRequest.headers().contentType().orElse(MediaType.APPLICATION_JSON);
ServerRequest.Headers headers = serverRequest.headers();
MediaType contentType;
try {
contentType = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Could not parse " +
"Content-Type [" + headers.firstHeader(HttpHeaders.CONTENT_TYPE) + "]: " + ex.getMessage());
}
return this.codecDelegate.decode(serverRequest.bodyToFlux(DataBuffer.class), contentType);
}
else {

View File

@@ -23,11 +23,14 @@ import reactor.core.publisher.Mono;
import org.springframework.graphql.MediaTypes;
import org.springframework.graphql.server.WebGraphQlHandler;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.NotAcceptableStatusException;
/**
* WebFlux.fn Handler for GraphQL over HTTP requests.
@@ -111,7 +114,16 @@ public class GraphQlHttpHandler extends AbstractGraphQlHttpHandler {
}
private static MediaType selectResponseMediaType(ServerRequest serverRequest) {
for (MediaType accepted : serverRequest.headers().accept()) {
ServerRequest.Headers headers = serverRequest.headers();
List<MediaType> acceptedMediaTypes;
try {
acceptedMediaTypes = headers.accept();
}
catch (InvalidMediaTypeException ex) {
throw new NotAcceptableStatusException("Could not parse " +
"Accept header [" + headers.firstHeader(HttpHeaders.ACCEPT) + "]: " + ex.getMessage());
}
for (MediaType accepted : acceptedMediaTypes) {
if (SUPPORTED_MEDIA_TYPES.contains(accepted)) {
return accepted;
}

View File

@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.graphql.MediaTypes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.server.PathContainer;
import org.springframework.lang.Nullable;
@@ -34,6 +35,8 @@ import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
@@ -122,7 +125,14 @@ public final class GraphQlRequestPredicates {
return true;
}
ServerRequest.Headers headers = request.headers();
MediaType actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
MediaType actual;
try {
actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Could not parse " +
"Content-Type [" + headers.firstHeader(HttpHeaders.CONTENT_TYPE) + "]: " + ex.getMessage());
}
boolean contentTypeMatch = false;
for (MediaType contentType : contentTypes) {
contentTypeMatch = contentType.includes(actual);
@@ -139,7 +149,14 @@ public final class GraphQlRequestPredicates {
return true;
}
ServerRequest.Headers headers = request.headers();
List<MediaType> acceptedMediaTypes = acceptedMediaTypes(headers);
List<MediaType> acceptedMediaTypes;
try {
acceptedMediaTypes = acceptedMediaTypes(headers);
}
catch (InvalidMediaTypeException ex) {
throw new NotAcceptableStatusException("Could not parse " +
"Accept header [" + headers.firstHeader(HttpHeaders.ACCEPT) + "]: " + ex.getMessage());
}
boolean match = false;
outer:
for (MediaType acceptedMediaType : acceptedMediaTypes) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.graphql.server.support.SerializableGraphQlRequest;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
@@ -52,6 +53,7 @@ import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.server.ServerWebInputException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
@@ -148,7 +150,15 @@ public abstract class AbstractGraphQlHttpHandler {
private GraphQlRequest readBody(ServerRequest request) throws ServletException {
try {
if (this.messageConverter != null) {
MediaType contentType = request.headers().contentType().orElse(MediaType.APPLICATION_JSON);
ServerRequest.Headers headers = request.headers();
MediaType contentType;
try {
contentType = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Could not parse " +
"Content-Type [" + headers.firstHeader(HttpHeaders.CONTENT_TYPE) + "]: " + ex.getMessage());
}
if (this.messageConverter.canRead(SerializableGraphQlRequest.class, contentType)) {
ServerHttpRequest httpRequest = new ServletServerHttpRequest(request.servletRequest());
return (GraphQlRequest) this.messageConverter.read(SerializableGraphQlRequest.class, httpRequest);

View File

@@ -26,10 +26,13 @@ import reactor.core.publisher.Mono;
import org.springframework.graphql.MediaTypes;
import org.springframework.graphql.server.WebGraphQlHandler;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
@@ -140,7 +143,16 @@ public class GraphQlHttpHandler extends AbstractGraphQlHttpHandler {
}
private static MediaType selectResponseMediaType(ServerRequest request) {
for (MediaType mediaType : request.headers().accept()) {
ServerRequest.Headers headers = request.headers();
List<MediaType> acceptedMediaTypes;
try {
acceptedMediaTypes = headers.accept();
}
catch (InvalidMediaTypeException ex) {
throw new NotAcceptableStatusException("Could not parse " +
"Accept header [" + headers.firstHeader(HttpHeaders.ACCEPT) + "]: " + ex.getMessage());
}
for (MediaType mediaType : acceptedMediaTypes) {
if (SUPPORTED_MEDIA_TYPES.contains(mediaType)) {
return mediaType;
}

View File

@@ -25,12 +25,15 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.graphql.MediaTypes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.server.PathContainer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerRequest;
@@ -122,7 +125,14 @@ public final class GraphQlRequestPredicates {
return true;
}
ServerRequest.Headers headers = request.headers();
MediaType actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
MediaType actual;
try {
actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Could not parse " +
"Content-Type [" + headers.firstHeader(HttpHeaders.CONTENT_TYPE) + "]: " + ex.getMessage());
}
boolean contentTypeMatch = false;
for (MediaType contentType : contentTypes) {
contentTypeMatch = contentType.includes(actual);
@@ -139,7 +149,14 @@ public final class GraphQlRequestPredicates {
return true;
}
ServerRequest.Headers headers = request.headers();
List<MediaType> acceptedMediaTypes = acceptedMediaTypes(headers);
List<MediaType> acceptedMediaTypes;
try {
acceptedMediaTypes = acceptedMediaTypes(headers);
}
catch (InvalidMediaTypeException ex) {
throw new NotAcceptableStatusException("Could not parse " +
"Accept header [" + headers.firstHeader(HttpHeaders.ACCEPT) + "]: " + ex.getMessage());
}
boolean match = false;
outer:
for (MediaType acceptedMediaType : acceptedMediaTypes) {

View File

@@ -30,6 +30,7 @@ import graphql.GraphQL;
import graphql.GraphQLError;
import graphql.GraphqlErrorBuilder;
import graphql.TrivialDataFetcher;
import graphql.execution.DataFetcherResult;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetcherFactories;
import graphql.schema.FieldCoordinates;
@@ -135,6 +136,32 @@ public class ContextDataFetcherDecoratorTests {
.verifyComplete();
}
@Test
void fluxDataFetcherSubscriptionWithDataFetcherResult() throws Exception {
GraphQL graphQl = GraphQlSetup.schemaContent(SCHEMA_CONTENT)
.subscriptionFetcher("greetings", (env) -> {
Flux<String> flux = Mono.delay(Duration.ofMillis(50))
.flatMapMany((aLong) -> Flux.deferContextual((context) -> {
String name = context.get("name");
return Flux.just("Hi", "Bonjour", "Hola").map((s) -> s + " " + name);
}));
return DataFetcherResult.newResult().data(flux).build();
})
.toGraphQl();
ExecutionInput input = ExecutionInput.newExecutionInput().query("subscription { greetings }").build();
input.getGraphQLContext().put("name", "007");
ExecutionResult executionResult = graphQl.executeAsync(input).get();
Flux<String> greetingsFlux = ResponseHelper.forSubscription(executionResult)
.map(response -> response.toEntity("greetings", String.class));
StepVerifier.create(greetingsFlux)
.expectNext("Hi 007", "Bonjour 007", "Hola 007")
.verifyComplete();
}
@Test
void fluxDataFetcherSubscriptionThrowingException() throws Exception {

View File

@@ -18,6 +18,7 @@ package org.springframework.graphql.server.webflux;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -31,10 +32,13 @@ import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link GraphQlRequestPredicates}.
@@ -93,23 +97,41 @@ class GraphQlRequestPredicatesTests {
}
@Test
void shouldRejectRequestWithDifferentContentType() {
void shouldRejectRequestWithIncompatibleContentType() {
ServerWebExchange exchange = createMatchingHttpExchange()
.mutate().request(req -> req.headers(headers -> headers.setContentType(MediaType.TEXT_HTML)))
.mutate().request(request -> request.headers(h -> h.setContentType(MediaType.TEXT_HTML)))
.build();
ServerRequest serverRequest = ServerRequest.create(exchange, Collections.emptyList());
assertThat(httpPredicate.test(serverRequest)).isFalse();
}
@Test
void shouldRejectRequestWithInvalidContentType() {
ServerWebExchange exchange = createMatchingHttpExchange()
.mutate().request(request -> request.headers(h -> h.set("Content-Type", "bogus")))
.build();
ServerRequest request = ServerRequest.create(exchange, Collections.emptyList());
assertThatThrownBy(() -> httpPredicate.test(request)).isInstanceOf(UnsupportedMediaTypeStatusException.class);
}
@Test
void shouldRejectRequestWithIncompatibleAccept() {
ServerWebExchange exchange = createMatchingHttpExchange()
.mutate().request(req -> req.headers(headers -> headers.setAccept(Collections.singletonList(MediaType.TEXT_HTML))))
.mutate().request(request -> request.headers(h -> h.setAccept(List.of(MediaType.TEXT_HTML))))
.build();
ServerRequest serverRequest = ServerRequest.create(exchange, Collections.emptyList());
assertThat(httpPredicate.test(serverRequest)).isFalse();
}
@Test
void shouldRejectRequestWithInvalidAccept() {
ServerWebExchange exchange = createMatchingHttpExchange()
.mutate().request(request -> request.headers(h -> h.set("Accept", "bogus")))
.build();
ServerRequest request = ServerRequest.create(exchange, Collections.emptyList());
assertThatThrownBy(() -> httpPredicate.test(request)).isInstanceOf(NotAcceptableStatusException.class);
}
@Test
void shouldSetMatchingPatternAttribute() {
ServerWebExchange exchange = createMatchingHttpExchange();

View File

@@ -18,18 +18,22 @@ package org.springframework.graphql.server.webmvc;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link GraphQlRequestPredicates}.
@@ -85,13 +89,21 @@ class GraphQlRequestPredicatesTests {
}
@Test
void shouldRejectRequestWithDifferentContentType() {
void shouldRejectRequestWithIncompatibleContentType() {
MockHttpServletRequest request = createMatchingHttpRequest();
request.setContentType("text/xml");
ServerRequest serverRequest = ServerRequest.create(request, Collections.emptyList());
assertThat(httpPredicate.test(serverRequest)).isFalse();
}
@Test // gh-1145
void shouldRejectRequestWithInvalidContentType() {
MockHttpServletRequest servletRequest = createMatchingHttpRequest();
servletRequest.setContentType("bogus");
ServerRequest request = ServerRequest.create(servletRequest, List.of());
assertThatThrownBy(() -> httpPredicate.test(request)).isInstanceOf(UnsupportedMediaTypeStatusException.class);
}
@Test
void shouldRejectRequestWithIncompatibleAccept() {
MockHttpServletRequest request = createMatchingHttpRequest();
@@ -101,6 +113,15 @@ class GraphQlRequestPredicatesTests {
assertThat(httpPredicate.test(serverRequest)).isFalse();
}
@Test
void shouldRejectRequestWithInvalidAccept() {
MockHttpServletRequest servletRequest = createMatchingHttpRequest();
servletRequest.removeHeader("Accept");
servletRequest.addHeader("Accept", "bogus");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
assertThatThrownBy(() -> httpPredicate.test(request)).isInstanceOf(NotAcceptableStatusException.class);
}
@Test
void shouldSetMatchingPatternAttribute() {
MockHttpServletRequest request = createMatchingHttpRequest();
@@ -168,7 +189,7 @@ class GraphQlRequestPredicatesTests {
}
@Test
void shouldRejectRequestWithDifferentContentType() {
void shouldRejectRequestWithIncmopatibleContentType() {
MockHttpServletRequest request = createMatchingSseRequest();
request.setContentType("text/xml");
ServerRequest serverRequest = ServerRequest.create(request, Collections.emptyList());