1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/TestRedirects.java,v 1.9 2005/01/14 19:40:39 olegk Exp $
3    * $Revision: 155418 $
4    * $Date: 2005-02-26 08:01:52 -0500 (Sat, 26 Feb 2005) $
5    * ====================================================================
6    *
7    *  Copyright 1999-2004 The Apache Software Foundation
8    *
9    *  Licensed under the Apache License, Version 2.0 (the "License");
10   *  you may not use this file except in compliance with the License.
11   *  You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing, software
16   *  distributed under the License is distributed on an "AS IS" BASIS,
17   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   *  See the License for the specific language governing permissions and
19   *  limitations under the License.
20   * ====================================================================
21   *
22   * This software consists of voluntary contributions made by many
23   * individuals on behalf of the Apache Software Foundation.  For more
24   * information on the Apache Software Foundation, please see
25   * <http://www.apache.org/>.
26   *
27   */
28  
29  package org.apache.commons.httpclient;
30  
31  import java.io.IOException;
32  
33  import junit.framework.Test;
34  import junit.framework.TestSuite;
35  
36  import org.apache.commons.httpclient.methods.GetMethod;
37  import org.apache.commons.httpclient.methods.PostMethod;
38  import org.apache.commons.httpclient.methods.StringRequestEntity;
39  import org.apache.commons.httpclient.params.HttpClientParams;
40  import org.apache.commons.httpclient.protocol.Protocol;
41  import org.apache.commons.httpclient.server.HttpService;
42  import org.apache.commons.httpclient.server.RequestLine;
43  import org.apache.commons.httpclient.server.SimpleHttpServer;
44  import org.apache.commons.httpclient.server.SimpleRequest;
45  import org.apache.commons.httpclient.server.SimpleResponse;
46  
47  /***
48   * Basic authentication test cases.
49   *
50   * @author Oleg Kalnichevski
51   * 
52   * @version $Id: TestRedirects.java 155418 2005-02-26 13:01:52Z dirkv $
53   */
54  public class TestRedirects extends HttpClientTestBase {
55  
56      // ------------------------------------------------------------ Constructor
57      public TestRedirects(final String testName) throws IOException {
58          super(testName);
59      }
60  
61      // ------------------------------------------------------------------- Main
62      public static void main(String args[]) {
63          String[] testCaseName = { TestRedirects.class.getName() };
64          junit.textui.TestRunner.main(testCaseName);
65      }
66  
67      // ------------------------------------------------------- TestCase Methods
68  
69      public static Test suite() {
70          TestSuite suite = new TestSuite(TestRedirects.class);
71          ProxyTestDecorator.addTests(suite);
72          return suite;
73      }
74  
75      private class BasicRedirectService implements HttpService {
76          
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              {
97                  RequestLine reqline = request.getRequestLine();
98                  HttpVersion ver = reqline.getHttpVersion();
99                  if (reqline.getUri().equals("/oldlocation/")) {
100                     response.setStatusLine(ver, this.statuscode);
101                     response.addHeader(new Header("Location", 
102                     		"http://" + this.host + ":" + this.port + "/newlocation/"));
103                     response.addHeader(new Header("Connection", "close"));
104                 } else if (reqline.getUri().equals("/newlocation/")) {
105                     response.setStatusLine(ver, HttpStatus.SC_OK);
106                     response.setBodyString("Successful redirect");
107                 } else {
108                     response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
109                 }
110                 return true;
111             }
112         }
113 
114     private class CircularRedirectService implements HttpService {
115 
116         private int invocations = 0;
117         
118         public CircularRedirectService() {
119             super();
120         }
121         
122         public boolean process(final SimpleRequest request, final SimpleResponse response)
123             throws IOException
124         {
125             RequestLine reqline = request.getRequestLine();
126             HttpVersion ver = reqline.getHttpVersion();
127             if (reqline.getUri().startsWith("/circular-oldlocation")) {
128                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
129                 response.addHeader(new Header("Location", "/circular-location2?invk=" + (++this.invocations)));
130             } else if (reqline.getUri().startsWith("/circular-location2")) {
131                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
132                 response.addHeader(new Header("Location", "/circular-oldlocation?invk=" + (++this.invocations)));
133             } else {
134                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
135             }
136             return true;
137         }
138     }
139 
140     private class RelativeRedirectService implements HttpService {
141         
142             public RelativeRedirectService() {
143                 super();
144             }
145 
146             public boolean process(final SimpleRequest request, final SimpleResponse response)
147                 throws IOException
148             {
149                 RequestLine reqline = request.getRequestLine();
150                 HttpVersion ver = reqline.getHttpVersion();
151                 if (reqline.getUri().equals("/oldlocation/")) {
152                     response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
153                     response.addHeader(new Header("Location", "/relativelocation/"));
154                 } else if (reqline.getUri().equals("/relativelocation/")) {
155                     response.setStatusLine(ver, HttpStatus.SC_OK);
156                     response.setBodyString("Successful redirect");
157                 } else {
158                     response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
159                 }
160                 return true;
161             }
162         }
163 
164     private class BogusRedirectService implements HttpService {
165         
166             public BogusRedirectService() {
167                 super();
168             }
169 
170             public boolean process(final SimpleRequest request, final SimpleResponse response)
171                 throws IOException
172             {
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", "xxx://bogus"));
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"));
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());
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 testCrossSiteRedirect() throws IOException {
431         String host = this.server.getLocalAddress();
432         int port = this.server.getLocalPort();
433         
434         SimpleHttpServer thatserver = new SimpleHttpServer();
435         this.server.setHttpService(new BasicRedirectService(host, port));
436         thatserver.setHttpService(new BasicRedirectService(host, port));
437         thatserver.setTestname(getName());
438         
439         HostConfiguration hostconfig = new HostConfiguration();
440         hostconfig.setHost(
441                 thatserver.getLocalAddress(), 
442                 thatserver.getLocalPort(),
443                 Protocol.getProtocol("http"));
444 
445         GetMethod httpget = new GetMethod("/oldlocation/");
446         httpget.setFollowRedirects(true);
447         try {
448             this.client.executeMethod(hostconfig, httpget);
449             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
450             assertEquals("/newlocation/", httpget.getPath());
451             assertEquals(host, httpget.getURI().getHost());
452             assertEquals(port, httpget.getURI().getPort());
453             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), 
454             		httpget.getURI());
455         } finally {
456             httpget.releaseConnection();
457         }
458         thatserver.destroy();
459     }
460 
461     public void testRedirectWithCookie() throws IOException {
462     	
463         client.getState().addCookie(new Cookie("localhost", "name", "value", "/", -1, false)); 
464 
465         String host = this.server.getLocalAddress();
466         int port = this.server.getLocalPort();
467 
468         this.server.setHttpService(new BasicRedirectService(host, port));
469         GetMethod httpget = new GetMethod("/oldlocation/");
470         httpget.setFollowRedirects(true);
471         try {
472             this.client.executeMethod(httpget);
473             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
474             assertEquals("/newlocation/", httpget.getPath());
475 
476             Header[] headers = httpget.getRequestHeaders();
477             int cookiecount = 0;
478             for (int i = 0; i < headers.length; i++) {
479                 if ("cookie".equalsIgnoreCase(headers[i].getName())) {
480                     ++cookiecount;
481                 }
482             }
483             assertEquals("There can only be one (cookie)", 1, cookiecount);            
484         } finally {
485             httpget.releaseConnection();
486         }
487     }
488 }