All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.hyperfoil.http.connection.HttpChannelInitializer Maven / Gradle / Ivy

There is a newer version: 0.27.1
Show newest version
package io.hyperfoil.http.connection;

import java.io.IOException;
import java.util.function.BiConsumer;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpClientUpgradeHandler;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.Http2ClientUpgradeCodec;
import io.netty.handler.ssl.ApplicationProtocolNames;
import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
import io.hyperfoil.http.api.HttpConnection;

class HttpChannelInitializer extends ChannelInitializer {
   private final HttpClientPoolImpl clientPool;
   private final BiConsumer handler;
   private final Http2ConnectionHandlerBuilder http2ConnectionHandlerBuilder;
   private final ApplicationProtocolNegotiationHandler alpnHandler = new ApplicationProtocolNegotiationHandler(ApplicationProtocolNames.HTTP_1_1) {
      @Override
      protected void configurePipeline(ChannelHandlerContext ctx, String protocol) {
         ChannelPipeline p = ctx.pipeline();
         if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
            io.netty.handler.codec.http2.Http2Connection connection = new DefaultHttp2Connection(false);
            CustomHttp2ConnectionHandler clientHandler = http2ConnectionHandlerBuilder.build(connection);
            p.addLast(clientHandler);
         } else if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) {
            initHttp1xConnection(p);
         } else {
            ctx.close();
            throw new IllegalStateException("unknown protocol: " + protocol);
         }
      }

      @Override
      protected void handshakeFailure(ChannelHandlerContext ctx, Throwable cause) throws Exception {
         handler.accept(null, new IOException("TLS handshake failure", cause));
         ctx.close();
      }
   };

   HttpChannelInitializer(HttpClientPoolImpl clientPool, BiConsumer handler) {
      this.clientPool = clientPool;
      this.handler = handler;
      this.http2ConnectionHandlerBuilder = new Http2ConnectionHandlerBuilder(clientPool, clientPool.sslContext == null, handler);
   }

   @Override
   protected void initChannel(Channel ch) {
      ChannelPipeline pipeline = ch.pipeline();
      if (clientPool.sslContext != null) {
         pipeline.addLast(clientPool.sslContext.newHandler(ch.alloc(), clientPool.host, clientPool.port));
         pipeline.addLast(alpnHandler);
      } else if (clientPool.forceH2c) {
         io.netty.handler.codec.http2.Http2Connection connection = new DefaultHttp2Connection(false);
         CustomHttp2ConnectionHandler clientHandler = http2ConnectionHandlerBuilder.build(connection);
         HttpClientCodec sourceCodec = new HttpClientCodec();
         Http2ClientUpgradeCodec upgradeCodec = new Http2ClientUpgradeCodec(clientHandler);
         HttpClientUpgradeHandler upgradeHandler = new HttpClientUpgradeHandler(sourceCodec, upgradeCodec, 65536);
         ChannelHandler upgradeRequestHandler = new ChannelInboundHandlerAdapter() {
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
               DefaultFullHttpRequest upgradeRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
               upgradeRequest.headers().add(HttpHeaderNames.HOST, clientPool.authority);
               ctx.writeAndFlush(upgradeRequest);
               ctx.fireChannelActive();
               ctx.pipeline().remove(this);
            }
         };
         pipeline.addLast(sourceCodec,
               upgradeHandler,
               upgradeRequestHandler);
      } else {
         initHttp1xConnection(pipeline);
      }
   }

   private void initHttp1xConnection(ChannelPipeline pipeline) {
      Http1xConnection connection = new Http1xConnection(clientPool, handler);
      if (clientPool.http.rawBytesHandlers()) {
         pipeline.addLast(new Http1xResponseHandler(connection));
         pipeline.addLast(new RawRequestHandler(connection));
      }
      pipeline.addLast("handler", connection);
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy