1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/test/org/apache/commons/httpclient/TestRedirects.java $
3    * $Revision: 1425331 $
4    * $Date: 2012-12-22 19:29:41 +0100 (Sat, 22 Dec 2012) $
5    * ====================================================================
6    *
7    *  Licensed to the Apache Software Foundation (ASF) under one or more
8    *  contributor license agreements.  See the NOTICE file distributed with
9    *  this work for additional information regarding copyright ownership.
10   *  The ASF licenses this file to You under the Apache License, Version 2.0
11   *  (the "License"); you may not use this file except in compliance with
12   *  the License.  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient;
31  
32  import java.io.IOException;
33  
34  import junit.framework.Test;
35  import junit.framework.TestSuite;
36  
37  import org.apache.commons.httpclient.methods.GetMethod;
38  import org.apache.commons.httpclient.methods.PostMethod;
39  import org.apache.commons.httpclient.methods.StringRequestEntity;
40  import org.apache.commons.httpclient.params.HttpClientParams;
41  import org.apache.commons.httpclient.protocol.Protocol;
42  import org.apache.commons.httpclient.server.HttpService;
43  import org.apache.commons.httpclient.server.RequestLine;
44  import org.apache.commons.httpclient.server.SimpleHttpServer;
45  import org.apache.commons.httpclient.server.SimpleRequest;
46  import org.apache.commons.httpclient.server.SimpleResponse;
47  
48  /***
49   * Redirection test cases.
50   *
51   * @author Oleg Kalnichevski
52   * 
53   * @version $Id: TestRedirects.java 608014 2008-01-02 05:48:53Z rolandw $
54   */
55  public class TestRedirects extends HttpClientTestBase {
56  
57      // ------------------------------------------------------------ Constructor
58      public TestRedirects(final String testName) throws IOException {
59          super(testName);
60      }
61  
62      // ------------------------------------------------------------------- Main
63      public static void main(String args[]) {
64          String[] testCaseName = { TestRedirects.class.getName() };
65          junit.textui.TestRunner.main(testCaseName);
66      }
67  
68      // ------------------------------------------------------- TestCase Methods
69  
70      public static Test suite() {
71          TestSuite suite = new TestSuite(TestRedirects.class);
72          ProxyTestDecorator.addTests(suite);
73          return suite;
74      }
75  
76      private class BasicRedirectService implements HttpService {
77  		private int statuscode = HttpStatus.SC_MOVED_TEMPORARILY;
78  		private String host = null;
79          private int port;
80  
81          public BasicRedirectService(final String host, int port, int statuscode) {
82              super();
83              this.host = host;
84              this.port = port;
85              if (statuscode > 0) {
86              	this.statuscode = statuscode;
87              }
88          }
89  
90          public BasicRedirectService(final String host, int port) {
91              this(host, port, -1);
92          }
93  
94          public boolean process(final SimpleRequest request, final SimpleResponse response)
95              throws IOException {
96              RequestLine reqline = request.getRequestLine();
97              HttpVersion ver = reqline.getHttpVersion();
98              if (reqline.getUri().equals("/oldlocation/")) {
99                  response.setStatusLine(ver, this.statuscode);
100                 response.addHeader(new Header("Location", 
101                 		"http://" + this.host + ":" + this.port + "/newlocation/"));
102                 response.addHeader(new Header("Connection", "close"));
103             } else if (reqline.getUri().equals("/newlocation/")) {
104                 response.setStatusLine(ver, HttpStatus.SC_OK);
105                 response.setBodyString("Successful redirect");
106             } else {
107                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
108             }
109             return true;
110         }
111     }
112 
113     private class CircularRedirectService implements HttpService {
114 
115         private int invocations = 0;
116         
117         public CircularRedirectService() {
118             super();
119         }
120         
121         public boolean process(final SimpleRequest request, final SimpleResponse response)
122             throws IOException
123         {
124             RequestLine reqline = request.getRequestLine();
125             HttpVersion ver = reqline.getHttpVersion();
126             if (reqline.getUri().startsWith("/circular-oldlocation")) {
127                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
128                 response.addHeader(new Header("Location", "/circular-location2?invk=" + (++this.invocations)));
129             } else if (reqline.getUri().startsWith("/circular-location2")) {
130                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
131                 response.addHeader(new Header("Location", "/circular-oldlocation?invk=" + (++this.invocations)));
132             } else {
133                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
134             }
135             return true;
136         }
137     }
138 
139     private class RelativeRedirectService implements HttpService {
140         
141             public RelativeRedirectService() {
142                 super();
143             }
144 
145             public boolean process(final SimpleRequest request, final SimpleResponse response)
146                 throws IOException
147             {
148                 RequestLine reqline = request.getRequestLine();
149                 HttpVersion ver = reqline.getHttpVersion();
150                 if (reqline.getUri().equals("/oldlocation/")) {
151                     response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
152                     response.addHeader(new Header("Location", "/relativelocation/"));
153                 } else if (reqline.getUri().equals("/relativelocation/")) {
154                     response.setStatusLine(ver, HttpStatus.SC_OK);
155                     response.setBodyString("Successful redirect");
156                 } else {
157                     response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
158                 }
159                 return true;
160             }
161         }
162 
163     private class BogusRedirectService implements HttpService {
164         private String url;
165         
166         public BogusRedirectService(String redirectUrl) {
167             super();
168             this.url = redirectUrl;
169         }
170 
171         public boolean process(final SimpleRequest request, final SimpleResponse response)
172             throws IOException {
173             RequestLine reqline = request.getRequestLine();
174             HttpVersion ver = reqline.getHttpVersion();
175             if (reqline.getUri().equals("/oldlocation/")) {
176                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
177                 response.addHeader(new Header("Location", url));
178             } else if (reqline.getUri().equals("/relativelocation/")) {
179                 response.setStatusLine(ver, HttpStatus.SC_OK);
180                 response.setBodyString("Successful redirect");
181             } else {
182                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
183             }
184             return true;
185         }
186     }
187 
188     public void testBasicRedirect300() throws IOException {
189         String host = this.server.getLocalAddress();
190         int port = this.server.getLocalPort();
191         this.server.setHttpService(
192                 new BasicRedirectService(host, port, HttpStatus.SC_MULTIPLE_CHOICES));
193         GetMethod httpget = new GetMethod("/oldlocation/");
194         httpget.setFollowRedirects(false);
195         try {
196             this.client.executeMethod(httpget);
197             assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, httpget.getStatusCode());
198             assertEquals("/oldlocation/", httpget.getPath());
199             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
200         } finally {
201             httpget.releaseConnection();
202         }
203     }
204 
205     public void testBasicRedirect301() throws IOException {
206         String host = this.server.getLocalAddress();
207         int port = this.server.getLocalPort();
208         this.server.setHttpService(
209                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_PERMANENTLY));
210         GetMethod httpget = new GetMethod("/oldlocation/");
211         httpget.setFollowRedirects(true);
212         try {
213             this.client.executeMethod(httpget);
214             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
215             assertEquals("/newlocation/", httpget.getPath());
216             assertEquals(host, httpget.getURI().getHost());
217             assertEquals(port, httpget.getURI().getPort());
218             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
219         } finally {
220             httpget.releaseConnection();
221         }
222     }
223 
224     public void testBasicRedirect302() throws IOException {
225         String host = this.server.getLocalAddress();
226         int port = this.server.getLocalPort();
227         this.server.setHttpService(
228                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_TEMPORARILY));
229         GetMethod httpget = new GetMethod("/oldlocation/");
230         httpget.setFollowRedirects(true);
231         try {
232             this.client.executeMethod(httpget);
233             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
234             assertEquals("/newlocation/", httpget.getPath());
235             assertEquals(host, httpget.getURI().getHost());
236             assertEquals(port, httpget.getURI().getPort());
237             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
238         } finally {
239             httpget.releaseConnection();
240         }
241     }
242 
243     public void testBasicRedirect303() throws IOException {
244         String host = this.server.getLocalAddress();
245         int port = this.server.getLocalPort();
246         this.server.setHttpService(
247                 new BasicRedirectService(host, port, HttpStatus.SC_SEE_OTHER));
248         GetMethod httpget = new GetMethod("/oldlocation/");
249         httpget.setFollowRedirects(true);
250         try {
251             this.client.executeMethod(httpget);
252             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
253             assertEquals("/newlocation/", httpget.getPath());
254             assertEquals(host, httpget.getURI().getHost());
255             assertEquals(port, httpget.getURI().getPort());
256             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
257         } finally {
258             httpget.releaseConnection();
259         }
260     }
261 
262     public void testBasicRedirect304() throws IOException {
263         String host = this.server.getLocalAddress();
264         int port = this.server.getLocalPort();
265         this.server.setHttpService(
266                 new BasicRedirectService(host, port, HttpStatus.SC_NOT_MODIFIED));
267         GetMethod httpget = new GetMethod("/oldlocation/");
268         httpget.setFollowRedirects(true);
269         try {
270             this.client.executeMethod(httpget);
271             assertEquals(HttpStatus.SC_NOT_MODIFIED, httpget.getStatusCode());
272             assertEquals("/oldlocation/", httpget.getPath());
273             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
274         } finally {
275             httpget.releaseConnection();
276         }
277     }
278 
279     public void testBasicRedirect305() throws IOException {
280         String host = this.server.getLocalAddress();
281         int port = this.server.getLocalPort();
282         this.server.setHttpService(
283                 new BasicRedirectService(host, port, HttpStatus.SC_USE_PROXY));
284         GetMethod httpget = new GetMethod("/oldlocation/");
285         httpget.setFollowRedirects(true);
286         try {
287             this.client.executeMethod(httpget);
288             assertEquals(HttpStatus.SC_USE_PROXY, httpget.getStatusCode());
289             assertEquals("/oldlocation/", httpget.getPath());
290             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
291         } finally {
292             httpget.releaseConnection();
293         }
294     }
295 
296     public void testBasicRedirect307() throws IOException {
297         String host = this.server.getLocalAddress();
298         int port = this.server.getLocalPort();
299         this.server.setHttpService(
300                 new BasicRedirectService(host, port, HttpStatus.SC_TEMPORARY_REDIRECT));
301         GetMethod httpget = new GetMethod("/oldlocation/");
302         httpget.setFollowRedirects(true);
303         try {
304             this.client.executeMethod(httpget);
305             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
306             assertEquals("/newlocation/", httpget.getPath());
307             assertEquals(host, httpget.getURI().getHost());
308             assertEquals(port, httpget.getURI().getPort());
309             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
310         } finally {
311             httpget.releaseConnection();
312         }
313     }
314 
315     public void testNoRedirect() throws IOException {
316         String host = this.server.getLocalAddress();
317         int port = this.server.getLocalPort();
318         this.server.setHttpService(new BasicRedirectService(host, port));
319         GetMethod httpget = new GetMethod("/oldlocation/");
320         httpget.setFollowRedirects(false);
321         try {
322             this.client.executeMethod(httpget);
323             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httpget.getStatusCode());
324             assertEquals("/oldlocation/", httpget.getPath());
325             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
326         } finally {
327             httpget.releaseConnection();
328         }
329     }
330 
331     public void testMaxRedirectCheck() throws IOException {
332         this.server.setHttpService(new CircularRedirectService());
333         GetMethod httpget = new GetMethod("/circular-oldlocation/");
334         try {
335             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true);
336             this.client.getParams().setIntParameter(HttpClientParams.MAX_REDIRECTS, 5);
337             this.client.executeMethod(httpget);
338             fail("RedirectException exception should have been thrown");
339         }
340         catch (RedirectException e) {
341             // expected
342         } finally {
343             httpget.releaseConnection();
344         }
345     }
346 
347     public void testCircularRedirect() throws IOException {
348         this.server.setHttpService(new CircularRedirectService());
349         GetMethod httpget = new GetMethod("/circular-oldlocation/");
350         try {
351             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false);
352             this.client.executeMethod(httpget);
353             fail("CircularRedirectException exception should have been thrown");
354         } catch (CircularRedirectException expected) {
355         } finally {
356             httpget.releaseConnection();
357         }
358     }
359 
360     public void testPostRedirect() throws IOException {
361         String host = this.server.getLocalAddress();
362         int port = this.server.getLocalPort();
363         this.server.setHttpService(new BasicRedirectService(host, port));
364         PostMethod httppost = new PostMethod("/oldlocation/");
365         httppost.setRequestEntity(new StringRequestEntity("stuff", null, null));
366         try {
367             this.client.executeMethod(httppost);
368             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httppost.getStatusCode());
369             assertEquals("/oldlocation/", httppost.getPath());
370             assertEquals(new URI("/oldlocation/", false), httppost.getURI());
371         } finally {
372         	httppost.releaseConnection();
373         }
374     }
375 
376     public void testRelativeRedirect() throws IOException {
377         String host = this.server.getLocalAddress();
378         int port = this.server.getLocalPort();
379         this.server.setHttpService(new RelativeRedirectService());
380         this.client.getParams().setBooleanParameter(
381                 HttpClientParams.REJECT_RELATIVE_REDIRECT, false);
382         GetMethod httpget = new GetMethod("/oldlocation/");
383         httpget.setFollowRedirects(true);
384         try {
385             this.client.executeMethod(httpget);
386             assertEquals("/relativelocation/", httpget.getPath());
387             assertEquals(host, httpget.getURI().getHost());
388             assertEquals(port, httpget.getURI().getPort());
389             assertEquals(new URI("http://" + host + ":" + port + "/relativelocation/", false), 
390             		httpget.getURI());
391         } finally {
392             httpget.releaseConnection();
393         }
394     }
395 
396     public void testRejectRelativeRedirect() throws IOException {
397         String host = this.server.getLocalAddress();
398         int port = this.server.getLocalPort();
399         this.server.setHttpService(new RelativeRedirectService());
400         this.client.getParams().setBooleanParameter(
401                 HttpClientParams.REJECT_RELATIVE_REDIRECT, true);
402         GetMethod httpget = new GetMethod("/oldlocation/");
403         httpget.setFollowRedirects(true);
404         try {
405             this.client.executeMethod(httpget);
406             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httpget.getStatusCode());
407             assertEquals("/oldlocation/", httpget.getPath());
408             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
409         } finally {
410             httpget.releaseConnection();
411         }
412     }
413 
414     public void testRejectBogusRedirectLocation() throws IOException {
415         String host = this.server.getLocalAddress();
416         int port = this.server.getLocalPort();
417         this.server.setHttpService(new BogusRedirectService("xxx://bogus"));
418         GetMethod httpget = new GetMethod("/oldlocation/");
419         httpget.setFollowRedirects(true);
420         try {
421             this.client.executeMethod(httpget);
422             fail("BogusRedirectService should have been thrown");
423         } catch (IllegalStateException e) {
424         	//expected
425         } finally {
426             httpget.releaseConnection();
427         }
428     }
429 
430     public void testRejectInvalidRedirectLocation() throws IOException {
431         String host = this.server.getLocalAddress();
432         int port = this.server.getLocalPort();
433         this.server.setHttpService(new BogusRedirectService("http://"+ host +":"+ port +"/newlocation/?p=I have spaces"));
434         GetMethod httpget = new GetMethod("/oldlocation/");
435         httpget.setFollowRedirects(true);
436         try {
437             this.client.executeMethod(httpget);
438             fail("InvalidRedirectLocationException should have been thrown");
439         } catch (InvalidRedirectLocationException e) {
440             //expected a protocol exception
441         } finally {
442             httpget.releaseConnection();
443         }
444     }
445 
446     public void testCrossSiteRedirect() throws IOException {
447         String host = this.server.getLocalAddress();
448         int port = this.server.getLocalPort();
449         
450         SimpleHttpServer thatserver = new SimpleHttpServer();
451         this.server.setHttpService(new BasicRedirectService(host, port));
452         thatserver.setHttpService(new BasicRedirectService(host, port));
453         thatserver.setTestname(getName());
454         
455         HostConfiguration hostconfig = new HostConfiguration();
456         hostconfig.setHost(
457                 thatserver.getLocalAddress(), 
458                 thatserver.getLocalPort(),
459                 Protocol.getProtocol("http"));
460 
461         GetMethod httpget = new GetMethod("/oldlocation/");
462         httpget.setFollowRedirects(true);
463         try {
464             this.client.executeMethod(hostconfig, httpget);
465             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
466             assertEquals("/newlocation/", httpget.getPath());
467             assertEquals(host, httpget.getURI().getHost());
468             assertEquals(port, httpget.getURI().getPort());
469             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), 
470             		httpget.getURI());
471         } finally {
472             httpget.releaseConnection();
473         }
474         thatserver.destroy();
475     }
476 
477     public void testRedirectWithCookie() throws IOException {
478     	
479         client.getState().addCookie(new Cookie("localhost", "name", "value", "/", -1, false)); 
480 
481         String host = this.server.getLocalAddress();
482         int port = this.server.getLocalPort();
483 
484         this.server.setHttpService(new BasicRedirectService(host, port));
485         GetMethod httpget = new GetMethod("/oldlocation/");
486         httpget.setFollowRedirects(true);
487         try {
488             this.client.executeMethod(httpget);
489             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
490             assertEquals("/newlocation/", httpget.getPath());
491 
492             Header[] headers = httpget.getRequestHeaders();
493             int cookiecount = 0;
494             for (int i = 0; i < headers.length; i++) {
495                 if ("cookie".equalsIgnoreCase(headers[i].getName())) {
496                     ++cookiecount;
497                 }
498             }
499             assertEquals("There can only be one (cookie)", 1, cookiecount);            
500         } finally {
501             httpget.releaseConnection();
502         }
503     }
504 }