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 package org.apache.hc.client5.testing.async;
28
29 import static org.hamcrest.MatcherAssert.assertThat;
30
31 import java.net.InetSocketAddress;
32 import java.net.URI;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.Future;
35
36 import org.apache.hc.client5.http.CircularRedirectException;
37 import org.apache.hc.client5.http.RedirectException;
38 import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
39 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
40 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
41 import org.apache.hc.client5.http.config.RequestConfig;
42 import org.apache.hc.client5.http.cookie.BasicCookieStore;
43 import org.apache.hc.client5.http.cookie.CookieStore;
44 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
45 import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
46 import org.apache.hc.client5.http.protocol.HttpClientContext;
47 import org.apache.hc.client5.testing.OldPathRedirectResolver;
48 import org.apache.hc.client5.testing.SSLTestContexts;
49 import org.apache.hc.client5.testing.redirect.Redirect;
50 import org.apache.hc.core5.function.Decorator;
51 import org.apache.hc.core5.http.ContentType;
52 import org.apache.hc.core5.http.Header;
53 import org.apache.hc.core5.http.HttpException;
54 import org.apache.hc.core5.http.HttpHost;
55 import org.apache.hc.core5.http.HttpRequest;
56 import org.apache.hc.core5.http.HttpResponse;
57 import org.apache.hc.core5.http.HttpStatus;
58 import org.apache.hc.core5.http.HttpVersion;
59 import org.apache.hc.core5.http.ProtocolException;
60 import org.apache.hc.core5.http.URIScheme;
61 import org.apache.hc.core5.http.config.Http1Config;
62 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
63 import org.apache.hc.core5.http.protocol.HttpCoreContext;
64 import org.apache.hc.core5.http2.config.H2Config;
65 import org.apache.hc.core5.net.URIBuilder;
66 import org.apache.hc.core5.reactor.IOReactorConfig;
67 import org.apache.hc.core5.testing.nio.H2TestServer;
68 import org.apache.hc.core5.util.TimeValue;
69 import org.hamcrest.CoreMatchers;
70 import org.junit.jupiter.api.Assertions;
71 import org.junit.jupiter.api.Test;
72
73 public abstract class AbstractHttpAsyncRedirectsTest <T extends CloseableHttpAsyncClient> extends AbstractIntegrationTestBase {
74
75 private final HttpVersion version;
76
77 public AbstractHttpAsyncRedirectsTest(final URIScheme scheme, final HttpVersion version) {
78 super(scheme);
79 this.version = version;
80 }
81
82 abstract protected H2TestServer startServer(final Decorator<AsyncServerExchangeHandler> exchangeHandlerDecorator) throws Exception;
83
84 protected H2TestServer startServer() throws Exception {
85 return startServer(null);
86 }
87
88 abstract protected T startClient() throws Exception;
89
90 @Test
91 public void testBasicRedirect300() throws Exception {
92 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
93 exchangeHandler,
94 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES)));
95
96 server.register("/random/*", AsyncRandomHandler::new);
97 final HttpHost target = targetHost();
98
99 final T client = startClient();
100
101 final HttpClientContext context = HttpClientContext.create();
102 final Future<SimpleHttpResponse> future = client.execute(
103 SimpleRequestBuilder.get()
104 .setHttpHost(target)
105 .setPath("/oldlocation/")
106 .build(), context, null);
107 final HttpResponse response = future.get();
108 Assertions.assertNotNull(response);
109
110 final HttpRequest request = context.getRequest();
111
112 Assertions.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getCode());
113 Assertions.assertEquals("/oldlocation/", request.getRequestUri());
114 }
115
116 @Test
117 public void testBasicRedirect301() throws Exception {
118 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
119 exchangeHandler,
120 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY)));
121 server.register("/random/*", AsyncRandomHandler::new);
122 final HttpHost target = targetHost();
123
124 final T client = startClient();
125
126 final HttpClientContext context = HttpClientContext.create();
127 final Future<SimpleHttpResponse> future = client.execute(
128 SimpleRequestBuilder.get()
129 .setHttpHost(target)
130 .setPath("/oldlocation/100")
131 .build(), context, null);
132 final HttpResponse response = future.get();
133 Assertions.assertNotNull(response);
134
135 final HttpRequest request = context.getRequest();
136
137 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
138 Assertions.assertEquals("/random/100", request.getRequestUri());
139 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
140 }
141
142 @Test
143 public void testBasicRedirect302() throws Exception {
144 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
145 exchangeHandler,
146 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY)));
147 server.register("/random/*", AsyncRandomHandler::new);
148 final HttpHost target = targetHost();
149
150 final T client = startClient();
151
152 final HttpClientContext context = HttpClientContext.create();
153 final Future<SimpleHttpResponse> future = client.execute(
154 SimpleRequestBuilder.get()
155 .setHttpHost(target)
156 .setPath("/oldlocation/123")
157 .build(), context, null);
158 final HttpResponse response = future.get();
159 Assertions.assertNotNull(response);
160
161 final HttpRequest request = context.getRequest();
162
163 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
164 Assertions.assertEquals("/random/123", request.getRequestUri());
165 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
166 }
167
168 @Test
169 public void testBasicRedirect302NoLocation() throws Exception {
170 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
171 exchangeHandler,
172 requestUri -> {
173 final String path = requestUri.getPath();
174 if (path.startsWith("/oldlocation")) {
175 return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, null);
176 }
177 return null;
178 }));
179 server.register("/random/*", AsyncRandomHandler::new);
180 final HttpHost target = targetHost();
181
182 final T client = startClient();
183
184 final HttpClientContext context = HttpClientContext.create();
185 final Future<SimpleHttpResponse> future = client.execute(
186 SimpleRequestBuilder.get()
187 .setHttpHost(target)
188 .setPath("/oldlocation/100")
189 .build(), context, null);
190 final HttpResponse response = future.get();
191 Assertions.assertNotNull(response);
192
193 final HttpRequest request = context.getRequest();
194 Assertions.assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getCode());
195 Assertions.assertEquals("/oldlocation/100", request.getRequestUri());
196 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
197 }
198
199 @Test
200 public void testBasicRedirect303() throws Exception {
201 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
202 exchangeHandler,
203 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_SEE_OTHER)));
204 server.register("/random/*", AsyncRandomHandler::new);
205 final HttpHost target = targetHost();
206
207 final T client = startClient();
208
209 final HttpClientContext context = HttpClientContext.create();
210 final Future<SimpleHttpResponse> future = client.execute(
211 SimpleRequestBuilder.get()
212 .setHttpHost(target)
213 .setPath("/oldlocation/123")
214 .build(), context, null);
215 final HttpResponse response = future.get();
216 Assertions.assertNotNull(response);
217
218 final HttpRequest request = context.getRequest();
219
220 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
221 Assertions.assertEquals("/random/123", request.getRequestUri());
222 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
223 }
224
225 @Test
226 public void testBasicRedirect304() throws Exception {
227 final H2TestServer server = startServer();
228 server.register("/random/*", AsyncRandomHandler::new);
229 server.register("/oldlocation/*", () -> new AbstractSimpleServerExchangeHandler() {
230
231 @Override
232 protected SimpleHttpResponse handle(final SimpleHttpRequest request,
233 final HttpCoreContext context) throws HttpException {
234 return SimpleHttpResponse.create(HttpStatus.SC_NOT_MODIFIED, (String) null);
235 }
236 });
237 final HttpHost target = targetHost();
238
239 final T client = startClient();
240
241 final HttpClientContext context = HttpClientContext.create();
242 final Future<SimpleHttpResponse> future = client.execute(
243 SimpleRequestBuilder.get()
244 .setHttpHost(target)
245 .setPath("/oldlocation/")
246 .build(), context, null);
247 final HttpResponse response = future.get();
248 Assertions.assertNotNull(response);
249
250 final HttpRequest request = context.getRequest();
251
252 Assertions.assertEquals(HttpStatus.SC_NOT_MODIFIED, response.getCode());
253 Assertions.assertEquals("/oldlocation/", request.getRequestUri());
254 }
255
256 @Test
257 public void testBasicRedirect305() throws Exception {
258 final H2TestServer server = startServer();
259 server.register("/random/*", AsyncRandomHandler::new);
260 server.register("/oldlocation/*", () -> new AbstractSimpleServerExchangeHandler() {
261
262 @Override
263 protected SimpleHttpResponse handle(final SimpleHttpRequest request,
264 final HttpCoreContext context) throws HttpException {
265 return SimpleHttpResponse.create(HttpStatus.SC_USE_PROXY, (String) null);
266 }
267 });
268 final HttpHost target = targetHost();
269
270 final T client = startClient();
271
272 final HttpClientContext context = HttpClientContext.create();
273 final Future<SimpleHttpResponse> future = client.execute(
274 SimpleRequestBuilder.get()
275 .setHttpHost(target)
276 .setPath("/oldlocation/")
277 .build(), context, null);
278 final HttpResponse response = future.get();
279 Assertions.assertNotNull(response);
280
281 final HttpRequest request = context.getRequest();
282
283 Assertions.assertEquals(HttpStatus.SC_USE_PROXY, response.getCode());
284 Assertions.assertEquals("/oldlocation/", request.getRequestUri());
285 }
286
287 @Test
288 public void testBasicRedirect307() throws Exception {
289 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
290 exchangeHandler,
291 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_TEMPORARY_REDIRECT)));
292 server.register("/random/*", AsyncRandomHandler::new);
293 final HttpHost target = targetHost();
294
295 final T client = startClient();
296
297 final HttpClientContext context = HttpClientContext.create();
298 final Future<SimpleHttpResponse> future = client.execute(
299 SimpleRequestBuilder.get()
300 .setHttpHost(target)
301 .setPath("/oldlocation/123")
302 .build(), context, null);
303 final HttpResponse response = future.get();
304 Assertions.assertNotNull(response);
305
306 final HttpRequest request = context.getRequest();
307
308 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
309 Assertions.assertEquals("/random/123", request.getRequestUri());
310 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
311 }
312
313 @Test
314 public void testMaxRedirectCheck() throws Exception {
315 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
316 exchangeHandler,
317 new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/",
318 HttpStatus.SC_MOVED_TEMPORARILY)));
319 server.register("/random/*", AsyncRandomHandler::new);
320 final HttpHost target = targetHost();
321
322 final T client = startClient();
323
324 final RequestConfig config = RequestConfig.custom()
325 .setCircularRedirectsAllowed(true)
326 .setMaxRedirects(5).build();
327 final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> {
328 final Future<SimpleHttpResponse> future = client.execute(SimpleRequestBuilder.get()
329 .setHttpHost(target)
330 .setPath("/circular-oldlocation/")
331 .setRequestConfig(config)
332 .build(), null);
333 future.get();
334 });
335 assertThat(exception.getCause(), CoreMatchers.instanceOf(RedirectException.class));
336 }
337
338 @Test
339 public void testCircularRedirect() throws Exception {
340 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
341 exchangeHandler,
342 new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/",
343 HttpStatus.SC_MOVED_TEMPORARILY)));
344 server.register("/random/*", AsyncRandomHandler::new);
345 final HttpHost target = targetHost();
346
347 final T client = startClient();
348
349 final RequestConfig config = RequestConfig.custom()
350 .setCircularRedirectsAllowed(false)
351 .build();
352 final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> {
353 final Future<SimpleHttpResponse> future = client.execute(
354 SimpleRequestBuilder.get()
355 .setHttpHost(target)
356 .setPath("/circular-oldlocation/")
357 .setRequestConfig(config)
358 .build(), null);
359 future.get();
360 });
361 assertThat(exception.getCause(), CoreMatchers.instanceOf(CircularRedirectException.class));
362 }
363
364 @Test
365 public void testPostRedirect() throws Exception {
366 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
367 exchangeHandler,
368 new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_TEMPORARY_REDIRECT)));
369
370 server.register("/echo/*", AsyncEchoHandler::new);
371 final HttpHost target = targetHost();
372
373 final T client = startClient();
374
375 final HttpClientContext context = HttpClientContext.create();
376 final Future<SimpleHttpResponse> future = client.execute(
377 SimpleRequestBuilder.post()
378 .setHttpHost(target)
379 .setPath("/oldlocation/stuff")
380 .setBody("stuff", ContentType.TEXT_PLAIN)
381 .build(), context, null);
382 final HttpResponse response = future.get();
383 Assertions.assertNotNull(response);
384
385 final HttpRequest request = context.getRequest();
386
387 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
388 Assertions.assertEquals("/echo/stuff", request.getRequestUri());
389 Assertions.assertEquals("POST", request.getMethod());
390 }
391
392 @Test
393 public void testPostRedirectSeeOther() throws Exception {
394 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
395 exchangeHandler,
396 new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_SEE_OTHER)));
397
398 server.register("/echo/*", AsyncEchoHandler::new);
399 final HttpHost target = targetHost();
400
401 final T client = startClient();
402
403 final HttpClientContext context = HttpClientContext.create();
404 final Future<SimpleHttpResponse> future = client.execute(
405 SimpleRequestBuilder.post()
406 .setHttpHost(target)
407 .setPath("/oldlocation/stuff")
408 .setBody("stuff", ContentType.TEXT_PLAIN)
409 .build(), context, null);
410 final HttpResponse response = future.get();
411 Assertions.assertNotNull(response);
412
413 final HttpRequest request = context.getRequest();
414
415 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
416 Assertions.assertEquals("/echo/stuff", request.getRequestUri());
417 Assertions.assertEquals("GET", request.getMethod());
418 }
419
420 @Test
421 public void testRelativeRedirect() throws Exception {
422 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
423 exchangeHandler,
424 requestUri -> {
425 final String path = requestUri.getPath();
426 if (path.startsWith("/oldlocation")) {
427 return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "/random/100");
428
429 }
430 return null;
431 }));
432
433 server.register("/random/*", AsyncRandomHandler::new);
434 final HttpHost target = targetHost();
435
436 final T client = startClient();
437
438 final HttpClientContext context = HttpClientContext.create();
439
440 final Future<SimpleHttpResponse> future = client.execute(
441 SimpleRequestBuilder.get()
442 .setHttpHost(target)
443 .setPath("/oldlocation/stuff")
444 .build(), context, null);
445 final HttpResponse response = future.get();
446 Assertions.assertNotNull(response);
447
448 final HttpRequest request = context.getRequest();
449
450 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
451 Assertions.assertEquals("/random/100", request.getRequestUri());
452 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
453 }
454
455 @Test
456 public void testRelativeRedirect2() throws Exception {
457 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
458 exchangeHandler,
459 requestUri -> {
460 final String path = requestUri.getPath();
461 if (path.equals("/random/oldlocation")) {
462 return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "100");
463
464 }
465 return null;
466 }));
467
468 server.register("/random/*", AsyncRandomHandler::new);
469 final HttpHost target = targetHost();
470
471 final T client = startClient();
472
473 final HttpClientContext context = HttpClientContext.create();
474
475 final Future<SimpleHttpResponse> future = client.execute(
476 SimpleRequestBuilder.get()
477 .setHttpHost(target)
478 .setPath("/random/oldlocation")
479 .build(), context, null);
480 final HttpResponse response = future.get();
481 Assertions.assertNotNull(response);
482
483 final HttpRequest request = context.getRequest();
484
485 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
486 Assertions.assertEquals("/random/100", request.getRequestUri());
487 Assertions.assertEquals(target, new HttpHost(request.getScheme(), request.getAuthority()));
488 }
489
490 @Test
491 public void testRejectBogusRedirectLocation() throws Exception {
492 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
493 exchangeHandler,
494 requestUri -> {
495 final String path = requestUri.getPath();
496 if (path.equals("/oldlocation/")) {
497 return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "xxx://bogus");
498
499 }
500 return null;
501 }));
502 server.register("/random/*", AsyncRandomHandler::new);
503 final HttpHost target = targetHost();
504
505 final T client = startClient();
506
507 final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> {
508 final Future<SimpleHttpResponse> future = client.execute(
509 SimpleRequestBuilder.get()
510 .setHttpHost(target)
511 .setPath("/oldlocation/")
512 .build(), null);
513 future.get();
514 });
515 assertThat(exception.getCause(), CoreMatchers.instanceOf(HttpException.class));
516 }
517
518 @Test
519 public void testRejectInvalidRedirectLocation() throws Exception {
520 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
521 exchangeHandler,
522 requestUri -> {
523 final String path = requestUri.getPath();
524 if (path.equals("/oldlocation/")) {
525 return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "/newlocation/?p=I have spaces");
526
527 }
528 return null;
529 }));
530 server.register("/random/*", AsyncRandomHandler::new);
531 final HttpHost target = targetHost();
532
533 final T client = startClient();
534
535 final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> {
536 final Future<SimpleHttpResponse> future = client.execute(
537 SimpleRequestBuilder.get()
538 .setHttpHost(target)
539 .setPath("/oldlocation/")
540 .build(), null);
541 future.get();
542 });
543 assertThat(exception.getCause(), CoreMatchers.instanceOf(ProtocolException.class));
544 }
545
546 @Test
547 public void testRedirectWithCookie() throws Exception {
548 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
549 exchangeHandler,
550 new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY)));
551
552 final CookieStore cookieStore = new BasicCookieStore();
553 server.register("/random/*", AsyncRandomHandler::new);
554 final HttpHost target = targetHost();
555
556 final T client = startClient();
557
558 final HttpClientContext context = HttpClientContext.create();
559 context.setCookieStore(cookieStore);
560
561 final BasicClientCookie cookie = new BasicClientCookie("name", "value");
562 cookie.setDomain(target.getHostName());
563 cookie.setPath("/");
564
565 cookieStore.addCookie(cookie);
566
567 final Future<SimpleHttpResponse> future = client.execute(
568 SimpleRequestBuilder.get()
569 .setHttpHost(target)
570 .setPath("/oldlocation/100")
571 .build(), context, null);
572 final HttpResponse response = future.get();
573 Assertions.assertNotNull(response);
574
575 final HttpRequest request = context.getRequest();
576
577 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
578 Assertions.assertEquals("/random/100", request.getRequestUri());
579
580 final Header[] headers = request.getHeaders("Cookie");
581 Assertions.assertEquals(1, headers.length, "There can only be one (cookie)");
582 }
583
584 @Test
585 public void testCrossSiteRedirect() throws Exception {
586 final URIScheme scheme = scheme();
587 final H2TestServer secondServer = new H2TestServer(IOReactorConfig.DEFAULT,
588 scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null, null, null);
589 try {
590 secondServer.register("/random/*", AsyncRandomHandler::new);
591 final InetSocketAddress address2;
592 if (version.greaterEquals(HttpVersion.HTTP_2)) {
593 address2 = secondServer.start(H2Config.DEFAULT);
594 } else {
595 address2 = secondServer.start(Http1Config.DEFAULT);
596 }
597 final HttpHost redirectTarget = new HttpHost(scheme.name(), "localhost", address2.getPort());
598
599 final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator(
600 exchangeHandler,
601 requestUri -> {
602 final String path = requestUri.getPath();
603 if (path.equals("/oldlocation")) {
604 final URI location = new URIBuilder(requestUri)
605 .setHttpHost(redirectTarget)
606 .setPath("/random/100")
607 .build();
608 return new Redirect(HttpStatus.SC_MOVED_PERMANENTLY, location.toString());
609 }
610 return null;
611 }));
612
613 server.register("/random/*", AsyncRandomHandler::new);
614 final HttpHost target = targetHost();
615
616 final T client = startClient();
617
618 final HttpClientContext context = HttpClientContext.create();
619 final Future<SimpleHttpResponse> future = client.execute(
620 SimpleRequestBuilder.get()
621 .setHttpHost(target)
622 .setPath("/oldlocation")
623 .build(), context, null);
624 final HttpResponse response = future.get();
625 Assertions.assertNotNull(response);
626
627 final HttpRequest request = context.getRequest();
628
629 Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
630 Assertions.assertEquals("/random/100", request.getRequestUri());
631 Assertions.assertEquals(redirectTarget, new HttpHost(request.getScheme(), request.getAuthority()));
632 } finally {
633 secondServer.shutdown(TimeValue.ofSeconds(5));
634 }
635 }
636
637 }