1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.testing.nio;
29
30 import static org.hamcrest.MatcherAssert.assertThat;
31
32 import java.io.IOException;
33 import java.net.InetSocketAddress;
34 import java.util.concurrent.Future;
35
36 import org.apache.hc.core5.http.ContentType;
37 import org.apache.hc.core5.http.HeaderElements;
38 import org.apache.hc.core5.http.HttpException;
39 import org.apache.hc.core5.http.HttpHeaders;
40 import org.apache.hc.core5.http.HttpHost;
41 import org.apache.hc.core5.http.HttpRequest;
42 import org.apache.hc.core5.http.HttpResponse;
43 import org.apache.hc.core5.http.HttpStatus;
44 import org.apache.hc.core5.http.Message;
45 import org.apache.hc.core5.http.Method;
46 import org.apache.hc.core5.http.URIScheme;
47 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
48 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
49 import org.apache.hc.core5.http.impl.bootstrap.StandardFilter;
50 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
51 import org.apache.hc.core5.http.nio.AsyncFilterChain;
52 import org.apache.hc.core5.http.nio.AsyncPushProducer;
53 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
54 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
55 import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
56 import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
57 import org.apache.hc.core5.http.protocol.UriPatternMatcher;
58 import org.apache.hc.core5.reactor.IOReactorConfig;
59 import org.apache.hc.core5.reactor.ListenerEndpoint;
60 import org.apache.hc.core5.testing.nio.extension.HttpAsyncRequesterResource;
61 import org.apache.hc.core5.testing.nio.extension.HttpAsyncServerResource;
62 import org.apache.hc.core5.util.Timeout;
63 import org.hamcrest.CoreMatchers;
64 import org.junit.jupiter.api.Test;
65 import org.junit.jupiter.api.extension.RegisterExtension;
66
67 public abstract class Http1CoreTransportTest extends HttpCoreTransportTest {
68
69 private static final Timeout TIMEOUT = Timeout.ofMinutes(1);
70
71 @RegisterExtension
72 private final HttpAsyncServerResource serverResource;
73 @RegisterExtension
74 private final HttpAsyncRequesterResource clientResource;
75
76 public Http1CoreTransportTest(final URIScheme scheme) {
77 super(scheme);
78 this.serverResource = new HttpAsyncServerResource(bootstrap -> bootstrap
79 .setIOReactorConfig(
80 IOReactorConfig.custom()
81 .setSoTimeout(TIMEOUT)
82 .build())
83 .setLookupRegistry(new UriPatternMatcher<>())
84 .register("*", () -> new EchoHandler(2048))
85 .addFilterBefore(StandardFilter.MAIN_HANDLER.name(), "no-keepalive", (request, entityDetails, context, responseTrigger, chain) ->
86 chain.proceed(request, entityDetails, context, new AsyncFilterChain.ResponseTrigger() {
87
88 @Override
89 public void sendInformation(
90 final HttpResponse response) throws HttpException, IOException {
91 responseTrigger.sendInformation(response);
92 }
93
94 @Override
95 public void submitResponse(
96 final HttpResponse response,
97 final AsyncEntityProducer entityProducer) throws HttpException, IOException {
98 if (request.getPath().startsWith("/no-keep-alive")) {
99 response.setHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
100 }
101 responseTrigger.submitResponse(response, entityProducer);
102 }
103
104 @Override
105 public void pushPromise(
106 final HttpRequest promise,
107 final AsyncPushProducer responseProducer) throws HttpException, IOException {
108 responseTrigger.pushPromise(promise, responseProducer);
109 }
110
111 }))
112 );
113 this.clientResource = new HttpAsyncRequesterResource(bootstrap -> bootstrap
114 .setIOReactorConfig(IOReactorConfig.custom()
115 .setSoTimeout(TIMEOUT)
116 .build())
117 );
118 }
119
120 @Override
121 HttpAsyncServer serverStart() throws IOException {
122 return serverResource.start();
123 }
124
125 @Override
126 HttpAsyncRequester clientStart() {
127 return clientResource.start();
128 }
129
130 @Test
131 public void testSequentialRequestsNonPersistentConnection() throws Exception {
132 final HttpAsyncServer server = serverResource.start();
133 final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
134 final ListenerEndpoint listener = future.get();
135 final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
136 final HttpAsyncRequester requester = clientResource.start();
137
138 final HttpHost target = new HttpHost(scheme.id, "localhost", address.getPort());
139 final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
140 new BasicRequestProducer(Method.POST, target, "/no-keep-alive/stuff",
141 new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
142 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
143 final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
144 assertThat(message1, CoreMatchers.notNullValue());
145 final HttpResponse response1 = message1.getHead();
146 assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
147 final String body1 = message1.getBody();
148 assertThat(body1, CoreMatchers.equalTo("some stuff"));
149
150 final Future<Message<HttpResponse, String>> resultFuture2 = requester.execute(
151 new BasicRequestProducer(Method.POST, target, "/no-keep-alive/other-stuff",
152 new StringAsyncEntityProducer("some other stuff", ContentType.TEXT_PLAIN)),
153 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
154 final Message<HttpResponse, String> message2 = resultFuture2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
155 assertThat(message2, CoreMatchers.notNullValue());
156 final HttpResponse response2 = message2.getHead();
157 assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
158 final String body2 = message2.getBody();
159 assertThat(body2, CoreMatchers.equalTo("some other stuff"));
160
161 final Future<Message<HttpResponse, String>> resultFuture3 = requester.execute(
162 new BasicRequestProducer(Method.POST, target, "/no-keep-alive/more-stuff",
163 new StringAsyncEntityProducer("some more stuff", ContentType.TEXT_PLAIN)),
164 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
165 final Message<HttpResponse, String> message3 = resultFuture3.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
166 assertThat(message3, CoreMatchers.notNullValue());
167 final HttpResponse response3 = message3.getHead();
168 assertThat(response3.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
169 final String body3 = message3.getBody();
170 assertThat(body3, CoreMatchers.equalTo("some more stuff"));
171 }
172
173 }