|
116 | 116 | import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
|
117 | 117 | import org.apache.hc.core5.http.nio.support.AbstractServerExchangeHandler;
|
118 | 118 | import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder;
|
| 119 | +import org.apache.hc.core5.http.nio.support.AsyncResponseBuilder; |
119 | 120 | import org.apache.hc.core5.http.nio.support.BasicAsyncServerExpectationDecorator;
|
120 | 121 | import org.apache.hc.core5.http.nio.support.BasicRequestConsumer;
|
121 | 122 | import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
|
|
142 | 143 | import org.apache.hc.core5.util.TextUtils;
|
143 | 144 | import org.apache.hc.core5.util.Timeout;
|
144 | 145 | import org.hamcrest.CoreMatchers;
|
| 146 | +import org.hamcrest.MatcherAssert; |
| 147 | +import org.hamcrest.Matchers; |
145 | 148 | import org.junit.jupiter.api.Assertions;
|
146 | 149 | import org.junit.jupiter.api.Test;
|
147 | 150 | import org.junit.jupiter.api.extension.RegisterExtension;
|
@@ -2095,4 +2098,130 @@ public void releaseResources() {
|
2095 | 2098 | }
|
2096 | 2099 | }
|
2097 | 2100 |
|
| 2101 | + @Test |
| 2102 | + void testDelayedResponseSubmission() throws Exception { |
| 2103 | + final Http1TestServer server = resources.server(); |
| 2104 | + final Http1TestClient client = resources.client(); |
| 2105 | + |
| 2106 | + server.register("/hello", () -> new AbstractServerExchangeHandler<Message<HttpRequest, String>>() { |
| 2107 | + |
| 2108 | + private final Random random = new Random(System.currentTimeMillis()); |
| 2109 | + |
| 2110 | + @Override |
| 2111 | + protected AsyncRequestConsumer<Message<HttpRequest, String>> supplyConsumer( |
| 2112 | + final HttpRequest request, |
| 2113 | + final EntityDetails entityDetails, |
| 2114 | + final HttpContext context) throws HttpException { |
| 2115 | + return new BasicRequestConsumer<>(entityDetails != null ? new StringAsyncEntityConsumer() : null); |
| 2116 | + } |
| 2117 | + |
| 2118 | + @Override |
| 2119 | + protected void handle( |
| 2120 | + final Message<HttpRequest, String> requestMessage, |
| 2121 | + final AsyncServerRequestHandler.ResponseTrigger responseTrigger, |
| 2122 | + final HttpContext context) throws HttpException, IOException { |
| 2123 | + executorResource.getExecutorService().execute(() -> { |
| 2124 | + try { |
| 2125 | + Thread.sleep(random.nextInt(200)); |
| 2126 | + responseTrigger.submitResponse(AsyncResponseBuilder.create(HttpStatus.SC_OK) |
| 2127 | + .setEntity(new MultiLineEntityProducer("All is well", 100)) |
| 2128 | + .build(), |
| 2129 | + context); |
| 2130 | + Thread.sleep(random.nextInt(200)); |
| 2131 | + } catch (final Exception ignore) { |
| 2132 | + // ignore |
| 2133 | + } |
| 2134 | + }); |
| 2135 | + |
| 2136 | + } |
| 2137 | + |
| 2138 | + }); |
| 2139 | + final InetSocketAddress serverEndpoint = server.start(); |
| 2140 | + |
| 2141 | + client.start(); |
| 2142 | + |
| 2143 | + final Future<ClientSessionEndpoint> connectFuture = client.connect( |
| 2144 | + "localhost", serverEndpoint.getPort(), TIMEOUT); |
| 2145 | + final ClientSessionEndpoint streamEndpoint = connectFuture.get(); |
| 2146 | + |
| 2147 | + final Queue<Future<Message<HttpResponse, String>>> queue = new LinkedList<>(); |
| 2148 | + for (int i = 0; i < 5; i++) { |
| 2149 | + final HttpRequest request = new BasicHttpRequest(Method.GET, createRequestURI(serverEndpoint, "/hello")); |
| 2150 | + queue.add(streamEndpoint.execute( |
| 2151 | + new BasicRequestProducer(request, null), |
| 2152 | + new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null)); |
| 2153 | + } |
| 2154 | + while (!queue.isEmpty()) { |
| 2155 | + final Future<Message<HttpResponse, String>> future = queue.remove(); |
| 2156 | + final Message<HttpResponse, String> result = future.get(LONG_TIMEOUT.getDuration(), LONG_TIMEOUT.getTimeUnit()); |
| 2157 | + Assertions.assertNotNull(result); |
| 2158 | + final HttpResponse response = result.getHead(); |
| 2159 | + Assertions.assertNotNull(response); |
| 2160 | + Assertions.assertEquals(200, response.getCode()); |
| 2161 | + MatcherAssert.assertThat(result.getBody(), Matchers.startsWith("All is well")); |
| 2162 | + } |
| 2163 | + } |
| 2164 | + |
| 2165 | + @Test |
| 2166 | + void testDelayedResponseSubmissionNoResponseBody() throws Exception { |
| 2167 | + final Http1TestServer server = resources.server(); |
| 2168 | + final Http1TestClient client = resources.client(); |
| 2169 | + |
| 2170 | + server.register("/hello", () -> new AbstractServerExchangeHandler<Message<HttpRequest, String>>() { |
| 2171 | + |
| 2172 | + private final Random random = new Random(System.currentTimeMillis()); |
| 2173 | + |
| 2174 | + @Override |
| 2175 | + protected AsyncRequestConsumer<Message<HttpRequest, String>> supplyConsumer( |
| 2176 | + final HttpRequest request, |
| 2177 | + final EntityDetails entityDetails, |
| 2178 | + final HttpContext context) throws HttpException { |
| 2179 | + return new BasicRequestConsumer<>(entityDetails != null ? new StringAsyncEntityConsumer() : null); |
| 2180 | + } |
| 2181 | + |
| 2182 | + @Override |
| 2183 | + protected void handle( |
| 2184 | + final Message<HttpRequest, String> requestMessage, |
| 2185 | + final AsyncServerRequestHandler.ResponseTrigger responseTrigger, |
| 2186 | + final HttpContext context) throws HttpException, IOException { |
| 2187 | + executorResource.getExecutorService().execute(() -> { |
| 2188 | + try { |
| 2189 | + Thread.sleep(random.nextInt(200)); |
| 2190 | + responseTrigger.submitResponse(AsyncResponseBuilder.create(200) |
| 2191 | + .build(), |
| 2192 | + context); |
| 2193 | + Thread.sleep(random.nextInt(200)); |
| 2194 | + } catch (final Exception ignore) { |
| 2195 | + // ignore |
| 2196 | + } |
| 2197 | + }); |
| 2198 | + |
| 2199 | + } |
| 2200 | + |
| 2201 | + }); |
| 2202 | + final InetSocketAddress serverEndpoint = server.start(); |
| 2203 | + |
| 2204 | + client.start(); |
| 2205 | + |
| 2206 | + final Future<ClientSessionEndpoint> connectFuture = client.connect( |
| 2207 | + "localhost", serverEndpoint.getPort(), TIMEOUT); |
| 2208 | + final ClientSessionEndpoint streamEndpoint = connectFuture.get(); |
| 2209 | + |
| 2210 | + final Queue<Future<Message<HttpResponse, String>>> queue = new LinkedList<>(); |
| 2211 | + for (int i = 0; i < 5; i++) { |
| 2212 | + final HttpRequest request = new BasicHttpRequest(Method.GET, createRequestURI(serverEndpoint, "/hello")); |
| 2213 | + queue.add(streamEndpoint.execute( |
| 2214 | + new BasicRequestProducer(request, null), |
| 2215 | + new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null)); |
| 2216 | + } |
| 2217 | + while (!queue.isEmpty()) { |
| 2218 | + final Future<Message<HttpResponse, String>> future = queue.remove(); |
| 2219 | + final Message<HttpResponse, String> result = future.get(LONG_TIMEOUT.getDuration(), LONG_TIMEOUT.getTimeUnit()); |
| 2220 | + Assertions.assertNotNull(result); |
| 2221 | + final HttpResponse response = result.getHead(); |
| 2222 | + Assertions.assertNotNull(response); |
| 2223 | + Assertions.assertEquals(200, response.getCode()); |
| 2224 | + } |
| 2225 | + } |
| 2226 | + |
2098 | 2227 | }
|
0 commit comments