/** * Converts the {@link Throwable} to a {@link Status}, taking into account exceptions specific to Armeria as * well. */ public static Status fromThrowable(Throwable t) { requireNonNull(t, "t"); Status s = Status.fromThrowable(t); if (s.getCode() != Code.UNKNOWN) { return s; } if (t instanceof StreamException) { StreamException streamException = (StreamException) t; if (streamException.getMessage() != null && streamException.getMessage().contains("RST_STREAM")) { return Status.CANCELLED; } } if (t instanceof ClosedChannelException) { // ClosedChannelException is used any time the Netty channel is closed. Proper error // processing requires remembering the error that occurred before this one and using it // instead. return Status.UNKNOWN.withCause(t); } if (t instanceof IOException) { return Status.UNAVAILABLE.withCause(t); } if (t instanceof Http2Exception) { return Status.INTERNAL.withCause(t); } if (t instanceof ResponseTimeoutException) { return Status.DEADLINE_EXCEEDED.withCause(t); } return s; }
@Override protected void onStreamError(ChannelHandlerContext ctx, Throwable cause, StreamException http2Ex) { logger.log(Level.WARNING, "Stream Error", cause); NettyServerStream.TransportState serverStream = serverStream( connection().stream(Http2Exception.streamId(http2Ex))); if (serverStream != null) { serverStream.transportReportStatus(Utils.statusFromThrowable(cause)); } // TODO(ejona): Abort the stream by sending headers to help the client with debugging. // Delegate to the base class to send a RST_STREAM. super.onStreamError(ctx, cause, http2Ex); }