Skip to content

Commit b1cb364

Browse files
committed
Update GraphQlRequestPredicates to map application/graphql content
Closes gh-948
1 parent 03c11d0 commit b1cb364

File tree

4 files changed

+72
-34
lines changed

4 files changed

+72
-34
lines changed

spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlRequestPredicates.java

+26-17
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.graphql.server.webflux;
1818

19-
import java.util.Arrays;
2019
import java.util.Collections;
2120
import java.util.List;
2221

@@ -40,6 +39,7 @@
4039
* {@link RequestPredicate} implementations tailored for GraphQL reactive endpoints.
4140
*
4241
* @author Brian Clozel
42+
* @author Rossen Stoyanchev
4343
* @since 1.3.0
4444
*/
4545
public final class GraphQlRequestPredicates {
@@ -56,7 +56,8 @@ private GraphQlRequestPredicates() {
5656
* @see GraphQlHttpHandler
5757
*/
5858
public static RequestPredicate graphQlHttp(String path) {
59-
return new GraphQlHttpRequestPredicate(path, MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL_RESPONSE);
59+
return new GraphQlHttpRequestPredicate(
60+
path, List.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL_RESPONSE));
6061
}
6162

6263
/**
@@ -65,59 +66,67 @@ public static RequestPredicate graphQlHttp(String path) {
6566
* @see GraphQlSseHandler
6667
*/
6768
public static RequestPredicate graphQlSse(String path) {
68-
return new GraphQlHttpRequestPredicate(path, MediaType.TEXT_EVENT_STREAM);
69+
return new GraphQlHttpRequestPredicate(path, List.of(MediaType.TEXT_EVENT_STREAM));
6970
}
7071

7172
private static class GraphQlHttpRequestPredicate implements RequestPredicate {
7273

7374
private final PathPattern pattern;
7475

76+
private final List<MediaType> contentTypes;
77+
7578
private final List<MediaType> acceptedMediaTypes;
7679

7780

78-
GraphQlHttpRequestPredicate(String path, MediaType... accepted) {
81+
GraphQlHttpRequestPredicate(String path, List<MediaType> accepted) {
7982
Assert.notNull(path, "'path' must not be null");
8083
Assert.notEmpty(accepted, "'accepted' must not be empty");
8184
PathPatternParser parser = PathPatternParser.defaultInstance;
8285
path = parser.initFullPathPattern(path);
8386
this.pattern = parser.parse(path);
84-
this.acceptedMediaTypes = Arrays.asList(accepted);
87+
this.contentTypes = List.of(MediaType.APPLICATION_JSON, MediaType.parseMediaType("application/graphql"));
88+
this.acceptedMediaTypes = accepted;
8589
}
8690

8791
@Override
8892
public boolean test(ServerRequest request) {
89-
return methodMatch(request, HttpMethod.POST)
90-
&& contentTypeMatch(request, MediaType.APPLICATION_JSON)
93+
return httpMethodMatch(request, HttpMethod.POST)
94+
&& contentTypeMatch(request, this.contentTypes)
9195
&& acceptMatch(request, this.acceptedMediaTypes)
9296
&& pathMatch(request, this.pattern);
9397
}
9498

95-
private static boolean methodMatch(ServerRequest request, HttpMethod expected) {
96-
HttpMethod actual = resolveMethod(request);
99+
private static boolean httpMethodMatch(ServerRequest request, HttpMethod expected) {
100+
HttpMethod actual = resolveHttpMethod(request);
97101
boolean methodMatch = expected.equals(actual);
98102
traceMatch("Method", expected, actual, methodMatch);
99103
return methodMatch;
100104
}
101105

102-
private static HttpMethod resolveMethod(ServerRequest request) {
106+
private static HttpMethod resolveHttpMethod(ServerRequest request) {
103107
if (CorsUtils.isPreFlightRequest(request.exchange().getRequest())) {
104-
String accessControlRequestMethod =
105-
request.headers().firstHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
106-
if (accessControlRequestMethod != null) {
107-
return HttpMethod.valueOf(accessControlRequestMethod);
108+
String httpMethod = request.headers().firstHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
109+
if (httpMethod != null) {
110+
return HttpMethod.valueOf(httpMethod);
108111
}
109112
}
110113
return request.method();
111114
}
112115

113-
private static boolean contentTypeMatch(ServerRequest request, MediaType expected) {
116+
private static boolean contentTypeMatch(ServerRequest request, List<MediaType> contentTypes) {
114117
if (CorsUtils.isPreFlightRequest(request.exchange().getRequest())) {
115118
return true;
116119
}
117120
ServerRequest.Headers headers = request.headers();
118121
MediaType actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
119-
boolean contentTypeMatch = expected.includes(actual);
120-
traceMatch("Content-Type", expected, actual, contentTypeMatch);
122+
boolean contentTypeMatch = false;
123+
for (MediaType contentType : contentTypes) {
124+
contentTypeMatch = contentType.includes(actual);
125+
traceMatch("Content-Type", contentTypes, actual, contentTypeMatch);
126+
if (contentTypeMatch) {
127+
break;
128+
}
129+
}
121130
return contentTypeMatch;
122131
}
123132

spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlRequestPredicates.java

+26-17
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.graphql.server.webmvc;
1818

19-
import java.util.Arrays;
2019
import java.util.Collections;
2120
import java.util.List;
2221

@@ -40,6 +39,7 @@
4039
* {@link RequestPredicate} implementations tailored for GraphQL endpoints.
4140
*
4241
* @author Brian Clozel
42+
* @author Rossen Stoyanchev
4343
* @since 1.3.0
4444
*/
4545
public final class GraphQlRequestPredicates {
@@ -56,7 +56,8 @@ private GraphQlRequestPredicates() {
5656
* @see GraphQlHttpHandler
5757
*/
5858
public static RequestPredicate graphQlHttp(String path) {
59-
return new GraphQlHttpRequestPredicate(path, MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL_RESPONSE);
59+
return new GraphQlHttpRequestPredicate(
60+
path, List.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL_RESPONSE));
6061
}
6162

6263
/**
@@ -65,59 +66,67 @@ public static RequestPredicate graphQlHttp(String path) {
6566
* @see GraphQlSseHandler
6667
*/
6768
public static RequestPredicate graphQlSse(String path) {
68-
return new GraphQlHttpRequestPredicate(path, MediaType.TEXT_EVENT_STREAM);
69+
return new GraphQlHttpRequestPredicate(path, List.of(MediaType.TEXT_EVENT_STREAM));
6970
}
7071

7172
private static class GraphQlHttpRequestPredicate implements RequestPredicate {
7273

7374
private final PathPattern pattern;
7475

76+
private final List<MediaType> contentTypes;
77+
7578
private final List<MediaType> acceptedMediaTypes;
7679

7780

78-
GraphQlHttpRequestPredicate(String path, MediaType... accepted) {
81+
GraphQlHttpRequestPredicate(String path, List<MediaType> accepted) {
7982
Assert.notNull(path, "'path' must not be null");
8083
Assert.notEmpty(accepted, "'accepted' must not be empty");
8184
PathPatternParser parser = PathPatternParser.defaultInstance;
8285
path = parser.initFullPathPattern(path);
8386
this.pattern = parser.parse(path);
84-
this.acceptedMediaTypes = Arrays.asList(accepted);
87+
this.contentTypes = List.of(MediaType.APPLICATION_JSON, MediaType.parseMediaType("application/graphql"));
88+
this.acceptedMediaTypes = accepted;
8589
}
8690

8791
@Override
8892
public boolean test(ServerRequest request) {
89-
return methodMatch(request, HttpMethod.POST)
90-
&& contentTypeMatch(request, MediaType.APPLICATION_JSON)
93+
return httpMethodMatch(request, HttpMethod.POST)
94+
&& contentTypeMatch(request, this.contentTypes)
9195
&& acceptMatch(request, this.acceptedMediaTypes)
9296
&& pathMatch(request, this.pattern);
9397
}
9498

95-
private static boolean methodMatch(ServerRequest request, HttpMethod expected) {
96-
HttpMethod actual = resolveMethod(request);
99+
private static boolean httpMethodMatch(ServerRequest request, HttpMethod expected) {
100+
HttpMethod actual = resolveHttpMethod(request);
97101
boolean methodMatch = expected.equals(actual);
98102
traceMatch("Method", expected, actual, methodMatch);
99103
return methodMatch;
100104
}
101105

102-
private static HttpMethod resolveMethod(ServerRequest request) {
106+
private static HttpMethod resolveHttpMethod(ServerRequest request) {
103107
if (CorsUtils.isPreFlightRequest(request.servletRequest())) {
104-
String accessControlRequestMethod =
105-
request.headers().firstHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
106-
if (accessControlRequestMethod != null) {
107-
return HttpMethod.valueOf(accessControlRequestMethod);
108+
String httpMethod = request.headers().firstHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
109+
if (httpMethod != null) {
110+
return HttpMethod.valueOf(httpMethod);
108111
}
109112
}
110113
return request.method();
111114
}
112115

113-
private static boolean contentTypeMatch(ServerRequest request, MediaType expected) {
116+
private static boolean contentTypeMatch(ServerRequest request, List<MediaType> contentTypes) {
114117
if (CorsUtils.isPreFlightRequest(request.servletRequest())) {
115118
return true;
116119
}
117120
ServerRequest.Headers headers = request.headers();
118121
MediaType actual = headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
119-
boolean contentTypeMatch = expected.includes(actual);
120-
traceMatch("Content-Type", expected, actual, contentTypeMatch);
122+
boolean contentTypeMatch = false;
123+
for (MediaType contentType : contentTypes) {
124+
contentTypeMatch = contentType.includes(actual);
125+
traceMatch("Content-Type", contentTypes, actual, contentTypeMatch);
126+
if (contentTypeMatch) {
127+
break;
128+
}
129+
}
121130
return contentTypeMatch;
122131
}
123132

spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphQlRequestPredicatesTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ void shouldRejectRequestWithDifferentPath() {
7777
assertThat(httpPredicate.test(serverRequest)).isFalse();
7878
}
7979

80+
@Test
81+
void shouldMapApplicationGraphQlRequestContent() {
82+
ServerWebExchange exchange = createMatchingHttpExchange()
83+
.mutate().request(builder -> builder.headers(headers -> {
84+
MediaType contentType = MediaType.parseMediaType("application/graphql");
85+
headers.setContentType(contentType);
86+
}))
87+
.build();
88+
ServerRequest serverRequest = ServerRequest.create(exchange, Collections.emptyList());
89+
assertThat(httpPredicate.test(serverRequest)).isTrue();
90+
}
91+
8092
@Test
8193
void shouldRejectRequestWithDifferentContentType() {
8294
ServerWebExchange exchange = createMatchingHttpExchange()

spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlRequestPredicatesTests.java

+8
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ void shouldRejectRequestWithDifferentPath() {
7474
assertThat(httpPredicate.test(serverRequest)).isFalse();
7575
}
7676

77+
@Test
78+
void shouldMapApplicationGraphQlRequestContent() {
79+
MockHttpServletRequest request = createMatchingHttpRequest();
80+
request.setContentType("application/graphql");
81+
ServerRequest serverRequest = ServerRequest.create(request, Collections.emptyList());
82+
assertThat(httpPredicate.test(serverRequest)).isTrue();
83+
}
84+
7785
@Test
7886
void shouldRejectRequestWithDifferentContentType() {
7987
MockHttpServletRequest request = createMatchingHttpRequest();

0 commit comments

Comments
 (0)