Skip to content

Commit

Permalink
Log unhandled exceptions in WebSocket handlers
Browse files Browse the repository at this point in the history
Closes gh-1122
  • Loading branch information
rstoyanchev committed Feb 17, 2025
1 parent db78043 commit 3360e4a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -28,6 +28,8 @@
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;
Expand All @@ -36,6 +38,8 @@
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;
Expand Down Expand Up @@ -256,7 +260,20 @@ private Flux<WebSocketMessage> handleResponse(WebSocketSession session, String i
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));
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -105,13 +101,7 @@ WebSocketMessage encodeNext(WebSocketSession session, String id, Map<String, Obj
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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,19 @@ private Flux<TextMessage> handleResponse(WebSocketSession session, String id, We
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)));
});
}
Expand Down

0 comments on commit 3360e4a

Please sign in to comment.