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