@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (needsToFilterUpgradeResponse && msg instanceof HttpResponse) { needsToFilterUpgradeResponse = false; final HttpResponse res = (HttpResponse) msg; if (res.status().code() == HttpResponseStatus.SWITCHING_PROTOCOLS.code()) { final HttpHeaders headers = res.headers(); if (!headers.contains(HttpHeaderNames.UPGRADE)) { headers.set(HttpHeaderNames.UPGRADE, Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME); } } if (!needsToFilterUpgradeRequest) { ctx.pipeline().remove(this); } } ctx.fireChannelRead(msg); }
private void configureHttp1WithUpgrade(ChannelHandlerContext ctx) { final ChannelPipeline p = ctx.pipeline(); final HttpServerCodec http1codec = new HttpServerCodec( config.defaultMaxHttp1InitialLineLength(), config.defaultMaxHttp1HeaderSize(), config.defaultMaxHttp1ChunkSize()); String baseName = name; baseName = addAfter(p, baseName, http1codec); baseName = addAfter(p, baseName, new HttpServerUpgradeHandler( http1codec, protocol -> { if (!AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { return null; } return new Http2ServerUpgradeCodec( newHttp2ConnectionHandler(p)); }, UPGRADE_REQUEST_MAX_LENGTH)); addAfter(p, baseName, new Http1RequestDecoder(config, ctx.channel(), SCHEME_HTTP)); }
@Override protected void manualSetUp() throws Exception { assertNull("manualSetUp should not run more than once", handler()); initChannel(new GrpcHttp2ServerHeadersDecoder(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE)); // replace the keepAliveManager with spyKeepAliveManager spyKeepAliveManager = mock(KeepAliveManager.class, delegatesTo(handler().getKeepAliveManagerForTest())); handler().setKeepAliveManagerForTest(spyKeepAliveManager); // Simulate receipt of the connection preface handler().handleProtocolNegotiationCompleted(Attributes.EMPTY); channelRead(Http2CodecUtil.connectionPrefaceBuf()); // Simulate receipt of initial remote settings. ByteBuf serializedSettings = serializeSettings(new Http2Settings()); channelRead(serializedSettings); }
@Test public void transportTracer_windowUpdate_local() throws Exception { manualSetUp(); TransportStats before = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, before.remoteFlowControlWindow); assertEquals(flowControlWindow, before.localFlowControlWindow); // If the window size is below a certain threshold, netty will wait to apply the update. // Use a large increment to be sure that it exceeds the threshold. connection().local().flowController().incrementWindowSize( connection().connectionStream(), 8 * Http2CodecUtil.DEFAULT_WINDOW_SIZE); TransportStats after = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, after.remoteFlowControlWindow); assertEquals(flowControlWindow + 8 * Http2CodecUtil.DEFAULT_WINDOW_SIZE, connection().local().flowController().windowSize(connection().connectionStream())); }
@Override public UpgradeCodec newUpgradeCodec(CharSequence protocol) { if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { return new Http2ServerUpgradeCodec(new Http2MultiplexCodec(true, new HelloWorldHttp2Handler())); } else { return null; } }
@Override public UpgradeCodec newUpgradeCodec(CharSequence protocol) { if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { return new Http2ServerUpgradeCodec(new HelloWorldHttp2HandlerBuilder().build()); } else { return null; } }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof UpgradeEvent) { // Generate the initial Http2Settings frame, // so that the next handler knows the protocol upgrade occurred as well. ctx.fireChannelRead(DEFAULT_HTTP2_SETTINGS); // Continue handling the upgrade request after the upgrade is complete. final FullHttpRequest nettyReq = ((UpgradeEvent) evt).upgradeRequest(); // Remove the headers related with the upgrade. nettyReq.headers().remove(HttpHeaderNames.CONNECTION); nettyReq.headers().remove(HttpHeaderNames.UPGRADE); nettyReq.headers().remove(Http2CodecUtil.HTTP_UPGRADE_SETTINGS_HEADER); if (logger.isDebugEnabled()) { logger.debug("{} Handling the pre-upgrade request ({}): {} {} {} ({}B)", ctx.channel(), ((UpgradeEvent) evt).protocol(), nettyReq.method(), nettyReq.uri(), nettyReq.protocolVersion(), nettyReq.content().readableBytes()); } channelRead(ctx, nettyReq); channelReadComplete(ctx); return; } ctx.fireUserEventTriggered(evt); }
private void writeHeaders( ChannelHandlerContext ctx, Http2Headers headers, boolean eos, ChannelPromise promise) throws Exception { encoder() .writeHeaders( ctx, currentStreamId, headers, 0, Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT, false, 0, eos, promise); }
private void h2cOrHttp1(final ChannelHandlerContext ctx) { ChannelPipeline p = ctx.pipeline(); HttpServerCodec http1codec = http1Codec(); String baseName = name; baseName = addAfter(p, baseName, "codec", http1codec); baseName = addAfter(p, baseName, "h2upgrade", new HttpServerUpgradeHandler(http1codec, protocol -> { if (!AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) { return null; } return new Http2ServerUpgradeCodec(newHttp2ConnectionHandler(p)); }, maxContentLength)); }
@Test public void transportReadyDelayedUntilConnectionPreface() throws Exception { initChannel(new GrpcHttp2ServerHeadersDecoder(GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE)); handler().handleProtocolNegotiationCompleted(Attributes.EMPTY); verify(transportListener, never()).transportReady(any(Attributes.class)); // Simulate receipt of the connection preface channelRead(Http2CodecUtil.connectionPrefaceBuf()); channelRead(serializeSettings(new Http2Settings())); verify(transportListener).transportReady(any(Attributes.class)); }
@Test public void transportTracer_windowSizeDefault() throws Exception { manualSetUp(); TransportStats transportStats = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, transportStats.remoteFlowControlWindow); assertEquals(flowControlWindow, transportStats.localFlowControlWindow); }
@Test public void transportTracer_windowSize() throws Exception { flowControlWindow = 1024 * 1024; manualSetUp(); TransportStats transportStats = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, transportStats.remoteFlowControlWindow); assertEquals(flowControlWindow, transportStats.localFlowControlWindow); }
@Test public void transportTracer_windowUpdate_remote() throws Exception { manualSetUp(); TransportStats before = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, before.remoteFlowControlWindow); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE, before.localFlowControlWindow); ByteBuf serializedSettings = windowUpdate(0, 1000); channelRead(serializedSettings); TransportStats after = transportTracer.getStats(); assertEquals(Http2CodecUtil.DEFAULT_WINDOW_SIZE + 1000, after.remoteFlowControlWindow); assertEquals(flowControlWindow, after.localFlowControlWindow); }