13
13
*/
14
14
package wvlet .airframe .http .grpc .internal
15
15
16
- import io .grpc .{StatusException , StatusRuntimeException }
16
+ import io .grpc .{Metadata , Status , StatusException , StatusRuntimeException }
17
17
import wvlet .airframe .codec .MessageCodecException
18
- import wvlet .airframe .http .{HttpServerException , HttpStatus }
18
+ import wvlet .airframe .http .{GrpcStatus , HttpServerException , HttpStatus }
19
19
import wvlet .log .LogSupport
20
20
21
21
import java .lang .reflect .InvocationTargetException
@@ -26,6 +26,8 @@ import scala.concurrent.ExecutionException
26
26
*/
27
27
object GrpcException extends LogSupport {
28
28
29
+ private [grpc] val rpcErrorKey = Metadata .Key .of[String ](" airframe_rpc_error" , Metadata .ASCII_STRING_MARSHALLER )
30
+
29
31
/**
30
32
* Convert an exception to gRPC-specific exception types
31
33
*
@@ -56,40 +58,34 @@ object GrpcException extends LogSupport {
56
58
s
57
59
case e : MessageCodecException =>
58
60
io.grpc.Status .INTERNAL
59
- .withDescription(s " Failed to encode/decode data " )
61
+ .withDescription(s " Failed to encode/decode data: ${e.getMessage} " )
60
62
.withCause(e)
61
63
.asRuntimeException()
62
64
case e : IllegalArgumentException =>
63
65
io.grpc.Status .INVALID_ARGUMENT
64
66
.withCause(e)
67
+ .withDescription(e.getMessage)
65
68
.asRuntimeException()
66
69
case e : UnsupportedOperationException =>
67
70
io.grpc.Status .UNIMPLEMENTED
68
71
.withCause(e)
72
+ .withDescription(e.getMessage)
69
73
.asRuntimeException()
70
74
case e : HttpServerException =>
71
- val s = e.status match {
72
- case HttpStatus .BadRequest_400 =>
73
- io.grpc.Status .INVALID_ARGUMENT
74
- case HttpStatus .Unauthorized_401 =>
75
- io.grpc.Status .UNAUTHENTICATED
76
- case HttpStatus .Forbidden_403 =>
77
- io.grpc.Status .PERMISSION_DENIED
78
- case HttpStatus .NotFound_404 =>
79
- io.grpc.Status .UNIMPLEMENTED
80
- case HttpStatus .Conflict_409 =>
81
- io.grpc.Status .ALREADY_EXISTS
82
- case HttpStatus .TooManyRequests_429 | HttpStatus .BadGateway_502 | HttpStatus .ServiceUnavailable_503 |
83
- HttpStatus .GatewayTimeout_504 =>
84
- io.grpc.Status .UNAVAILABLE
85
- case s if s.isServerError =>
86
- io.grpc.Status .INTERNAL
87
- case s if s.isClientError =>
88
- io.grpc.Status .INVALID_ARGUMENT
89
- case other =>
90
- io.grpc.Status .UNKNOWN
75
+ val grpcStatus = GrpcStatus .ofHttpStatus(e.status)
76
+ val s = Status
77
+ .fromCodeValue(grpcStatus.code)
78
+ .withCause(e)
79
+ .withDescription(e.getMessage)
80
+
81
+ if (e.message.nonEmpty) {
82
+ val m = e.message
83
+ val metadata = new Metadata ()
84
+ metadata.put[String ](rpcErrorKey, s " ${m.toContentString}" )
85
+ s.asRuntimeException(metadata)
86
+ } else {
87
+ s.asRuntimeException()
91
88
}
92
- s.withCause(e).asRuntimeException()
93
89
case other =>
94
90
io.grpc.Status .INTERNAL
95
91
.withCause(other)
0 commit comments