下面列出了怎么用 io.netty.handler.codec.http2.Http2Exception.StreamException 的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Central handler for all exceptions caught during HTTP/2 processing.
*/
@Override
public void onError(ChannelHandlerContext ctx, boolean outbound, Throwable cause) {
Http2Exception embedded = getEmbeddedHttp2Exception(cause);
if (isStreamError(embedded)) {
onStreamError(ctx, outbound, cause, (StreamException) embedded);
} else if (embedded instanceof CompositeStreamException) {
CompositeStreamException compositException = (CompositeStreamException) embedded;
for (StreamException streamException : compositException) {
onStreamError(ctx, outbound, cause, streamException);
}
} else {
onConnectionError(ctx, outbound, cause, embedded);
}
ctx.flush();
}
@Test
public void streamErrorShouldFireExceptionForInbound() throws Exception {
frameListener.onHeadersRead(http2HandlerCtx, 3, request, 31, false);
Http2Stream stream = frameCodec.connection().stream(3);
assertNotNull(stream);
StreamException streamEx = new StreamException(3, Http2Error.INTERNAL_ERROR, "foo");
frameCodec.onError(http2HandlerCtx, false, streamEx);
Http2FrameStreamEvent event = inboundHandler.readInboundMessageOrUserEvent();
assertEquals(Http2FrameStreamEvent.Type.State, event.type());
assertEquals(State.OPEN, event.stream().state());
Http2HeadersFrame headersFrame = inboundHandler.readInboundMessageOrUserEvent();
assertNotNull(headersFrame);
try {
inboundHandler.checkException();
fail("stream exception expected");
} catch (Http2FrameStreamException e) {
assertEquals(streamEx, e.getCause());
}
assertNull(inboundHandler.readInboundMessageOrUserEvent());
}
@Test
public void streamErrorShouldNotFireExceptionForOutbound() throws Exception {
frameListener.onHeadersRead(http2HandlerCtx, 3, request, 31, false);
Http2Stream stream = frameCodec.connection().stream(3);
assertNotNull(stream);
StreamException streamEx = new StreamException(3, Http2Error.INTERNAL_ERROR, "foo");
frameCodec.onError(http2HandlerCtx, true, streamEx);
Http2FrameStreamEvent event = inboundHandler.readInboundMessageOrUserEvent();
assertEquals(Http2FrameStreamEvent.Type.State, event.type());
assertEquals(State.OPEN, event.stream().state());
Http2HeadersFrame headersFrame = inboundHandler.readInboundMessageOrUserEvent();
assertNotNull(headersFrame);
// No exception expected
inboundHandler.checkException();
assertNull(inboundHandler.readInboundMessageOrUserEvent());
}
@Test(expected = ClosedChannelException.class)
public void streamClosedErrorTranslatedToClosedChannelExceptionOnWrites() throws Exception {
writer = new Writer() {
@Override
void write(Object msg, ChannelPromise promise) {
promise.tryFailure(new StreamException(inboundStream.id(), Http2Error.STREAM_CLOSED, "Stream Closed"));
}
};
LastInboundHandler inboundHandler = new LastInboundHandler();
childChannelInitializer.handler = inboundHandler;
Channel childChannel = newOutboundStream();
assertTrue(childChannel.isActive());
ChannelFuture future = childChannel.writeAndFlush(new DefaultHttp2HeadersFrame(new DefaultHttp2Headers()));
parentChannel.flush();
assertFalse(childChannel.isActive());
assertFalse(childChannel.isOpen());
inboundHandler.checkException();
future.syncUninterruptibly();
}
@Override
protected void onStreamError(ChannelHandlerContext ctx, boolean outbound, Throwable cause,
StreamException http2Ex) {
logger.log(Level.WARNING, "Stream Error", cause);
NettyServerStream.TransportState serverStream = serverStream(
connection().stream(Http2Exception.streamId(http2Ex)));
Tag tag = serverStream != null ? serverStream.tag() : PerfMark.createTag();
PerfMark.startTask("NettyServerHandler.onStreamError", tag);
try {
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, outbound, cause, http2Ex);
} finally {
PerfMark.stopTask("NettyServerHandler.onStreamError", tag);
}
}
@Override
protected void onStreamError(ChannelHandlerContext ctx, boolean outbound, 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, outbound, cause, http2Ex);
}
@Override
public boolean visit(Http2Stream stream) throws Http2Exception {
try {
// Increment flow control window first so state will be consistent if overflow is detected.
FlowState state = state(stream);
state.incrementFlowControlWindows(delta);
state.incrementInitialStreamWindow(delta);
} catch (StreamException e) {
if (compositeException == null) {
compositeException = new CompositeStreamException(e.error(), 4);
}
compositeException.add(e);
}
return true;
}
@Test(expected = StreamException.class)
public void streamExceptionTriggersChildChannelExceptionAndClose() throws Exception {
LastInboundHandler inboundHandler = streamActiveAndWriteHeaders(inboundStream);
StreamException cause = new StreamException(inboundStream.id(), Http2Error.PROTOCOL_ERROR, "baaam!");
Http2FrameStreamException http2Ex = new Http2FrameStreamException(
inboundStream, Http2Error.PROTOCOL_ERROR, cause);
codec.onHttp2FrameStreamException(http2Ex);
inboundHandler.checkException();
}
@Test(expected = StreamException.class)
public void streamExceptionClosesChildChannel() throws Exception {
LastInboundHandler inboundHandler = streamActiveAndWriteHeaders(inboundStream);
assertTrue(inboundHandler.isChannelActive());
StreamException cause = new StreamException(inboundStream.id(), Http2Error.PROTOCOL_ERROR, "baaam!");
Http2FrameStreamException http2Ex = new Http2FrameStreamException(
inboundStream, Http2Error.PROTOCOL_ERROR, cause);
codec.onHttp2FrameStreamException(http2Ex);
parentChannel.runPendingTasks();
assertFalse(inboundHandler.isChannelActive());
inboundHandler.checkException();
}
/**
* Handler for a stream error. Sends a {@code RST_STREAM} frame to the remote endpoint and closes the
* stream.
*
* @param ctx the channel context
* @param outbound {@code true} if the error was caused by an outbound operation.
* @param cause the exception that was caught
* @param http2Ex the {@link StreamException} that is embedded in the causality chain.
*/
protected void onStreamError(ChannelHandlerContext ctx, boolean outbound,
@SuppressWarnings("unused") Throwable cause, StreamException http2Ex) {
final int streamId = http2Ex.streamId();
Http2Stream stream = connection().stream(streamId);
//if this is caused by reading headers that are too large, send a header with status 431
if (http2Ex instanceof Http2Exception.HeaderListSizeException &&
((Http2Exception.HeaderListSizeException) http2Ex).duringDecode() &&
connection().isServer()) {
// NOTE We have to check to make sure that a stream exists before we send our reply.
// We likely always create the stream below as the stream isn't created until the
// header block is completely processed.
// The case of a streamId referring to a stream which was already closed is handled
// by createStream and will land us in the catch block below
if (stream == null) {
try {
stream = encoder.connection().remote().createStream(streamId, true);
} catch (Http2Exception e) {
resetUnknownStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise());
return;
}
}
// ensure that we have not already sent headers on this stream
if (stream != null && !stream.isHeadersSent()) {
try {
handleServerHeaderDecodeSizeError(ctx, stream);
} catch (Throwable cause2) {
onError(ctx, outbound, connectionError(INTERNAL_ERROR, cause2, "Error DecodeSizeError"));
}
}
}
if (stream == null) {
resetUnknownStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise());
} else {
resetStream(ctx, stream, http2Ex.error().code(), ctx.newPromise());
}
}
@Test(expected = StreamException.class)
public void headersExceedMaxSetSizeShouldFail() throws Http2Exception {
Http2Headers headers = headers();
encoder.maxHeaderListSize(2);
encoder.encodeHeaders(3 /* randomly chosen */, headers, Unpooled.buffer());
}