Polishing in GraphQlHttpHandler
This commit is contained in:
@@ -76,14 +76,15 @@ public abstract class AbstractGraphQlHttpHandler {
|
||||
return readRequest(request)
|
||||
.flatMap((body) -> {
|
||||
WebGraphQlRequest graphQlRequest = new WebGraphQlRequest(
|
||||
request.uri(), request.headers().asHttpHeaders(),
|
||||
request.cookies(), request.remoteAddress().orElse(null),
|
||||
request.attributes(), body,
|
||||
request.uri(), request.headers().asHttpHeaders(), request.cookies(),
|
||||
request.remoteAddress().orElse(null), request.attributes(), body,
|
||||
request.exchange().getRequest().getId(),
|
||||
request.exchange().getLocaleContext().getLocale());
|
||||
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Executing: " + graphQlRequest);
|
||||
}
|
||||
|
||||
return this.graphQlHandler.handleRequest(graphQlRequest);
|
||||
})
|
||||
.flatMap((response) -> {
|
||||
@@ -92,6 +93,7 @@ public abstract class AbstractGraphQlHttpHandler {
|
||||
this.logger.debug("Execution result " +
|
||||
(!CollectionUtils.isEmpty(errors) ? "has errors: " + errors : "is ready") + ".");
|
||||
}
|
||||
|
||||
return prepareResponse(request, response);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,9 +18,12 @@ package org.springframework.graphql.server.webmvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -36,7 +39,9 @@ import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AlternativeJdkIdGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -46,6 +51,7 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.function.ServerRequest;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
@@ -79,11 +85,19 @@ public abstract class AbstractGraphQlHttpHandler {
|
||||
|
||||
|
||||
/**
|
||||
* Return the custom message converter, if configured, to read and write with.
|
||||
* Exposes a {@link ServerResponse.HeadersBuilder.WriteFunction} that writes
|
||||
* with the {@code HttpMessageConverter} provided to the constructor.
|
||||
* @param resultMap the result map to write
|
||||
* @param contentType to set the response content type to
|
||||
* @return the write function, or {@code null} if a
|
||||
* {@code HttpMessageConverter} was not provided to the constructor
|
||||
*/
|
||||
@Nullable
|
||||
public HttpMessageConverter<Object> getMessageConverter() {
|
||||
return this.messageConverter;
|
||||
protected ServerResponse.HeadersBuilder.WriteFunction getWriteFunction(
|
||||
Map<String, Object> resultMap, MediaType contentType) {
|
||||
|
||||
return (this.messageConverter != null) ?
|
||||
new MessageConverterWriteFunction(resultMap, contentType, this.messageConverter) : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,8 +147,8 @@ public abstract class AbstractGraphQlHttpHandler {
|
||||
if (this.messageConverter != null) {
|
||||
MediaType contentType = request.headers().contentType().orElse(MediaType.APPLICATION_JSON);
|
||||
if (this.messageConverter.canRead(SerializableGraphQlRequest.class, contentType)) {
|
||||
return (GraphQlRequest) this.messageConverter.read(SerializableGraphQlRequest.class,
|
||||
new ServletServerHttpRequest(request.servletRequest()));
|
||||
ServerHttpRequest httpRequest = new ServletServerHttpRequest(request.servletRequest());
|
||||
return (GraphQlRequest) this.messageConverter.read(SerializableGraphQlRequest.class, httpRequest);
|
||||
}
|
||||
throw new HttpMediaTypeNotSupportedException(
|
||||
contentType, this.messageConverter.getSupportedMediaTypes(), request.method());
|
||||
@@ -181,4 +195,20 @@ public abstract class AbstractGraphQlHttpHandler {
|
||||
protected abstract ServerResponse prepareResponse(
|
||||
ServerRequest request, Mono<WebGraphQlResponse> responseMono) throws ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* WriteFunction that writes with a given, fixed {@link HttpMessageConverter}.
|
||||
*/
|
||||
private record MessageConverterWriteFunction(
|
||||
Map<String, Object> resultMap, MediaType contentType, HttpMessageConverter<Object> converter)
|
||||
implements ServerResponse.HeadersBuilder.WriteFunction {
|
||||
|
||||
@Override
|
||||
public ModelAndView write(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||
this.converter.write(this.resultMap, this.contentType, httpResponse);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.springframework.graphql.server.WebGraphQlHandler;
|
||||
import org.springframework.graphql.server.WebGraphQlResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.function.ServerRequest;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
@@ -56,12 +55,12 @@ public class GraphQlHttpHandler extends AbstractGraphQlHttpHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with a custom message converter.
|
||||
* <p>If no converter is provided, this will use
|
||||
* Create a new instance with a custom message converter for GraphQL payloads.
|
||||
* <p>If no converter is provided, the handler will use
|
||||
* {@link org.springframework.web.servlet.config.annotation.WebMvcConfigurer#configureMessageConverters(List)
|
||||
* the one configured in the web framework}.
|
||||
* the one configured for web use}.
|
||||
* @param graphQlHandler common handler for GraphQL over HTTP requests
|
||||
* @param converter custom {@link HttpMessageConverter} to read and write GraphQL payloads
|
||||
* @param converter the converter to use to read and write GraphQL payloads
|
||||
*/
|
||||
public GraphQlHttpHandler(WebGraphQlHandler graphQlHandler, @Nullable HttpMessageConverter<?> converter) {
|
||||
super(graphQlHandler, converter);
|
||||
@@ -77,15 +76,12 @@ public class GraphQlHttpHandler extends AbstractGraphQlHttpHandler {
|
||||
builder.headers((headers) -> headers.putAll(response.getResponseHeaders()));
|
||||
builder.contentType(contentType);
|
||||
|
||||
if (getMessageConverter() != null) {
|
||||
return builder.build(writeFunction(getMessageConverter(), contentType, response.toMap()));
|
||||
}
|
||||
else {
|
||||
return builder.body(response.toMap());
|
||||
}
|
||||
Map<String, Object> resultMap = response.toMap();
|
||||
ServerResponse.HeadersBuilder.WriteFunction writer = getWriteFunction(resultMap, contentType);
|
||||
return (writer != null) ? builder.build(writer) : builder.body(resultMap);
|
||||
}).toFuture();
|
||||
|
||||
// This won't be needed with a Spring Framework 6.2 baseline:
|
||||
// This won't be needed on a Spring Framework 6.2 baseline:
|
||||
// https://github.com/spring-projects/spring-framework/issues/32223
|
||||
|
||||
if (future.isDone() && !future.isCancelled() && !future.isCompletedExceptionally()) {
|
||||
@@ -100,23 +96,13 @@ public class GraphQlHttpHandler extends AbstractGraphQlHttpHandler {
|
||||
return ServerResponse.async(future);
|
||||
}
|
||||
|
||||
private static MediaType selectResponseMediaType(ServerRequest serverRequest) {
|
||||
for (MediaType accepted : serverRequest.headers().accept()) {
|
||||
if (SUPPORTED_MEDIA_TYPES.contains(accepted)) {
|
||||
return accepted;
|
||||
private static MediaType selectResponseMediaType(ServerRequest request) {
|
||||
for (MediaType mediaType : request.headers().accept()) {
|
||||
if (SUPPORTED_MEDIA_TYPES.contains(mediaType)) {
|
||||
return mediaType;
|
||||
}
|
||||
}
|
||||
return MediaType.APPLICATION_JSON;
|
||||
}
|
||||
|
||||
private static ServerResponse.HeadersBuilder.WriteFunction writeFunction(
|
||||
HttpMessageConverter<Object> converter, MediaType contentType, Map<String, Object> resultMap) {
|
||||
|
||||
return (servletRequest, servletResponse) -> {
|
||||
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(servletResponse);
|
||||
converter.write(resultMap, contentType, httpResponse);
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user