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