Fix status trailers in exception handler
This commit is contained in:
@@ -5,7 +5,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.grpc.server.exception.GrpcExceptionHandler;
|
||||
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusException;
|
||||
|
||||
@SpringBootApplication
|
||||
public class GrpcServerApplication {
|
||||
@@ -18,7 +20,11 @@ public class GrpcServerApplication {
|
||||
public GrpcExceptionHandler globalInterceptor() {
|
||||
return exception -> {
|
||||
if (exception instanceof IllegalArgumentException) {
|
||||
return Status.INVALID_ARGUMENT.withDescription(exception.getMessage()).asException();
|
||||
Metadata metadata = new Metadata();
|
||||
metadata.put(Metadata.Key.of("error-code", Metadata.ASCII_STRING_MARSHALLER), "INVALID_ARGUMENT");
|
||||
StatusException result = Status.INVALID_ARGUMENT.withDescription(exception.getMessage())
|
||||
.asException(metadata);
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import io.grpc.ForwardingServerCallListener;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.ServerCall.Listener;
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.Status.Code;
|
||||
@@ -77,18 +78,19 @@ class GrpcServerIntegrationTests {
|
||||
void specificErrorResponse(@Autowired GrpcChannelFactory channels) {
|
||||
SimpleGrpc.SimpleBlockingStub client = SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:0"));
|
||||
assertThat(assertThrows(StatusRuntimeException.class,
|
||||
() -> client.sayHello(HelloRequest.newBuilder().setName("error").build()))
|
||||
() -> client.sayHello(HelloRequest.newBuilder().setName("internal").build()))
|
||||
.getStatus()
|
||||
.getCode()).isEqualTo(Code.INVALID_ARGUMENT);
|
||||
.getCode()).isEqualTo(Code.UNKNOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultErrorResponseIsUnknown(@Autowired GrpcChannelFactory channels) {
|
||||
SimpleGrpc.SimpleBlockingStub client = SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:0"));
|
||||
assertThat(assertThrows(StatusRuntimeException.class,
|
||||
() -> client.sayHello(HelloRequest.newBuilder().setName("internal").build()))
|
||||
.getStatus()
|
||||
.getCode()).isEqualTo(Code.UNKNOWN);
|
||||
StatusRuntimeException status = assertThrows(StatusRuntimeException.class,
|
||||
() -> client.sayHello(HelloRequest.newBuilder().setName("error").build()));
|
||||
assertThat(status.getStatus().getCode()).isEqualTo(Code.INVALID_ARGUMENT);
|
||||
assertThat(status.getTrailers().get(Metadata.Key.of("error-code", Metadata.ASCII_STRING_MARSHALLER)))
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public class GrpcExceptionHandledServerCall<ReqT, RespT>
|
||||
if (status.getCode() == Status.Code.UNKNOWN && status.getCause() != null) {
|
||||
final Throwable cause = status.getCause();
|
||||
final StatusException statusException = this.exceptionHandler.handleException(cause);
|
||||
trailers.merge(statusException.getTrailers());
|
||||
super.close(statusException.getStatus(), trailers);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -147,7 +147,7 @@ public class GrpcExceptionHandlerInterceptor implements ServerInterceptor {
|
||||
catch (Throwable e) {
|
||||
}
|
||||
try {
|
||||
this.call.close(status.getStatus(), headers(t));
|
||||
this.call.close(status.getStatus(), headers(status));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new IllegalStateException("Failed to close the call", e);
|
||||
|
||||
Reference in New Issue
Block a user