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.http.impl.client.integration;
28  
29  import java.io.ByteArrayInputStream;
30  import java.io.IOException;
31  import java.net.URI;
32  import java.util.Arrays;
33  import java.util.List;
34  
35  import org.apache.http.Consts;
36  import org.apache.http.Header;
37  import org.apache.http.HttpException;
38  import org.apache.http.HttpHost;
39  import org.apache.http.HttpInetConnection;
40  import org.apache.http.HttpRequest;
41  import org.apache.http.HttpResponse;
42  import org.apache.http.HttpStatus;
43  import org.apache.http.ProtocolException;
44  import org.apache.http.client.CircularRedirectException;
45  import org.apache.http.client.ClientProtocolException;
46  import org.apache.http.client.CookieStore;
47  import org.apache.http.client.RedirectException;
48  import org.apache.http.client.config.RequestConfig;
49  import org.apache.http.client.methods.HttpGet;
50  import org.apache.http.client.methods.HttpPost;
51  import org.apache.http.client.protocol.HttpClientContext;
52  import org.apache.http.client.utils.URIUtils;
53  import org.apache.http.cookie.SM;
54  import org.apache.http.entity.InputStreamEntity;
55  import org.apache.http.entity.StringEntity;
56  import org.apache.http.impl.client.BasicCookieStore;
57  import org.apache.http.impl.client.LaxRedirectStrategy;
58  import org.apache.http.impl.cookie.BasicClientCookie;
59  import org.apache.http.localserver.EchoHandler;
60  import org.apache.http.localserver.LocalServerTestBase;
61  import org.apache.http.message.BasicHeader;
62  import org.apache.http.protocol.HTTP;
63  import org.apache.http.protocol.HttpContext;
64  import org.apache.http.protocol.HttpCoreContext;
65  import org.apache.http.protocol.HttpExpectationVerifier;
66  import org.apache.http.protocol.HttpRequestHandler;
67  import org.apache.http.protocol.UriHttpRequestHandlerMapper;
68  import org.apache.http.util.EntityUtils;
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      private static class BasicRedirectService implements HttpRequestHandler {
78  
79          private final int statuscode;
80  
81          public BasicRedirectService(final int statuscode) {
82              super();
83              this.statuscode = statuscode > 0 ? statuscode : HttpStatus.SC_MOVED_TEMPORARILY;
84          }
85  
86          public BasicRedirectService() {
87              this(-1);
88          }
89  
90          @Override
91          public void handle(
92                  final HttpRequest request,
93                  final HttpResponse response,
94                  final HttpContext context) throws HttpException, IOException {
95              final HttpInetConnection conn = (HttpInetConnection) context.getAttribute(HttpCoreContext.HTTP_CONNECTION);
96              final int port = conn.getLocalPort();
97              final String uri = request.getRequestLine().getUri();
98              if (uri.equals("/oldlocation/")) {
99                  response.setStatusCode(this.statuscode);
100                 response.addHeader(new BasicHeader("Location",
101                         "http://localhost:" + port + "/newlocation/"));
102                 response.addHeader(new BasicHeader("Connection", "close"));
103             } else if (uri.equals("/newlocation/")) {
104                 response.setStatusCode(HttpStatus.SC_OK);
105                 final StringEntity entity = new StringEntity("Successful redirect");
106                 response.setEntity(entity);
107             } else {
108                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
109             }
110         }
111 
112     }
113 
114     private static class RedirectExpectationVerifier implements HttpExpectationVerifier {
115 
116         private final int statuscode;
117 
118         public RedirectExpectationVerifier(final int statuscode) {
119             super();
120             this.statuscode = statuscode > 0 ? statuscode : HttpStatus.SC_MOVED_TEMPORARILY;
121         }
122 
123         public RedirectExpectationVerifier() {
124             this(-1);
125         }
126 
127         @Override
128         public void verify(
129                 final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException {
130             final HttpInetConnection conn = (HttpInetConnection) context.getAttribute(HttpCoreContext.HTTP_CONNECTION);
131             final int port = conn.getLocalPort();
132             final String uri = request.getRequestLine().getUri();
133             if (uri.equals("/oldlocation/")) {
134                 response.setStatusCode(this.statuscode);
135                 response.addHeader(new BasicHeader("Location",
136                         "http://localhost:" + port + "/newlocation/"));
137                 response.addHeader(new BasicHeader("Connection", "close"));
138             } else {
139                 response.setStatusCode(HttpStatus.SC_CONTINUE);
140             }
141         }
142 
143     }
144 
145     private static class CircularRedirectService implements HttpRequestHandler {
146 
147         public CircularRedirectService() {
148             super();
149         }
150 
151         @Override
152         public void handle(
153                 final HttpRequest request,
154                 final HttpResponse response,
155                 final HttpContext context) throws HttpException, IOException {
156             final String uri = request.getRequestLine().getUri();
157             if (uri.startsWith("/circular-oldlocation")) {
158                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
159                 response.addHeader(new BasicHeader("Location", "/circular-location2"));
160             } else if (uri.startsWith("/circular-location2")) {
161                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
162                 response.addHeader(new BasicHeader("Location", "/circular-oldlocation"));
163             } else {
164                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
165             }
166         }
167     }
168 
169     private static class RelativeRedirectService implements HttpRequestHandler {
170 
171         public RelativeRedirectService() {
172             super();
173         }
174 
175         @Override
176         public void handle(
177                 final HttpRequest request,
178                 final HttpResponse response,
179                 final HttpContext context) throws HttpException, IOException {
180             final String uri = request.getRequestLine().getUri();
181             if (uri.equals("/oldlocation/")) {
182                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
183                 response.addHeader(new BasicHeader("Location", "/relativelocation/"));
184             } else if (uri.equals("/relativelocation/")) {
185                 response.setStatusCode(HttpStatus.SC_OK);
186                 final StringEntity entity = new StringEntity("Successful redirect");
187                 response.setEntity(entity);
188             } else {
189                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
190             }
191         }
192     }
193 
194     private static class RelativeRedirectService2 implements HttpRequestHandler {
195 
196         public RelativeRedirectService2() {
197             super();
198         }
199 
200         @Override
201         public void handle(
202                 final HttpRequest request,
203                 final HttpResponse response,
204                 final HttpContext context) throws HttpException, IOException {
205             final String uri = request.getRequestLine().getUri();
206             if (uri.equals("/test/oldlocation")) {
207                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
208                 response.addHeader(new BasicHeader("Location", "relativelocation"));
209             } else if (uri.equals("/test/relativelocation")) {
210                 response.setStatusCode(HttpStatus.SC_OK);
211                 final StringEntity entity = new StringEntity("Successful redirect");
212                 response.setEntity(entity);
213             } else {
214                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
215             }
216         }
217     }
218 
219     private static class RomeRedirectService implements HttpRequestHandler {
220 
221         public RomeRedirectService() {
222             super();
223         }
224 
225         @Override
226         public void handle(
227                 final HttpRequest request,
228                 final HttpResponse response,
229                 final HttpContext context) throws HttpException, IOException {
230             final String uri = request.getRequestLine().getUri();
231             if (uri.equals("/rome")) {
232                 response.setStatusCode(HttpStatus.SC_OK);
233                 final StringEntity entity = new StringEntity("Successful redirect");
234                 response.setEntity(entity);
235             } else {
236                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
237                 response.addHeader(new BasicHeader("Location", "/rome"));
238             }
239         }
240     }
241 
242     private static class BogusRedirectService implements HttpRequestHandler {
243         private final String url;
244 
245         public BogusRedirectService(final String redirectUrl) {
246             super();
247             this.url = redirectUrl;
248         }
249 
250         @Override
251         public void handle(
252                 final HttpRequest request,
253                 final HttpResponse response,
254                 final HttpContext context) throws HttpException, IOException {
255             final String uri = request.getRequestLine().getUri();
256             if (uri.equals("/oldlocation/")) {
257                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
258                 response.addHeader(new BasicHeader("Location", url));
259             } else if (uri.equals("/relativelocation/")) {
260                 response.setStatusCode(HttpStatus.SC_OK);
261                 final StringEntity entity = new StringEntity("Successful redirect");
262                 response.setEntity(entity);
263             } else {
264                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
265             }
266         }
267     }
268 
269     @Test
270     public void testBasicRedirect300() throws Exception {
271         this.serverBootstrap.registerHandler("*",
272                 new BasicRedirectService(HttpStatus.SC_MULTIPLE_CHOICES));
273 
274         final HttpHost target = start();
275 
276         final HttpClientContext context = HttpClientContext.create();
277 
278         final HttpGet httpget = new HttpGet("/oldlocation/");
279 
280         final HttpResponse response = this.httpclient.execute(target, httpget, context);
281         EntityUtils.consume(response.getEntity());
282 
283         final HttpRequest reqWrapper = context.getRequest();
284 
285         Assert.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getStatusLine().getStatusCode());
286         Assert.assertEquals("/oldlocation/", reqWrapper.getRequestLine().getUri());
287 
288         final List<URI> redirects = context.getRedirectLocations();
289         Assert.assertNull(redirects);
290     }
291 
292     @Test
293     public void testBasicRedirect301() throws Exception {
294         this.serverBootstrap.registerHandler("*",
295                 new BasicRedirectService(HttpStatus.SC_MOVED_PERMANENTLY));
296 
297         final HttpHost target = start();
298 
299         final HttpClientContext context = HttpClientContext.create();
300 
301         final HttpGet httpget = new HttpGet("/oldlocation/");
302 
303         final HttpResponse response = this.httpclient.execute(target, httpget, context);
304         EntityUtils.consume(response.getEntity());
305 
306         final HttpRequest reqWrapper = context.getRequest();
307         final HttpHost host = context.getTargetHost();
308 
309         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
310         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
311         Assert.assertEquals(target, host);
312 
313         final List<URI> redirects = context.getRedirectLocations();
314         Assert.assertNotNull(redirects);
315         Assert.assertEquals(1, redirects.size());
316 
317         final URI redirect = URIUtils.rewriteURI(new URI("/newlocation/"), target);
318         Assert.assertTrue(redirects.contains(redirect));
319     }
320 
321     @Test
322     public void testBasicRedirect302() throws Exception {
323         this.serverBootstrap.registerHandler("*",
324                 new BasicRedirectService(HttpStatus.SC_MOVED_TEMPORARILY));
325 
326         final HttpHost target = start();
327 
328         final HttpClientContext context = HttpClientContext.create();
329 
330         final HttpGet httpget = new HttpGet("/oldlocation/");
331 
332         final HttpResponse response = this.httpclient.execute(target, httpget, context);
333         EntityUtils.consume(response.getEntity());
334 
335         final HttpRequest reqWrapper = context.getRequest();
336         final HttpHost host = context.getTargetHost();
337 
338         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
339         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
340         Assert.assertEquals(target, host);
341     }
342 
343     @Test
344     public void testBasicRedirect302NoLocation() throws Exception {
345         this.serverBootstrap.registerHandler("*", new HttpRequestHandler() {
346 
347             @Override
348             public void handle(
349                     final HttpRequest request,
350                     final HttpResponse response,
351                     final HttpContext context) throws HttpException, IOException {
352                 response.setStatusCode(HttpStatus.SC_MOVED_TEMPORARILY);
353             }
354 
355         });
356 
357         final HttpHost target = start();
358 
359         final HttpClientContext context = HttpClientContext.create();
360 
361         final HttpGet httpget = new HttpGet("/oldlocation/");
362 
363         final HttpResponse response = this.httpclient.execute(target, httpget, context);
364         EntityUtils.consume(response.getEntity());
365 
366         final HttpRequest reqWrapper = context.getRequest();
367         final HttpHost host = context.getTargetHost();
368 
369         Assert.assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getStatusLine().getStatusCode());
370         Assert.assertEquals("/oldlocation/", reqWrapper.getRequestLine().getUri());
371         Assert.assertEquals(target, host);
372     }
373 
374     @Test
375     public void testBasicRedirect303() throws Exception {
376         this.serverBootstrap.registerHandler("*",
377                 new BasicRedirectService(HttpStatus.SC_SEE_OTHER));
378 
379         final HttpHost target = start();
380 
381         final HttpClientContext context = HttpClientContext.create();
382 
383         final HttpGet httpget = new HttpGet("/oldlocation/");
384 
385         final HttpResponse response = this.httpclient.execute(target, httpget, context);
386         EntityUtils.consume(response.getEntity());
387 
388         final HttpRequest reqWrapper = context.getRequest();
389         final HttpHost host = context.getTargetHost();
390 
391         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
392         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
393         Assert.assertEquals(target, host);
394     }
395 
396     @Test
397     public void testBasicRedirect304() throws Exception {
398         this.serverBootstrap.registerHandler("*",
399                 new BasicRedirectService(HttpStatus.SC_NOT_MODIFIED));
400 
401         final HttpHost target = start();
402 
403         final HttpClientContext context = HttpClientContext.create();
404 
405         final HttpGet httpget = new HttpGet("/oldlocation/");
406 
407         final HttpResponse response = this.httpclient.execute(target, httpget, context);
408         EntityUtils.consume(response.getEntity());
409 
410         final HttpRequest reqWrapper = context.getRequest();
411 
412         Assert.assertEquals(HttpStatus.SC_NOT_MODIFIED, response.getStatusLine().getStatusCode());
413         Assert.assertEquals("/oldlocation/", reqWrapper.getRequestLine().getUri());
414     }
415 
416     @Test
417     public void testBasicRedirect305() throws Exception {
418         this.serverBootstrap.registerHandler("*",
419                 new BasicRedirectService(HttpStatus.SC_USE_PROXY));
420         final HttpHost target = start();
421 
422         final HttpClientContext context = HttpClientContext.create();
423 
424         final HttpGet httpget = new HttpGet("/oldlocation/");
425 
426         final HttpResponse response = this.httpclient.execute(target, httpget, context);
427         EntityUtils.consume(response.getEntity());
428 
429         final HttpRequest reqWrapper = context.getRequest();
430 
431         Assert.assertEquals(HttpStatus.SC_USE_PROXY, response.getStatusLine().getStatusCode());
432         Assert.assertEquals("/oldlocation/", reqWrapper.getRequestLine().getUri());
433     }
434 
435     @Test
436     public void testBasicRedirect307() throws Exception {
437         this.serverBootstrap.registerHandler("*",
438                 new BasicRedirectService(HttpStatus.SC_TEMPORARY_REDIRECT));
439 
440         final HttpHost target = start();
441 
442         final HttpClientContext context = HttpClientContext.create();
443 
444         final HttpGet httpget = new HttpGet("/oldlocation/");
445 
446         final HttpResponse response = this.httpclient.execute(target, httpget, context);
447         EntityUtils.consume(response.getEntity());
448 
449         final HttpRequest reqWrapper = context.getRequest();
450         final HttpHost host = context.getTargetHost();
451 
452         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
453         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
454         Assert.assertEquals(target, host);
455     }
456 
457     @Test(expected=ClientProtocolException.class)
458     public void testMaxRedirectCheck() throws Exception {
459         this.serverBootstrap.registerHandler("*", new CircularRedirectService());
460 
461         final HttpHost target = start();
462 
463         final RequestConfig config = RequestConfig.custom()
464             .setCircularRedirectsAllowed(true)
465             .setMaxRedirects(5)
466             .build();
467 
468         final HttpGet httpget = new HttpGet("/circular-oldlocation/");
469         httpget.setConfig(config);
470         try {
471             this.httpclient.execute(target, httpget);
472         } catch (final ClientProtocolException e) {
473             Assert.assertTrue(e.getCause() instanceof RedirectException);
474             throw e;
475         }
476     }
477 
478     @Test(expected=ClientProtocolException.class)
479     public void testCircularRedirect() throws Exception {
480         this.serverBootstrap.registerHandler("*", new CircularRedirectService());
481 
482         final HttpHost target = start();
483 
484         final RequestConfig config = RequestConfig.custom()
485             .setCircularRedirectsAllowed(false)
486             .build();
487 
488         final HttpGet httpget = new HttpGet("/circular-oldlocation/");
489         httpget.setConfig(config);
490         try {
491             this.httpclient.execute(target, httpget);
492         } catch (final ClientProtocolException e) {
493             Assert.assertTrue(e.getCause() instanceof CircularRedirectException);
494             throw e;
495         }
496     }
497 
498     @Test
499     public void testRepeatRequest() throws Exception {
500         this.serverBootstrap.registerHandler("*", new RomeRedirectService());
501 
502         final HttpHost target = start();
503 
504         final HttpClientContext context = HttpClientContext.create();
505 
506         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(true).build();
507         final HttpGet first = new HttpGet("/rome");
508         first.setConfig(config);
509 
510         EntityUtils.consume(this.httpclient.execute(target, first, context).getEntity());
511 
512         final HttpGet second = new HttpGet("/rome");
513         second.setConfig(config);
514 
515         final HttpResponse response = this.httpclient.execute(target, second, context);
516         EntityUtils.consume(response.getEntity());
517 
518         final HttpRequest reqWrapper = context.getRequest();
519         final HttpHost host = context.getTargetHost();
520 
521         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
522         Assert.assertEquals("/rome", reqWrapper.getRequestLine().getUri());
523         Assert.assertEquals(host, target);
524     }
525 
526     @Test
527     public void testRepeatRequestRedirect() throws Exception {
528         this.serverBootstrap.registerHandler("*", new RomeRedirectService());
529 
530         final HttpHost target = start();
531 
532         final HttpClientContext context = HttpClientContext.create();
533 
534         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(true).build();
535         final HttpGet first = new HttpGet("/lille");
536         first.setConfig(config);
537 
538         final HttpResponse response1 = this.httpclient.execute(target, first, context);
539         EntityUtils.consume(response1.getEntity());
540 
541         final HttpGet second = new HttpGet("/lille");
542         second.setConfig(config);
543 
544         final HttpResponse response2 = this.httpclient.execute(target, second, context);
545         EntityUtils.consume(response2.getEntity());
546 
547         final HttpRequest reqWrapper = context.getRequest();
548         final HttpHost host = context.getTargetHost();
549 
550         Assert.assertEquals(HttpStatus.SC_OK, response2.getStatusLine().getStatusCode());
551         Assert.assertEquals("/rome", reqWrapper.getRequestLine().getUri());
552         Assert.assertEquals(host, target);
553     }
554 
555     @Test
556     public void testDifferentRequestSameRedirect() throws Exception {
557         this.serverBootstrap.registerHandler("*", new RomeRedirectService());
558 
559         final HttpHost target = start();
560 
561         final HttpClientContext context = HttpClientContext.create();
562 
563         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(true).build();
564         final HttpGet first = new HttpGet("/alian");
565         first.setConfig(config);
566 
567         final HttpResponse response1 = this.httpclient.execute(target, first, context);
568         EntityUtils.consume(response1.getEntity());
569 
570         final HttpGet second = new HttpGet("/lille");
571         second.setConfig(config);
572 
573         final HttpResponse response2 = this.httpclient.execute(target, second, context);
574         EntityUtils.consume(response2.getEntity());
575 
576         final HttpRequest reqWrapper = context.getRequest();
577         final HttpHost host = context.getTargetHost();
578 
579         Assert.assertEquals(HttpStatus.SC_OK, response2.getStatusLine().getStatusCode());
580         Assert.assertEquals("/rome", reqWrapper.getRequestLine().getUri());
581         Assert.assertEquals(host, target);
582     }
583 
584     @Test
585     public void testPostNoRedirect() throws Exception {
586         this.serverBootstrap.registerHandler("*", new BasicRedirectService());
587 
588         final HttpHost target = start();
589 
590         final HttpClientContext context = HttpClientContext.create();
591 
592         final HttpPost httppost = new HttpPost("/oldlocation/");
593         httppost.setEntity(new StringEntity("stuff"));
594 
595         final HttpResponse response = this.httpclient.execute(target, httppost, context);
596         EntityUtils.consume(response.getEntity());
597 
598         final HttpRequest reqWrapper = context.getRequest();
599 
600         Assert.assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getStatusLine().getStatusCode());
601         Assert.assertEquals("/oldlocation/", reqWrapper.getRequestLine().getUri());
602         Assert.assertEquals("POST", reqWrapper.getRequestLine().getMethod());
603     }
604 
605     @Test
606     public void testPostRedirectSeeOther() throws Exception {
607         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_SEE_OTHER));
608 
609         final HttpHost target = start();
610 
611         final HttpClientContext context = HttpClientContext.create();
612 
613         final HttpPost httppost = new HttpPost("/oldlocation/");
614         httppost.setEntity(new StringEntity("stuff"));
615 
616         final HttpResponse response = this.httpclient.execute(target, httppost, context);
617         EntityUtils.consume(response.getEntity());
618 
619         final HttpRequest reqWrapper = context.getRequest();
620 
621         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
622         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
623         Assert.assertEquals("GET", reqWrapper.getRequestLine().getMethod());
624     }
625 
626     @Test
627     public void testPostRedirectMovedPermatently() throws Exception {
628         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_MOVED_PERMANENTLY));
629 
630         final HttpHost target = start();
631 
632         final HttpClientContext context = HttpClientContext.create();
633 
634         final HttpPost httppost = new HttpPost("/oldlocation/");
635         httppost.setEntity(new StringEntity("stuff"));
636 
637         final HttpResponse response = this.httpclient.execute(target, httppost, context);
638         EntityUtils.consume(response.getEntity());
639         Assert.assertEquals(HttpStatus.SC_MOVED_PERMANENTLY, response.getStatusLine().getStatusCode());
640     }
641 
642     @Test
643     public void testPostRedirectMovedPermatentlyLaxStrategy() throws Exception {
644         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_MOVED_PERMANENTLY));
645         this.clientBuilder.setRedirectStrategy(LaxRedirectStrategy.INSTANCE);
646 
647         final HttpHost target = start();
648 
649         final HttpClientContext context = HttpClientContext.create();
650 
651         final HttpPost httppost = new HttpPost("/oldlocation/");
652         httppost.setEntity(new StringEntity("stuff"));
653 
654         final HttpResponse response = this.httpclient.execute(target, httppost, context);
655         EntityUtils.consume(response.getEntity());
656 
657         final HttpRequest reqWrapper = context.getRequest();
658 
659         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
660         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
661         Assert.assertEquals("GET", reqWrapper.getRequestLine().getMethod());
662     }
663 
664     @Test
665     public void testPostTemporaryRedirectLaxStrategy() throws Exception {
666         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_TEMPORARY_REDIRECT));
667         this.clientBuilder.setRedirectStrategy(LaxRedirectStrategy.INSTANCE);
668 
669         final HttpHost target = start();
670 
671         final HttpClientContext context = HttpClientContext.create();
672 
673         final HttpPost httppost = new HttpPost("/oldlocation/");
674         httppost.setEntity(new StringEntity("stuff"));
675 
676         final HttpResponse response = this.httpclient.execute(target, httppost, context);
677         EntityUtils.consume(response.getEntity());
678 
679         final HttpRequest reqWrapper = context.getRequest();
680 
681         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
682         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
683         Assert.assertEquals("POST", reqWrapper.getRequestLine().getMethod());
684     }
685 
686     @Test
687     public void testNonRepeatablePostTemporaryRedirectLaxStrategy() throws Exception {
688         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_TEMPORARY_REDIRECT));
689         this.clientBuilder.setRedirectStrategy(LaxRedirectStrategy.INSTANCE);
690 
691         final HttpHost target = start();
692 
693         final HttpClientContext context = HttpClientContext.create();
694 
695         final HttpPost httppost = new HttpPost("/oldlocation/");
696         final byte[] content = "stuff".getBytes(Consts.ASCII);
697         httppost.setEntity(new InputStreamEntity(new ByteArrayInputStream(content), content.length));
698 
699         final HttpResponse response = this.httpclient.execute(target, httppost, context);
700         EntityUtils.consume(response.getEntity());
701         Assert.assertEquals(HttpStatus.SC_TEMPORARY_REDIRECT, response.getStatusLine().getStatusCode());
702     }
703 
704     @Test
705     public void testNonRepeatablePostTemporaryWithExpectContinueRedirectLaxStrategy() throws Exception {
706         this.serverBootstrap.registerHandler("*", new BasicRedirectService(HttpStatus.SC_TEMPORARY_REDIRECT));
707         this.clientBuilder.setRedirectStrategy(LaxRedirectStrategy.INSTANCE);
708 
709         final HttpHost target = start();
710 
711         final HttpClientContext context = HttpClientContext.create();
712         context.setRequestConfig(RequestConfig.custom()
713                 .setExpectContinueEnabled(true)
714                 .build());
715 
716         final HttpPost httppost = new HttpPost("/oldlocation/");
717         final byte[] content = "stuff".getBytes(Consts.ASCII);
718         httppost.setEntity(new InputStreamEntity(new ByteArrayInputStream(content), content.length));
719 
720         final HttpResponse response = this.httpclient.execute(target, httppost, context);
721         EntityUtils.consume(response.getEntity());
722         Assert.assertEquals(HttpStatus.SC_TEMPORARY_REDIRECT, response.getStatusLine().getStatusCode());
723     }
724 
725     @Test
726     public void testNonRepeatablePostTemporaryWithExpectContinueExpectVerifierRedirectLaxStrategy() throws Exception {
727         this.serverBootstrap.registerHandler("*", new EchoHandler());
728         this.serverBootstrap.setExpectationVerifier(new RedirectExpectationVerifier(HttpStatus.SC_TEMPORARY_REDIRECT));
729 
730         this.clientBuilder.setRedirectStrategy(LaxRedirectStrategy.INSTANCE);
731 
732         final HttpHost target = start();
733 
734         final HttpClientContext context = HttpClientContext.create();
735         context.setRequestConfig(RequestConfig.custom()
736                 .setExpectContinueEnabled(true)
737                 .build());
738 
739         final HttpPost httppost = new HttpPost("/oldlocation/");
740         final byte[] content = "stuff".getBytes(Consts.ASCII);
741         httppost.setEntity(new InputStreamEntity(new ByteArrayInputStream(content), content.length));
742 
743         final HttpResponse response = this.httpclient.execute(target, httppost, context);
744         EntityUtils.consume(response.getEntity());
745 
746         final HttpRequest reqWrapper = context.getRequest();
747 
748         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
749         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
750         Assert.assertEquals("POST", reqWrapper.getRequestLine().getMethod());
751     }
752 
753     @Test
754     public void testRelativeRedirect() throws Exception {
755         this.serverBootstrap.registerHandler("*", new RelativeRedirectService());
756 
757         final HttpHost target = start();
758 
759         final HttpClientContext context = HttpClientContext.create();
760 
761         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(true).build();
762         final HttpGet httpget = new HttpGet("/oldlocation/");
763         httpget.setConfig(config);
764 
765         final HttpResponse response = this.httpclient.execute(target, httpget, context);
766         EntityUtils.consume(response.getEntity());
767 
768         final HttpRequest reqWrapper = context.getRequest();
769         final HttpHost host = context.getTargetHost();
770 
771         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
772         Assert.assertEquals("/relativelocation/", reqWrapper.getRequestLine().getUri());
773         Assert.assertEquals(host, target);
774     }
775 
776     @Test
777     public void testRelativeRedirect2() throws Exception {
778         this.serverBootstrap.registerHandler("*", new RelativeRedirectService2());
779 
780         final HttpHost target = start();
781 
782         final HttpClientContext context = HttpClientContext.create();
783 
784         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(true).build();
785         final HttpGet httpget = new HttpGet("/test/oldlocation");
786         httpget.setConfig(config);
787 
788         final HttpResponse response = this.httpclient.execute(target, httpget, context);
789         EntityUtils.consume(response.getEntity());
790 
791         final HttpRequest reqWrapper = context.getRequest();
792         final HttpHost host = context.getTargetHost();
793 
794         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
795         Assert.assertEquals("/test/relativelocation", reqWrapper.getRequestLine().getUri());
796         Assert.assertEquals(host, target);
797     }
798 
799     @Test(expected=ClientProtocolException.class)
800     public void testRejectRelativeRedirect() throws Exception {
801         this.serverBootstrap.registerHandler("*", new RelativeRedirectService());
802 
803         final HttpHost target = start();
804 
805         final RequestConfig config = RequestConfig.custom().setRelativeRedirectsAllowed(false).build();
806         final HttpGet httpget = new HttpGet("/oldlocation/");
807         httpget.setConfig(config);
808         try {
809             this.httpclient.execute(target, httpget);
810         } catch (final ClientProtocolException e) {
811             Assert.assertTrue(e.getCause() instanceof ProtocolException);
812             throw e;
813         }
814     }
815 
816     @Test(expected=ClientProtocolException.class)
817     public void testRejectBogusRedirectLocation() throws Exception {
818         this.serverBootstrap.registerHandler("*", new BogusRedirectService("xxx://bogus"));
819 
820         final HttpHost target = start();
821 
822         final HttpGet httpget = new HttpGet("/oldlocation/");
823 
824         try {
825             this.httpclient.execute(target, httpget);
826         } catch (final ClientProtocolException ex) {
827             final Throwable cause = ex.getCause();
828             Assert.assertTrue(cause instanceof HttpException);
829             throw ex;
830         }
831     }
832 
833     @Test(expected=ClientProtocolException.class)
834     public void testRejectInvalidRedirectLocation() throws Exception {
835         final UriHttpRequestHandlerMapper reqistry = new UriHttpRequestHandlerMapper();
836         this.serverBootstrap.setHandlerMapper(reqistry);
837 
838         final HttpHost target = start();
839 
840         reqistry.register("*",
841                 new BogusRedirectService("http://" + target.toHostString() +
842                         "/newlocation/?p=I have spaces"));
843 
844         final HttpGet httpget = new HttpGet("/oldlocation/");
845 
846         try {
847             this.httpclient.execute(target, httpget);
848         } catch (final ClientProtocolException e) {
849             Assert.assertTrue(e.getCause() instanceof ProtocolException);
850             throw e;
851         }
852     }
853 
854     @Test
855     public void testRedirectWithCookie() throws Exception {
856         this.serverBootstrap.registerHandler("*", new BasicRedirectService());
857 
858         final HttpHost target = start();
859 
860         final CookieStore cookieStore = new BasicCookieStore();
861 
862         final BasicClientCookie cookie = new BasicClientCookie("name", "value");
863         cookie.setDomain(target.getHostName());
864         cookie.setPath("/");
865 
866         cookieStore.addCookie(cookie);
867 
868         final HttpClientContext context = HttpClientContext.create();
869         context.setCookieStore(cookieStore);
870         final HttpGet httpget = new HttpGet("/oldlocation/");
871 
872         final HttpResponse response = this.httpclient.execute(target, httpget, context);
873         EntityUtils.consume(response.getEntity());
874 
875         final HttpRequest reqWrapper = context.getRequest();
876 
877         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
878         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
879 
880         final Header[] headers = reqWrapper.getHeaders(SM.COOKIE);
881         Assert.assertEquals("There can only be one (cookie)", 1, headers.length);
882     }
883 
884     @Test
885     public void testDefaultHeadersRedirect() throws Exception {
886         this.clientBuilder.setDefaultHeaders(Arrays.asList(new BasicHeader(HTTP.USER_AGENT, "my-test-client")));
887 
888         this.serverBootstrap.registerHandler("*", new BasicRedirectService());
889 
890         final HttpHost target = start();
891 
892         final HttpClientContext context = HttpClientContext.create();
893 
894         final HttpGet httpget = new HttpGet("/oldlocation/");
895 
896 
897         final HttpResponse response = this.httpclient.execute(target, httpget, context);
898         EntityUtils.consume(response.getEntity());
899 
900         final HttpRequest reqWrapper = context.getRequest();
901 
902         Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
903         Assert.assertEquals("/newlocation/", reqWrapper.getRequestLine().getUri());
904 
905         final Header header = reqWrapper.getFirstHeader(HTTP.USER_AGENT);
906         Assert.assertEquals("my-test-client", header.getValue());
907     }
908 
909 }