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