Log unhandled exceptions in WebSocket handlers
Closes gh-1122
This commit is contained in:
@@ -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.
|
||||
@@ -28,6 +28,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import graphql.ExecutionResult;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.GraphqlErrorBuilder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -36,6 +38,8 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
|
||||
import org.springframework.graphql.execution.ErrorType;
|
||||
import org.springframework.graphql.execution.SubscriptionPublisherException;
|
||||
import org.springframework.graphql.server.WebGraphQlHandler;
|
||||
import org.springframework.graphql.server.WebGraphQlResponse;
|
||||
import org.springframework.graphql.server.WebSocketGraphQlInterceptor;
|
||||
@@ -256,7 +260,20 @@ public class GraphQlWebSocketHandler implements WebSocketHandler {
|
||||
CloseStatus status = new CloseStatus(4409, "Subscriber for " + id + " already exists");
|
||||
return GraphQlStatus.close(session, status);
|
||||
}
|
||||
return Mono.fromCallable(() -> this.codecDelegate.encodeError(session, id, ex));
|
||||
List<GraphQLError> errors;
|
||||
if (ex instanceof SubscriptionPublisherException subscriptionEx) {
|
||||
errors = subscriptionEx.getErrors();
|
||||
}
|
||||
else {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Unresolved " + ex.getClass().getSimpleName() + " for request id " + id, ex);
|
||||
}
|
||||
errors = Collections.singletonList(GraphqlErrorBuilder.newError()
|
||||
.message("Subscription error")
|
||||
.errorType(ErrorType.INTERNAL_ERROR)
|
||||
.build());
|
||||
}
|
||||
return Mono.fromCallable(() -> this.codecDelegate.encodeError(session, id, errors));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -16,20 +16,16 @@
|
||||
|
||||
package org.springframework.graphql.server.webflux;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import graphql.GraphQLError;
|
||||
import graphql.GraphqlErrorBuilder;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Decoder;
|
||||
import org.springframework.core.codec.Encoder;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.graphql.execution.ErrorType;
|
||||
import org.springframework.graphql.execution.SubscriptionPublisherException;
|
||||
import org.springframework.graphql.server.support.GraphQlWebSocketMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
@@ -105,13 +101,7 @@ final class WebSocketCodecDelegate {
|
||||
return encode(session, GraphQlWebSocketMessage.next(id, responseMap));
|
||||
}
|
||||
|
||||
WebSocketMessage encodeError(WebSocketSession session, String id, Throwable ex) {
|
||||
List<GraphQLError> errors = ((ex instanceof SubscriptionPublisherException) ?
|
||||
((SubscriptionPublisherException) ex).getErrors() :
|
||||
Collections.singletonList(GraphqlErrorBuilder.newError()
|
||||
.message("Subscription error")
|
||||
.errorType(ErrorType.INTERNAL_ERROR)
|
||||
.build()));
|
||||
WebSocketMessage encodeError(WebSocketSession session, String id, List<GraphQLError> errors) {
|
||||
return encode(session, GraphQlWebSocketMessage.error(id, errors));
|
||||
}
|
||||
|
||||
|
||||
@@ -347,12 +347,19 @@ public class GraphQlWebSocketHandler extends TextWebSocketHandler implements Sub
|
||||
GraphQlStatus.closeSession(session, status);
|
||||
return Flux.empty();
|
||||
}
|
||||
List<GraphQLError> errors = ((ex instanceof SubscriptionPublisherException) ?
|
||||
((SubscriptionPublisherException) ex).getErrors() :
|
||||
Collections.singletonList(GraphqlErrorBuilder.newError()
|
||||
.message("Subscription error")
|
||||
.errorType(ErrorType.INTERNAL_ERROR)
|
||||
.build()));
|
||||
List<GraphQLError> errors;
|
||||
if (ex instanceof SubscriptionPublisherException subscriptionEx) {
|
||||
errors = subscriptionEx.getErrors();
|
||||
}
|
||||
else {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Unresolved " + ex.getClass().getSimpleName() + " for request id " + id, ex);
|
||||
}
|
||||
errors = Collections.singletonList(GraphqlErrorBuilder.newError()
|
||||
.message("Subscription error")
|
||||
.errorType(ErrorType.INTERNAL_ERROR)
|
||||
.build());
|
||||
}
|
||||
return Mono.just(encode(GraphQlWebSocketMessage.error(id, errors)));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user