5252 */
5353public class Http1xOrH2ChannelConnector implements HttpChannelConnector {
5454
55+ private final HttpClientOptions options ;
5556 private final HttpClientMetrics clientMetrics ;
5657 private final NetClientInternal netClient ;
5758
5859 public Http1xOrH2ChannelConnector (NetClientInternal netClient ,
60+ HttpClientOptions options ,
5961 HttpClientMetrics clientMetrics ) {
62+
63+ if (!options .isKeepAlive () && options .isPipelining ()) {
64+ throw new IllegalStateException ("Cannot have pipelining with no keep alive" );
65+ }
66+ List <HttpVersion > alpnVersions = options .getAlpnVersions ();
67+ if (alpnVersions == null || alpnVersions .isEmpty ()) {
68+ if (options .getProtocolVersion () == HttpVersion .HTTP_2 ) {
69+ options .setAlpnVersions (List .of (HttpVersion .HTTP_2 , HttpVersion .HTTP_1_1 ));
70+ } else {
71+ options .setAlpnVersions (List .of (options .getProtocolVersion ()));
72+ }
73+ }
74+
6075 this .clientMetrics = clientMetrics ;
76+ this .options = options ;
6177 this .netClient = netClient ;
6278 }
6379
64- private Http2ClientChannelInitializer http2Initializer (HttpClientOptions options ) {
80+ public NetClientInternal netClient () {
81+ return netClient ;
82+ }
83+
84+ private Http2ClientChannelInitializer http2Initializer () {
6585 if (options .getHttp2MultiplexImplementation ()) {
6686 return new Http2MultiplexClientChannelInitializer (
6787 HttpUtils .fromVertxSettings (options .getInitialSettings ()),
@@ -81,14 +101,14 @@ private void connect(ContextInternal context, HttpConnectParams params, HostAndP
81101 if (authority != null ) {
82102 connectOptions .setHost (authority .host ());
83103 connectOptions .setPort (authority .port ());
84- if (params .ssl && params . options .isForceSni ()) {
104+ if (params .ssl && options .isForceSni ()) {
85105 connectOptions .setSniServerName (authority .host ());
86106 }
87107 }
88108 connectOptions .setSsl (params .ssl );
89109 if (params .ssl ) {
90110 if (params .sslOptions != null ) {
91- connectOptions .setSslOptions (params .sslOptions .copy ().setUseAlpn (params . useAlpn ));
111+ connectOptions .setSslOptions (params .sslOptions .copy ().setUseAlpn (options . isUseAlpn () ));
92112 } else {
93113 connectOptions .setSslOptions (new ClientSSLOptions ().setHostnameVerificationAlgorithm ("HTTPS" ));
94114 }
@@ -117,40 +137,45 @@ public Future<HttpClientConnection> wrap(ContextInternal context, HttpConnectPar
117137 Channel ch = so .channelHandlerContext ().channel ();
118138 if (params .ssl ) {
119139 String protocol = so .applicationLayerProtocol ();
120- if (params . useAlpn ) {
140+ if (options . isUseAlpn () ) {
121141 if ("h2" .equals (protocol )) {
122- applyHttp2ConnectionOptions (ch .pipeline (), params . options );
123- Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer (params . options );
142+ applyHttp2ConnectionOptions (ch .pipeline ());
143+ Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer ();
124144 http2ChannelInitializer .http2Connected (context , authority , metric , maxLifetimeMillis , ch , metrics , promise );
125145 } else {
126- applyHttp1xConnectionOptions (ch .pipeline (), params . options );
146+ applyHttp1xConnectionOptions (ch .pipeline ());
127147 HttpVersion fallbackProtocol = "http/1.0" .equals (protocol ) ?
128148 HttpVersion .HTTP_1_0 : HttpVersion .HTTP_1_1 ;
129- http1xConnected (params . options , fallbackProtocol , server , authority , true , context , metric , maxLifetimeMillis , ch , metrics , promise );
149+ http1xConnected (fallbackProtocol , server , authority , true , context , metric , maxLifetimeMillis , ch , metrics , promise );
130150 }
131151 } else {
132- applyHttp1xConnectionOptions (ch .pipeline (), params . options );
133- http1xConnected (params . options , params . version , server , authority , true , context , metric , maxLifetimeMillis , ch , metrics , promise );
152+ applyHttp1xConnectionOptions (ch .pipeline ());
153+ http1xConnected (options . getProtocolVersion () , server , authority , true , context , metric , maxLifetimeMillis , ch , metrics , promise );
134154 }
135155 } else {
136- if (params . version == HttpVersion .HTTP_2 ) {
137- if (params . options .isHttp2ClearTextUpgrade ()) {
138- applyHttp1xConnectionOptions (pipeline , params . options );
139- http1xConnected (params . options , params . version , server , authority , false , context , metric , maxLifetimeMillis , ch , metrics , promise );
156+ if (options . getProtocolVersion () == HttpVersion .HTTP_2 ) {
157+ if (options .isHttp2ClearTextUpgrade ()) {
158+ applyHttp1xConnectionOptions (pipeline );
159+ http1xConnected (options . getProtocolVersion () , server , authority , false , context , metric , maxLifetimeMillis , ch , metrics , promise );
140160 } else {
141- applyHttp2ConnectionOptions (pipeline , params . options );
142- Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer (params . options );
161+ applyHttp2ConnectionOptions (pipeline );
162+ Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer ();
143163 http2ChannelInitializer .http2Connected (context , authority , metric , maxLifetimeMillis , ch , metrics , promise );
144164 }
145165 } else {
146- applyHttp1xConnectionOptions (pipeline , params . options );
147- http1xConnected (params . options , params . version , server , authority , false , context , metric , maxLifetimeMillis , ch , metrics , promise );
166+ applyHttp1xConnectionOptions (pipeline );
167+ http1xConnected (options . getProtocolVersion () , server , authority , false , context , metric , maxLifetimeMillis , ch , metrics , promise );
148168 }
149169 }
150170 return promise .future ();
151171 }
152172
153173 public Future <HttpClientConnection > httpConnect (ContextInternal context , SocketAddress server , HostAndPort authority , HttpConnectParams params , long maxLifetimeMillis , ClientMetrics <?, ?, ?> metrics ) {
174+
175+ if (!options .isUseAlpn () && params .ssl && this .options .getProtocolVersion () == HttpVersion .HTTP_2 ) {
176+ return context .failedFuture ("Must enable ALPN when using H2" );
177+ }
178+
154179 Promise <NetSocket > promise = context .promise ();
155180 Future <NetSocket > future = promise .future ();
156181 // We perform the compose operation before calling connect to be sure that the composition happens
@@ -160,7 +185,7 @@ public Future<HttpClientConnection> httpConnect(ContextInternal context, SocketA
160185 return ret ;
161186 }
162187
163- private void applyHttp2ConnectionOptions (ChannelPipeline pipeline , HttpClientOptions options ) {
188+ private void applyHttp2ConnectionOptions (ChannelPipeline pipeline ) {
164189 int idleTimeout = options .getIdleTimeout ();
165190 int readIdleTimeout = options .getReadIdleTimeout ();
166191 int writeIdleTimeout = options .getWriteIdleTimeout ();
@@ -169,7 +194,7 @@ private void applyHttp2ConnectionOptions(ChannelPipeline pipeline, HttpClientOpt
169194 }
170195 }
171196
172- private void applyHttp1xConnectionOptions (ChannelPipeline pipeline , HttpClientOptions options ) {
197+ private void applyHttp1xConnectionOptions (ChannelPipeline pipeline ) {
173198 int idleTimeout = options .getIdleTimeout ();
174199 int readIdleTimeout = options .getReadIdleTimeout ();
175200 int writeIdleTimeout = options .getWriteIdleTimeout ();
@@ -191,8 +216,7 @@ private void applyHttp1xConnectionOptions(ChannelPipeline pipeline, HttpClientOp
191216 }
192217 }
193218
194- private void http1xConnected (HttpClientOptions options ,
195- HttpVersion version ,
219+ private void http1xConnected (HttpVersion version ,
196220 SocketAddress server ,
197221 HostAndPort authority ,
198222 boolean ssl ,
@@ -212,7 +236,7 @@ private void http1xConnected(HttpClientOptions options,
212236 });
213237 clientHandler .addHandler (conn -> {
214238 if (upgrade ) {
215- Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer (options );
239+ Http2ClientChannelInitializer http2ChannelInitializer = http2Initializer ();
216240 Http2UpgradeClientConnection .Http2ChannelUpgrade channelUpgrade = http2ChannelInitializer .channelUpgrade (conn , maxLifetimeMillis , metrics );
217241 boolean preflightRequest = options .isHttp2ClearTextUpgradeWithPreflightRequest ();
218242 if (preflightRequest ) {
0 commit comments