View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.testing.nio;
29  
30  import static org.hamcrest.MatcherAssert.assertThat;
31  
32  import java.net.InetSocketAddress;
33  import java.util.concurrent.Future;
34  
35  import org.apache.hc.core5.http.ContentType;
36  import org.apache.hc.core5.http.HttpHost;
37  import org.apache.hc.core5.http.HttpResponse;
38  import org.apache.hc.core5.http.HttpStatus;
39  import org.apache.hc.core5.http.HttpVersion;
40  import org.apache.hc.core5.http.Message;
41  import org.apache.hc.core5.http.Method;
42  import org.apache.hc.core5.http.URIScheme;
43  import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
44  import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
45  import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
46  import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
47  import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
48  import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
49  import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
50  import org.apache.hc.core5.http2.HttpVersionPolicy;
51  import org.apache.hc.core5.reactor.IOReactorConfig;
52  import org.apache.hc.core5.reactor.ListenerEndpoint;
53  import org.apache.hc.core5.testing.nio.extension.H2AsyncRequesterResource;
54  import org.apache.hc.core5.testing.nio.extension.H2AsyncServerResource;
55  import org.apache.hc.core5.util.Timeout;
56  import org.hamcrest.CoreMatchers;
57  import org.junit.jupiter.api.Test;
58  import org.junit.jupiter.api.extension.RegisterExtension;
59  
60  public class H2ProtocolNegotiationTest {
61  
62      private static final Timeout TIMEOUT = Timeout.ofMinutes(1);
63  
64      @RegisterExtension
65      private final H2AsyncServerResource serverResource;
66      @RegisterExtension
67      private final H2AsyncRequesterResource clientResource;
68  
69      public H2ProtocolNegotiationTest() {
70          this.serverResource = new H2AsyncServerResource(bootstrap -> bootstrap
71                  .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
72                  .setIOReactorConfig(
73                          IOReactorConfig.custom()
74                                  .setSoTimeout(TIMEOUT)
75                                  .build())
76                  .register("*", () -> new EchoHandler(2048))
77          );
78          this.clientResource = new H2AsyncRequesterResource(bootstrap -> bootstrap
79                  .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
80                  .setIOReactorConfig(IOReactorConfig.custom()
81                          .setSoTimeout(TIMEOUT)
82                          .build())
83          );
84      }
85  
86      @Test
87      public void testForceHttp1() throws Exception {
88          final HttpAsyncServer server = serverResource.start();
89          final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
90          final ListenerEndpoint listener = future.get();
91          final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
92          final HttpAsyncRequester requester = clientResource.start();
93  
94          final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
95          final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_1, null);
96          final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
97  
98          final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
99                  new BasicRequestProducer(Method.POST, target, "/stuff",
100                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
101                 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
102         final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
103         assertThat(message1, CoreMatchers.notNullValue());
104         final HttpResponse response1 = message1.getHead();
105         assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
106         assertThat(response1.getVersion(), CoreMatchers.equalTo(HttpVersion.HTTP_1_1));
107     }
108 
109     @Test
110     public void testForceHttp2() throws Exception {
111         final HttpAsyncServer server = serverResource.start();
112         final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
113         final ListenerEndpoint listener = future.get();
114         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
115         final HttpAsyncRequester requester = clientResource.start();
116 
117         final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
118         final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_2, null);
119         final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
120 
121         final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
122                 new BasicRequestProducer(Method.POST, target, "/stuff",
123                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
124                 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
125         final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
126         assertThat(message1, CoreMatchers.notNullValue());
127         final HttpResponse response1 = message1.getHead();
128         assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
129         assertThat(response1.getVersion(), CoreMatchers.equalTo(HttpVersion.HTTP_2));
130     }
131 
132     @Test
133     public void testNegotiateProtocol() throws Exception {
134         final HttpAsyncServer server = serverResource.start();
135         final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
136         final ListenerEndpoint listener = future.get();
137         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
138         final HttpAsyncRequester requester = clientResource.start();
139 
140         final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
141         final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.NEGOTIATE, null);
142         final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
143 
144         final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
145                 new BasicRequestProducer(Method.POST, target, "/stuff",
146                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
147                 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
148         final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
149         assertThat(message1, CoreMatchers.notNullValue());
150         final HttpResponse response1 = message1.getHead();
151         assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
152         assertThat(response1.getVersion(), CoreMatchers.equalTo(HttpVersion.HTTP_2));
153     }
154 
155 }