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