下面列出了怎么用 io.netty.handler.codec.http2.Http2FrameCodecBuilder 的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception {
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
ctx.pipeline().addLast(Http2FrameCodecBuilder.forServer().build(), new HelloWorldHttp2Handler());
return;
}
if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) {
ctx.pipeline().addLast(new HttpServerCodec(),
new HttpObjectAggregator(MAX_CONTENT_LENGTH),
new HelloWorldHttp1Handler("ALPN Negotiation"));
return;
}
throw new IllegalStateException("unknown protocol: " + protocol);
}
@Override
public void init(final Channel channel) {
final Http2FrameCodecBuilder multiplexCodecBuilder = forServer()
// We do not want close to trigger graceful closure (go away), instead when user triggers a graceful
// close, we do the appropriate go away handling.
.decoupleCloseAndGoAway(true)
// We don't want to rely upon Netty to manage the graceful close timeout, because we expect
// the user to apply their own timeout at the call site.
.gracefulShutdownTimeoutMillis(-1);
final BiPredicate<CharSequence, CharSequence> headersSensitivityDetector =
config.headersSensitivityDetector();
multiplexCodecBuilder.headerSensitivityDetector(headersSensitivityDetector::test);
final String frameLoggerName = config.frameLoggerName();
if (frameLoggerName != null) {
multiplexCodecBuilder.frameLogger(new Http2FrameLogger(TRACE, frameLoggerName));
}
// TODO(scott): more configuration. header validation, settings stream, etc...
channel.pipeline().addLast(multiplexCodecBuilder.build(), new Http2MultiplexHandler(streamChannelInitializer));
}
private InetSocketAddress bindH2Server(ChannelHandler childChannelHandler,
Consumer<ChannelPipeline> parentChannelInitializer) {
ServerBootstrap sb = new ServerBootstrap();
sb.group(serverEventLoopGroup);
sb.channel(serverChannel(serverEventLoopGroup, InetSocketAddress.class));
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(final Channel ch) {
ch.pipeline().addLast(
Http2FrameCodecBuilder.forServer().build(),
new Http2MultiplexHandler(childChannelHandler));
parentChannelInitializer.accept(ch.pipeline());
}
});
serverAcceptorChannel = sb.bind(localAddress(0)).syncUninterruptibly().channel();
return (InetSocketAddress) serverAcceptorChannel.localAddress();
}
static void configureHttp2Pipeline(ChannelPipeline p, HttpResponseDecoderSpec decoder, Http2Settings http2Settings,
ConnectionObserver observer) {
Http2FrameCodecBuilder http2FrameCodecBuilder =
Http2FrameCodecBuilder.forClient()
.validateHeaders(decoder.validateHeaders())
.initialSettings(http2Settings);
if (p.get(NettyPipeline.LoggingHandler) != null) {
http2FrameCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG,
"reactor.netty.http.client.h2"));
}
p.addBefore(NettyPipeline.ReactiveBridge, NettyPipeline.HttpCodec, http2FrameCodecBuilder.build())
.addBefore(NettyPipeline.ReactiveBridge, NettyPipeline.H2MultiplexHandler, new Http2MultiplexHandler(new H2Codec()))
.addBefore(NettyPipeline.ReactiveBridge, NettyPipeline.HttpTrafficHandler, new HttpTrafficHandler(observer));
}
static void configureH2Pipeline(ChannelPipeline p,
ServerCookieDecoder cookieDecoder,
ServerCookieEncoder cookieEncoder,
boolean forwarded,
Http2Settings http2Settings,
ConnectionObserver listener,
ChannelOperations.OnSetup opsFactory,
boolean validate) {
p.remove(NettyPipeline.ReactiveBridge);
Http2FrameCodecBuilder http2FrameCodecBuilder =
Http2FrameCodecBuilder.forServer()
.validateHeaders(validate)
.initialSettings(http2Settings);
if (p.get(NettyPipeline.LoggingHandler) != null) {
http2FrameCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG,
"reactor.netty.http.server.h2"));
}
p.addLast(NettyPipeline.HttpCodec, http2FrameCodecBuilder.build())
.addLast(NettyPipeline.H2MultiplexHandler,
new Http2MultiplexHandler(new H2Codec(opsFactory, listener, forwarded, cookieEncoder, cookieDecoder)));
}
Http11OrH2CleartextCodec(
ServerCookieDecoder cookieDecoder,
ServerCookieEncoder cookieEncoder,
boolean debug,
boolean forwarded,
Http2Settings http2Settings,
ConnectionObserver listener,
ChannelOperations.OnSetup opsFactory,
boolean validate) {
this.cookieDecoder = cookieDecoder;
this.cookieEncoder = cookieEncoder;
this.forwarded = forwarded;
Http2FrameCodecBuilder http2FrameCodecBuilder =
Http2FrameCodecBuilder.forServer()
.validateHeaders(validate)
.initialSettings(http2Settings);
if (debug) {
http2FrameCodecBuilder.frameLogger(new Http2FrameLogger(
LogLevel.DEBUG,
"reactor.netty.http.server.h2"));
}
this.http2FrameCodec = http2FrameCodecBuilder.build();
this.listener = listener;
this.opsFactory = opsFactory;
}
public static ApplicationProtocolNegotiationHandler getServerAPNHandler() {
ApplicationProtocolNegotiationHandler serverAPNHandler = new ApplicationProtocolNegotiationHandler(ApplicationProtocolNames.HTTP_2) {
@Override
protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception {
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
ctx.pipeline()
.addLast(Http2FrameCodecBuilder.forServer()
.build(), new Http2ServerResponseHandler());
return;
}
throw new IllegalStateException("Protocol: " + protocol + " not supported");
}
};
return serverAPNHandler;
}
private void configureHttp2(ChannelPipeline pipeline) {
// setup the initial stream settings for the server to use.
Http2Settings settings = new Http2Settings()
.maxConcurrentStreams(maxConcurrentStreams)
.initialWindowSize(initialWindowSize)
.headerTableSize(maxHeaderTableSize)
.maxHeaderListSize(maxHeaderListSize);
Http2FrameCodec frameCodec = Http2FrameCodecBuilder.forServer()
.frameLogger(FRAME_LOGGER)
.initialSettings(settings)
.validateHeaders(true)
.build();
Http2MultiplexHandler multiplexHandler = new Http2MultiplexHandler(http2StreamHandler);
// The frame codec MUST be in the pipeline.
pipeline.addBefore("codec_placeholder", /* name= */ null, frameCodec);
pipeline.replace("codec_placeholder", HTTP_CODEC_HANDLER_NAME, multiplexHandler);
}
@Override
public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) {
return new Http2ServerUpgradeCodec(
Http2FrameCodecBuilder.forServer().build(), new HelloWorldHttp2Handler());
} else {
return null;
}
}
@Override
public void init(final Channel channel) {
final Http2FrameCodecBuilder multiplexCodecBuilder = forClient()
// We do not want close to trigger graceful closure (go away), instead when user triggers a graceful
// close, we do the appropriate go away handling.
.decoupleCloseAndGoAway(true)
// The max concurrent streams is made available via a publisher and may be consumed asynchronously
// (e.g. when offloading is enabled), so we manually control the SETTINGS ACK frames.
.autoAckSettingsFrame(false)
// We don't want to rely upon Netty to manage the graceful close timeout, because we expect
// the user to apply their own timeout at the call site.
.gracefulShutdownTimeoutMillis(-1);
// Notify server that this client does not support server push and request it to be disabled.
multiplexCodecBuilder.initialSettings().pushEnabled(false).maxConcurrentStreams(0L);
final BiPredicate<CharSequence, CharSequence> headersSensitivityDetector =
config.headersSensitivityDetector();
multiplexCodecBuilder.headerSensitivityDetector(headersSensitivityDetector::test);
final String frameLoggerName = config.frameLoggerName();
if (frameLoggerName != null) {
multiplexCodecBuilder.frameLogger(new Http2FrameLogger(TRACE, frameLoggerName));
}
// TODO(scott): more configuration. header validation, settings stream, etc...
channel.pipeline().addLast(multiplexCodecBuilder.build(),
new Http2MultiplexHandler(H2PushStreamHandler.INSTANCE));
}
@Override
protected void initChannel(SocketChannel ch) {
Http2FrameCodec codec = Http2FrameCodecBuilder.forServer()
.autoAckPingFrame(true)
.initialSettings(new Http2Settings()
.initialWindowSize(16384)
.maxFrameSize(16384)
.maxConcurrentStreams(5))
.build();
ch.pipeline().addLast(codec);
ch.pipeline().addLast(handlerSupplier.get());
}
@Override
protected void initChannel(SocketChannel ch) {
Http2FrameCodec codec = Http2FrameCodecBuilder.forServer()
.initialSettings(new Http2Settings()
.maxConcurrentStreams(5))
.build();
ch.pipeline().addLast(codec);
ch.pipeline().addLast(handlerSupplier.get());
}
public static EmbeddedChannel newHttp2Channel(ChannelHandler channelHandler) {
Http2FrameCodec http2FrameCodec = Http2FrameCodecBuilder.forClient().initialSettings(
Http2Settings.defaultSettings().initialWindowSize(INITIAL_WINDOW_SIZE))
.frameLogger(new Http2FrameLogger(LogLevel.DEBUG)).build();
EmbeddedChannel channel = new EmbeddedChannel(http2FrameCodec,
new Http2MultiplexHandler(channelHandler));
channel.attr(ChannelAttributeKey.HTTP2_CONNECTION).set(http2FrameCodec.connection());
channel.attr(ChannelAttributeKey.HTTP2_INITIAL_WINDOW_SIZE).set(INITIAL_WINDOW_SIZE);
channel.attr(ChannelAttributeKey.PROTOCOL_FUTURE).set(CompletableFuture.completedFuture(Protocol.HTTP2));
return channel;
}
@Override
public void channelCreated(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
SslHandler sslHandler = new SslHandler(sslFactory.createSSLEngine(host, port, SSLFactory.Mode.CLIENT));
pipeline.addLast(sslHandler);
pipeline.addLast(Http2FrameCodecBuilder.forClient()
.initialSettings(Http2Settings.defaultSettings()
.maxFrameSize(http2ClientConfig.http2FrameMaxSize)
.initialWindowSize(http2ClientConfig.http2InitialWindowSize))
.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "client"))
.build());
pipeline.addLast(new Http2MultiplexHandler(new ChannelInboundHandlerAdapter()));
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// To honor http2 window size, WriteBufferWaterMark.high() should be greater or equal to http2 window size.
// Also see: https://github.com/netty/netty/issues/10193
// https://stackoverflow.com/questions/25281124/netty-4-high-and-low-write-watermarks
ch.config()
.setSendBufferSize(http2ClientConfig.nettySendBufferSize)
.setReceiveBufferSize(http2ClientConfig.nettyReceiveBufferSize)
.setWriteBufferWaterMark(new WriteBufferWaterMark(http2ClientConfig.http2InitialWindowSize,
2 * http2ClientConfig.http2InitialWindowSize));
// If channel handler implementations are not annotated with @Sharable, Netty creates a new instance of every class
// in the pipeline for every connection.
// i.e. if there are a 1000 active connections there will be a 1000 NettyMessageProcessor instances.
ChannelPipeline pipeline = ch.pipeline();
// connection stats handler to track connection related metrics
pipeline.addLast("ConnectionStatsHandler", connectionStatsHandler);
InetSocketAddress peerAddress = ch.remoteAddress();
String peerHost = peerAddress.getHostName();
int peerPort = peerAddress.getPort();
SslHandler sslHandler = new SslHandler(sslFactory.createSSLEngine(peerHost, peerPort, SSLFactory.Mode.SERVER));
pipeline.addLast("SslHandler", sslHandler);
pipeline.addLast("SecurityChecker", serverSecurityHandler);
pipeline.addLast("Http2FrameCodec", Http2FrameCodecBuilder.forServer()
.initialSettings(Http2Settings.defaultSettings()
.maxFrameSize(http2ClientConfig.http2FrameMaxSize)
.initialWindowSize(http2ClientConfig.http2InitialWindowSize))
.frameLogger(new Http2FrameLogger(LogLevel.DEBUG, "server"))
.build());
pipeline.addLast("Http2MultiplexHandler", new Http2MultiplexHandler(http2ServerStreamHandler));
pipeline.addLast("CloseOnExceptionHandler", closeOnExceptionHandler);
}
private EmbeddedChannel newHttp2Channel() {
EmbeddedChannel channel = new EmbeddedChannel(Http2FrameCodecBuilder.forClient().build(),
new Http2MultiplexHandler(new NoOpHandler()));
channel.attr(ChannelAttributeKey.PROTOCOL_FUTURE).set(CompletableFuture.completedFuture(Protocol.HTTP2));
return channel;
}
static void configureHttp11OrH2CleartextPipeline(
ChannelPipeline p,
boolean acceptGzip,
HttpResponseDecoderSpec decoder,
Http2Settings http2Settings,
@Nullable Supplier<? extends ChannelMetricsRecorder> metricsRecorder,
ConnectionObserver observer,
ChannelOperations.OnSetup opsFactory,
@Nullable Function<String, String> uriTagValue) {
HttpClientCodec httpClientCodec =
new HttpClientCodec(
decoder.maxInitialLineLength(),
decoder.maxHeaderSize(),
decoder.maxChunkSize(),
decoder.failOnMissingResponse,
decoder.validateHeaders(),
decoder.initialBufferSize(),
decoder.parseHttpAfterConnectRequest);
Http2FrameCodecBuilder http2FrameCodecBuilder =
Http2FrameCodecBuilder.forClient()
.validateHeaders(decoder.validateHeaders())
.initialSettings(http2Settings);
if (p.get(NettyPipeline.LoggingHandler) != null) {
http2FrameCodecBuilder.frameLogger(new Http2FrameLogger(LogLevel.DEBUG,
"reactor.netty.http.client.h2"));
}
Http2FrameCodec http2FrameCodec = http2FrameCodecBuilder.build();
Http2ClientUpgradeCodec upgradeCodec = new Http2ClientUpgradeCodec(http2FrameCodec, new H2CleartextCodec(http2FrameCodec, opsFactory));
HttpClientUpgradeHandler upgradeHandler = new HttpClientUpgradeHandler(httpClientCodec, upgradeCodec, decoder.h2cMaxContentLength());
p.addBefore(NettyPipeline.ReactiveBridge, null, httpClientCodec)
.addBefore(NettyPipeline.ReactiveBridge, NettyPipeline.H2CUpgradeHandler, upgradeHandler)
.addBefore(NettyPipeline.ReactiveBridge, NettyPipeline.HttpTrafficHandler, new HttpTrafficHandler(observer));
if (acceptGzip) {
p.addAfter(NettyPipeline.HttpCodec, NettyPipeline.HttpDecompressor, new HttpContentDecompressor());
}
if (metricsRecorder != null) {
ChannelMetricsRecorder channelMetricsRecorder = metricsRecorder.get();
if (channelMetricsRecorder instanceof HttpClientMetricsRecorder) {
p.addBefore(NettyPipeline.ReactiveBridge,
NettyPipeline.HttpMetricsHandler,
new HttpClientMetricsHandler((HttpClientMetricsRecorder) channelMetricsRecorder, uriTagValue));
}
}
}
static EmbeddedChannel newHttp2Channel() {
EmbeddedChannel channel =
new EmbeddedChannel(Http2FrameCodecBuilder.forClient().build(), new Http2MultiplexHandler(new NoOpHandler()));
return channel;
}