View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.testing.sync;
28  
29  import java.io.IOException;
30  import java.net.URI;
31  import java.net.URISyntaxException;
32  import java.util.Collections;
33  import java.util.Queue;
34  import java.util.concurrent.ConcurrentLinkedQueue;
35  
36  import org.apache.hc.client5.http.CircularRedirectException;
37  import org.apache.hc.client5.http.ClientProtocolException;
38  import org.apache.hc.client5.http.RedirectException;
39  import org.apache.hc.client5.http.classic.methods.HttpGet;
40  import org.apache.hc.client5.http.classic.methods.HttpPost;
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.cookie.BasicClientCookie;
45  import org.apache.hc.client5.http.protocol.HttpClientContext;
46  import org.apache.hc.client5.http.protocol.RedirectLocations;
47  import org.apache.hc.client5.testing.OldPathRedirectResolver;
48  import org.apache.hc.client5.testing.classic.RedirectingDecorator;
49  import org.apache.hc.client5.testing.redirect.Redirect;
50  import org.apache.hc.client5.testing.redirect.RedirectResolver;
51  import org.apache.hc.core5.function.Decorator;
52  import org.apache.hc.core5.http.ClassicHttpRequest;
53  import org.apache.hc.core5.http.ClassicHttpResponse;
54  import org.apache.hc.core5.http.Header;
55  import org.apache.hc.core5.http.HttpException;
56  import org.apache.hc.core5.http.HttpHeaders;
57  import org.apache.hc.core5.http.HttpHost;
58  import org.apache.hc.core5.http.HttpRequest;
59  import org.apache.hc.core5.http.HttpStatus;
60  import org.apache.hc.core5.http.ProtocolException;
61  import org.apache.hc.core5.http.io.HttpRequestHandler;
62  import org.apache.hc.core5.http.io.HttpServerRequestHandler;
63  import org.apache.hc.core5.http.io.entity.EntityUtils;
64  import org.apache.hc.core5.http.io.entity.StringEntity;
65  import org.apache.hc.core5.http.message.BasicHeader;
66  import org.apache.hc.core5.http.protocol.HttpContext;
67  import org.apache.hc.core5.net.URIBuilder;
68  import org.hamcrest.CoreMatchers;
69  import org.junit.Assert;
70  import org.junit.Test;
71  
72  /**
73   * Redirection test cases.
74   */
75  public class TestRedirects extends LocalServerTestBase {
76  
77      @Test
78      public void testBasicRedirect300() throws Exception {
79          final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
80  
81              @Override
82              public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
83                  return new RedirectingDecorator(
84                          requestHandler,
85                          new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES));
86              }
87  
88          });
89  
90          final HttpClientContext context = HttpClientContext.create();
91          final HttpGet httpget = new HttpGet("/oldlocation/100");
92          try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
93              final HttpRequest reqWrapper = context.getRequest();
94  
95              Assert.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getCode());
96              Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/oldlocation/100").build(),
97                      reqWrapper.getUri());
98  
99              final RedirectLocations redirects = context.getRedirectLocations();
100             Assert.assertNotNull(redirects);
101             Assert.assertEquals(0, redirects.size());
102 
103             EntityUtils.consume(response.getEntity());
104         }
105     }
106 
107     @Test
108     public void testBasicRedirect300NoKeepAlive() throws Exception {
109         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
110 
111             @Override
112             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
113                 return new RedirectingDecorator(
114                         requestHandler,
115                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES,
116                                 Redirect.ConnControl.CLOSE));
117             }
118 
119         });
120 
121         final HttpClientContext context = HttpClientContext.create();
122         final HttpGet httpget = new HttpGet("/oldlocation/100");
123         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
124             final HttpRequest reqWrapper = context.getRequest();
125 
126             Assert.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getCode());
127             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/oldlocation/100").build(),
128                     reqWrapper.getUri());
129 
130             final RedirectLocations redirects = context.getRedirectLocations();
131             Assert.assertNotNull(redirects);
132             Assert.assertEquals(0, redirects.size());
133 
134             EntityUtils.consume(response.getEntity());
135         }
136     }
137 
138     @Test
139     public void testBasicRedirect301() throws Exception {
140         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
141 
142             @Override
143             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
144                 return new RedirectingDecorator(
145                         requestHandler,
146                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY));
147             }
148 
149         });
150 
151         final HttpClientContext context = HttpClientContext.create();
152 
153         final HttpGet httpget = new HttpGet("/oldlocation/100");
154 
155         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
156             final HttpRequest reqWrapper = context.getRequest();
157 
158             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
159             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
160                     reqWrapper.getUri());
161 
162             final RedirectLocations redirects = context.getRedirectLocations();
163             Assert.assertNotNull(redirects);
164             Assert.assertEquals(1, redirects.size());
165 
166             final URI redirect = new URIBuilder().setHttpHost(target).setPath("/random/100").build();
167             Assert.assertTrue(redirects.contains(redirect));
168 
169             EntityUtils.consume(response.getEntity());
170         }
171     }
172 
173     @Test
174     public void testBasicRedirect302() throws Exception {
175         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
176 
177             @Override
178             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
179                 return new RedirectingDecorator(
180                         requestHandler,
181                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY));
182             }
183 
184         });
185 
186         final HttpClientContext context = HttpClientContext.create();
187 
188         final HttpGet httpget = new HttpGet("/oldlocation/50");
189 
190         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
191             final HttpRequest reqWrapper = context.getRequest();
192 
193             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
194             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/50").build(),
195                     reqWrapper.getUri());
196 
197             EntityUtils.consume(response.getEntity());
198         }
199     }
200 
201     @Test
202     public void testBasicRedirect302NoLocation() throws Exception {
203         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
204 
205             @Override
206             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
207                 return new RedirectingDecorator(
208                         requestHandler,
209                         new RedirectResolver() {
210 
211                             @Override
212                             public Redirect resolve(final URI requestUri) throws URISyntaxException {
213                                 final String path = requestUri.getPath();
214                                 if (path.startsWith("/oldlocation")) {
215                                     return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, null);
216                                 }
217                                 return null;
218                             }
219 
220                         });
221             }
222 
223         });
224 
225         final HttpClientContext context = HttpClientContext.create();
226 
227         final HttpGet httpget = new HttpGet("/oldlocation/100");
228 
229         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
230             final HttpRequest reqWrapper = context.getRequest();
231 
232             Assert.assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getCode());
233             Assert.assertEquals("/oldlocation/100", reqWrapper.getRequestUri());
234 
235             EntityUtils.consume(response.getEntity());
236         }
237     }
238 
239     @Test
240     public void testBasicRedirect303() throws Exception {
241         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
242 
243             @Override
244             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
245                 return new RedirectingDecorator(
246                         requestHandler,
247                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_SEE_OTHER));
248             }
249 
250         });
251 
252         final HttpClientContext context = HttpClientContext.create();
253 
254         final HttpGet httpget = new HttpGet("/oldlocation/123");
255 
256         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
257             final HttpRequest reqWrapper = context.getRequest();
258 
259             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
260             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/123").build(),
261                     reqWrapper.getUri());
262 
263             EntityUtils.consume(response.getEntity());
264         }
265     }
266 
267     @Test
268     public void testBasicRedirect304() throws Exception {
269         this.server.registerHandler("/oldlocation/*", new HttpRequestHandler() {
270 
271             @Override
272             public void handle(final ClassicHttpRequest request,
273                                final ClassicHttpResponse response,
274                                final HttpContext context) throws HttpException, IOException {
275                 response.setCode(HttpStatus.SC_NOT_MODIFIED);
276                 response.addHeader(HttpHeaders.LOCATION, "/random/100");
277             }
278 
279         });
280 
281         final HttpHost target = start();
282 
283         final HttpClientContext context = HttpClientContext.create();
284 
285         final HttpGet httpget = new HttpGet("/oldlocation/stuff");
286 
287         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
288             final HttpRequest reqWrapper = context.getRequest();
289 
290             Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, response.getCode());
291             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/oldlocation/stuff").build(),
292                     reqWrapper.getUri());
293 
294             final RedirectLocations redirects = context.getRedirectLocations();
295             Assert.assertNotNull(redirects);
296             Assert.assertEquals(0, redirects.size());
297 
298             EntityUtils.consume(response.getEntity());
299         }
300     }
301 
302     @Test
303     public void testBasicRedirect305() throws Exception {
304         this.server.registerHandler("/oldlocation/*", new HttpRequestHandler() {
305 
306             @Override
307             public void handle(final ClassicHttpRequest request,
308                                final ClassicHttpResponse response,
309                                final HttpContext context) throws HttpException, IOException {
310                 response.setCode(HttpStatus.SC_USE_PROXY);
311                 response.addHeader(HttpHeaders.LOCATION, "/random/100");
312             }
313 
314         });
315 
316         final HttpHost target = start();
317 
318         final HttpClientContext context = HttpClientContext.create();
319 
320         final HttpGet httpget = new HttpGet("/oldlocation/stuff");
321 
322         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
323             final HttpRequest reqWrapper = context.getRequest();
324 
325             Assert.assertEquals(HttpStatus.SC_USE_PROXY, response.getCode());
326             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/oldlocation/stuff").build(),
327                     reqWrapper.getUri());
328 
329             final RedirectLocations redirects = context.getRedirectLocations();
330             Assert.assertNotNull(redirects);
331             Assert.assertEquals(0, redirects.size());
332 
333             EntityUtils.consume(response.getEntity());
334         }
335     }
336 
337     @Test
338     public void testBasicRedirect307() throws Exception {
339         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
340 
341             @Override
342             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
343                 return new RedirectingDecorator(
344                         requestHandler,
345                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_TEMPORARY_REDIRECT));
346             }
347 
348         });
349 
350         final HttpClientContext context = HttpClientContext.create();
351 
352         final HttpGet httpget = new HttpGet("/oldlocation/123");
353 
354         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
355             final HttpRequest reqWrapper = context.getRequest();
356 
357             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
358             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/123").build(),
359                     reqWrapper.getUri());
360 
361             EntityUtils.consume(response.getEntity());
362         }
363     }
364 
365     @Test(expected = ClientProtocolException.class)
366     public void testMaxRedirectCheck() throws Exception {
367         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
368 
369             @Override
370             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
371                 return new RedirectingDecorator(
372                         requestHandler,
373                         new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/",
374                                 HttpStatus.SC_MOVED_TEMPORARILY));
375             }
376 
377         });
378 
379         final RequestConfig config = RequestConfig.custom()
380                 .setCircularRedirectsAllowed(true)
381                 .setMaxRedirects(5)
382                 .build();
383 
384         final HttpGet httpget = new HttpGet("/circular-oldlocation/123");
385         httpget.setConfig(config);
386         try {
387             this.httpclient.execute(target, httpget);
388         } catch (final ClientProtocolException e) {
389             Assert.assertTrue(e.getCause() instanceof RedirectException);
390             throw e;
391         }
392     }
393 
394     @Test(expected = ClientProtocolException.class)
395     public void testCircularRedirect() throws Exception {
396         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
397 
398             @Override
399             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
400                 return new RedirectingDecorator(
401                         requestHandler,
402                         new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/",
403                                 HttpStatus.SC_MOVED_TEMPORARILY));
404             }
405 
406         });
407 
408         final RequestConfig config = RequestConfig.custom()
409                 .setCircularRedirectsAllowed(false)
410                 .build();
411 
412         final HttpGet httpget = new HttpGet("/circular-oldlocation/123");
413         httpget.setConfig(config);
414         try {
415             this.httpclient.execute(target, httpget);
416         } catch (final ClientProtocolException e) {
417             Assert.assertTrue(e.getCause() instanceof CircularRedirectException);
418             throw e;
419         }
420     }
421 
422     @Test
423     public void testPostRedirectSeeOther() throws Exception {
424         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
425 
426             @Override
427             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
428                 return new RedirectingDecorator(
429                         requestHandler,
430                         new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_SEE_OTHER));
431             }
432 
433         });
434 
435         final HttpClientContext context = HttpClientContext.create();
436 
437         final HttpPost httppost = new HttpPost("/oldlocation/stuff");
438         httppost.setEntity(new StringEntity("stuff"));
439 
440         try (final ClassicHttpResponse response = this.httpclient.execute(target, httppost, context)) {
441             final HttpRequest reqWrapper = context.getRequest();
442 
443             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
444             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/echo/stuff").build(),
445                     reqWrapper.getUri());
446             Assert.assertEquals("GET", reqWrapper.getMethod());
447 
448             EntityUtils.consume(response.getEntity());
449         }
450 
451     }
452 
453     @Test
454     public void testRelativeRedirect() throws Exception {
455         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
456 
457             @Override
458             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
459                 return new RedirectingDecorator(
460                         requestHandler,
461                         new RedirectResolver() {
462 
463                             @Override
464                             public Redirect resolve(final URI requestUri) throws URISyntaxException {
465                                 final String path = requestUri.getPath();
466                                 if (path.startsWith("/oldlocation")) {
467                                     return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "/random/100");
468 
469                                 }
470                                 return null;
471                             }
472 
473                         });
474             }
475 
476         });
477         final HttpClientContext context = HttpClientContext.create();
478 
479         final HttpGet httpget = new HttpGet("/oldlocation/stuff");
480 
481         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
482             final HttpRequest reqWrapper = context.getRequest();
483 
484             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
485             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
486                     reqWrapper.getUri());
487 
488             EntityUtils.consume(response.getEntity());
489         }
490     }
491 
492     @Test
493     public void testRelativeRedirect2() throws Exception {
494         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
495 
496             @Override
497             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
498                 return new RedirectingDecorator(
499                         requestHandler,
500                         new RedirectResolver() {
501 
502                             @Override
503                             public Redirect resolve(final URI requestUri) throws URISyntaxException {
504                                 final String path = requestUri.getPath();
505                                 if (path.equals("/random/oldlocation")) {
506                                     return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "100");
507 
508                                 }
509                                 return null;
510                             }
511 
512                         });
513             }
514 
515         });
516 
517         final HttpClientContext context = HttpClientContext.create();
518 
519         final HttpGet httpget = new HttpGet("/random/oldlocation");
520 
521         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
522             final HttpRequest reqWrapper = context.getRequest();
523 
524             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
525             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
526                     reqWrapper.getUri());
527 
528             EntityUtils.consume(response.getEntity());
529         }
530 
531     }
532 
533     @Test(expected = ClientProtocolException.class)
534     public void testRejectBogusRedirectLocation() throws Exception {
535         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
536 
537             @Override
538             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
539                 return new RedirectingDecorator(
540                         requestHandler,
541                         new RedirectResolver() {
542 
543                             @Override
544                             public Redirect resolve(final URI requestUri) throws URISyntaxException {
545                                 final String path = requestUri.getPath();
546                                 if (path.equals("/oldlocation")) {
547                                     return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "xxx://bogus");
548 
549                                 }
550                                 return null;
551                             }
552 
553                         });
554             }
555 
556         });
557 
558         final HttpGet httpget = new HttpGet("/oldlocation");
559 
560         try {
561             this.httpclient.execute(target, httpget);
562         } catch (final ClientProtocolException ex) {
563             final Throwable cause = ex.getCause();
564             Assert.assertTrue(cause instanceof HttpException);
565             throw ex;
566         }
567     }
568 
569     @Test(expected = ClientProtocolException.class)
570     public void testRejectInvalidRedirectLocation() throws Exception {
571         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
572 
573             @Override
574             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
575                 return new RedirectingDecorator(
576                         requestHandler,
577                         new RedirectResolver() {
578 
579                             @Override
580                             public Redirect resolve(final URI requestUri) throws URISyntaxException {
581                                 final String path = requestUri.getPath();
582                                 if (path.equals("/oldlocation")) {
583                                     return new Redirect(HttpStatus.SC_MOVED_TEMPORARILY, "/newlocation/?p=I have spaces");
584 
585                                 }
586                                 return null;
587                             }
588 
589                         });
590             }
591 
592         });
593 
594         final HttpGet httpget = new HttpGet("/oldlocation");
595 
596         try {
597             this.httpclient.execute(target, httpget);
598         } catch (final ClientProtocolException e) {
599             Assert.assertTrue(e.getCause() instanceof ProtocolException);
600             throw e;
601         }
602     }
603 
604     @Test
605     public void testRedirectWithCookie() throws Exception {
606         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
607 
608             @Override
609             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
610                 return new RedirectingDecorator(
611                         requestHandler,
612                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY));
613             }
614 
615         });
616 
617         final CookieStore cookieStore = new BasicCookieStore();
618 
619         final BasicClientCookie cookie = new BasicClientCookie("name", "value");
620         cookie.setDomain(target.getHostName());
621         cookie.setPath("/");
622 
623         cookieStore.addCookie(cookie);
624 
625         final HttpClientContext context = HttpClientContext.create();
626         context.setCookieStore(cookieStore);
627         final HttpGet httpget = new HttpGet("/oldlocation/100");
628 
629         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
630             final HttpRequest reqWrapper = context.getRequest();
631 
632             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
633             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
634                     reqWrapper.getUri());
635 
636             final Header[] headers = reqWrapper.getHeaders("Cookie");
637             Assert.assertEquals("There can only be one (cookie)", 1, headers.length);
638 
639             EntityUtils.consume(response.getEntity());
640         }
641     }
642 
643     @Test
644     public void testDefaultHeadersRedirect() throws Exception {
645         this.clientBuilder.setDefaultHeaders(Collections.singletonList(new BasicHeader(HttpHeaders.USER_AGENT, "my-test-client")));
646 
647         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
648 
649             @Override
650             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
651                 return new RedirectingDecorator(
652                         requestHandler,
653                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY));
654             }
655 
656         });
657 
658         final HttpClientContext context = HttpClientContext.create();
659 
660         final HttpGet httpget = new HttpGet("/oldlocation/100");
661 
662         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
663             final HttpRequest reqWrapper = context.getRequest();
664 
665             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
666             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
667                     reqWrapper.getUri());
668 
669             final Header header = reqWrapper.getFirstHeader(HttpHeaders.USER_AGENT);
670             Assert.assertEquals("my-test-client", header.getValue());
671 
672             EntityUtils.consume(response.getEntity());
673         }
674     }
675 
676     @Test
677     public void testCompressionHeaderRedirect() throws Exception {
678         final Queue<String> values = new ConcurrentLinkedQueue<>();
679         final HttpHost target = start(null, new Decorator<HttpServerRequestHandler>() {
680 
681             @Override
682             public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
683                 return new RedirectingDecorator(
684                         requestHandler,
685                         new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY)) {
686 
687                     @Override
688                     public void handle(final ClassicHttpRequest request,
689                                        final ResponseTrigger responseTrigger,
690                                        final HttpContext context) throws HttpException, IOException {
691                         final Header header = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
692                         if (header != null) {
693                             values.add(header.getValue());
694                         }
695                         super.handle(request, responseTrigger, context);
696                     }
697 
698                 };
699             }
700 
701         });
702 
703         final HttpClientContext context = HttpClientContext.create();
704 
705         final HttpGet httpget = new HttpGet("/oldlocation/100");
706 
707         try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
708             final HttpRequest reqWrapper = context.getRequest();
709 
710             Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
711             Assert.assertEquals(new URIBuilder().setHttpHost(target).setPath("/random/100").build(),
712                     reqWrapper.getUri());
713 
714             EntityUtils.consume(response.getEntity());
715         }
716 
717         Assert.assertThat(values.poll(), CoreMatchers.equalTo("gzip, x-gzip, deflate"));
718         Assert.assertThat(values.poll(), CoreMatchers.equalTo("gzip, x-gzip, deflate"));
719         Assert.assertThat(values.poll(), CoreMatchers.nullValue());
720     }
721 
722 }