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: 280350 $
4    * $Date: 2005-09-12 11:03:03 -0400 (Mon, 12 Sep 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   * Redirection test cases.
49   *
50   * @author Oleg Kalnichevski
51   * 
52   * @version $Id: TestRedirects.java 280350 2005-09-12 15:03:03Z oglueck $
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  		private int statuscode = HttpStatus.SC_MOVED_TEMPORARILY;
77  		private String host = null;
78          private int port;
79  
80          public BasicRedirectService(final String host, int port, int statuscode) {
81              super();
82              this.host = host;
83              this.port = port;
84              if (statuscode > 0) {
85              	this.statuscode = statuscode;
86              }
87          }
88  
89          public BasicRedirectService(final String host, int port) {
90              this(host, port, -1);
91          }
92  
93          public boolean process(final SimpleRequest request, final SimpleResponse response)
94              throws IOException {
95              RequestLine reqline = request.getRequestLine();
96              HttpVersion ver = reqline.getHttpVersion();
97              if (reqline.getUri().equals("/oldlocation/")) {
98                  response.setStatusLine(ver, this.statuscode);
99                  response.addHeader(new Header("Location", 
100                 		"http://" + this.host + ":" + this.port + "/newlocation/"));
101                 response.addHeader(new Header("Connection", "close"));
102             } else if (reqline.getUri().equals("/newlocation/")) {
103                 response.setStatusLine(ver, HttpStatus.SC_OK);
104                 response.setBodyString("Successful redirect");
105             } else {
106                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
107             }
108             return true;
109         }
110     }
111 
112     private class CircularRedirectService implements HttpService {
113 
114         private int invocations = 0;
115         
116         public CircularRedirectService() {
117             super();
118         }
119         
120         public boolean process(final SimpleRequest request, final SimpleResponse response)
121             throws IOException
122         {
123             RequestLine reqline = request.getRequestLine();
124             HttpVersion ver = reqline.getHttpVersion();
125             if (reqline.getUri().startsWith("/circular-oldlocation")) {
126                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
127                 response.addHeader(new Header("Location", "/circular-location2?invk=" + (++this.invocations)));
128             } else if (reqline.getUri().startsWith("/circular-location2")) {
129                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
130                 response.addHeader(new Header("Location", "/circular-oldlocation?invk=" + (++this.invocations)));
131             } else {
132                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
133             }
134             return true;
135         }
136     }
137 
138     private class RelativeRedirectService implements HttpService {
139         
140             public RelativeRedirectService() {
141                 super();
142             }
143 
144             public boolean process(final SimpleRequest request, final SimpleResponse response)
145                 throws IOException
146             {
147                 RequestLine reqline = request.getRequestLine();
148                 HttpVersion ver = reqline.getHttpVersion();
149                 if (reqline.getUri().equals("/oldlocation/")) {
150                     response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
151                     response.addHeader(new Header("Location", "/relativelocation/"));
152                 } else if (reqline.getUri().equals("/relativelocation/")) {
153                     response.setStatusLine(ver, HttpStatus.SC_OK);
154                     response.setBodyString("Successful redirect");
155                 } else {
156                     response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
157                 }
158                 return true;
159             }
160         }
161 
162     private class BogusRedirectService implements HttpService {
163         private String url;
164         
165         public BogusRedirectService(String redirectUrl) {
166             super();
167             this.url = redirectUrl;
168         }
169 
170         public boolean process(final SimpleRequest request, final SimpleResponse response)
171             throws IOException {
172             RequestLine reqline = request.getRequestLine();
173             HttpVersion ver = reqline.getHttpVersion();
174             if (reqline.getUri().equals("/oldlocation/")) {
175                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
176                 response.addHeader(new Header("Location", url));
177             } else if (reqline.getUri().equals("/relativelocation/")) {
178                 response.setStatusLine(ver, HttpStatus.SC_OK);
179                 response.setBodyString("Successful redirect");
180             } else {
181                 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
182             }
183             return true;
184         }
185     }
186 
187     public void testBasicRedirect300() throws IOException {
188         String host = this.server.getLocalAddress();
189         int port = this.server.getLocalPort();
190         this.server.setHttpService(
191                 new BasicRedirectService(host, port, HttpStatus.SC_MULTIPLE_CHOICES));
192         GetMethod httpget = new GetMethod("/oldlocation/");
193         httpget.setFollowRedirects(false);
194         try {
195             this.client.executeMethod(httpget);
196             assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, httpget.getStatusCode());
197             assertEquals("/oldlocation/", httpget.getPath());
198             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
199         } finally {
200             httpget.releaseConnection();
201         }
202     }
203 
204     public void testBasicRedirect301() throws IOException {
205         String host = this.server.getLocalAddress();
206         int port = this.server.getLocalPort();
207         this.server.setHttpService(
208                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_PERMANENTLY));
209         GetMethod httpget = new GetMethod("/oldlocation/");
210         httpget.setFollowRedirects(true);
211         try {
212             this.client.executeMethod(httpget);
213             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
214             assertEquals("/newlocation/", httpget.getPath());
215             assertEquals(host, httpget.getURI().getHost());
216             assertEquals(port, httpget.getURI().getPort());
217             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
218         } finally {
219             httpget.releaseConnection();
220         }
221     }
222 
223     public void testBasicRedirect302() throws IOException {
224         String host = this.server.getLocalAddress();
225         int port = this.server.getLocalPort();
226         this.server.setHttpService(
227                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_TEMPORARILY));
228         GetMethod httpget = new GetMethod("/oldlocation/");
229         httpget.setFollowRedirects(true);
230         try {
231             this.client.executeMethod(httpget);
232             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
233             assertEquals("/newlocation/", httpget.getPath());
234             assertEquals(host, httpget.getURI().getHost());
235             assertEquals(port, httpget.getURI().getPort());
236             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
237         } finally {
238             httpget.releaseConnection();
239         }
240     }
241 
242     public void testBasicRedirect303() throws IOException {
243         String host = this.server.getLocalAddress();
244         int port = this.server.getLocalPort();
245         this.server.setHttpService(
246                 new BasicRedirectService(host, port, HttpStatus.SC_SEE_OTHER));
247         GetMethod httpget = new GetMethod("/oldlocation/");
248         httpget.setFollowRedirects(true);
249         try {
250             this.client.executeMethod(httpget);
251             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
252             assertEquals("/newlocation/", httpget.getPath());
253             assertEquals(host, httpget.getURI().getHost());
254             assertEquals(port, httpget.getURI().getPort());
255             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
256         } finally {
257             httpget.releaseConnection();
258         }
259     }
260 
261     public void testBasicRedirect304() throws IOException {
262         String host = this.server.getLocalAddress();
263         int port = this.server.getLocalPort();
264         this.server.setHttpService(
265                 new BasicRedirectService(host, port, HttpStatus.SC_NOT_MODIFIED));
266         GetMethod httpget = new GetMethod("/oldlocation/");
267         httpget.setFollowRedirects(true);
268         try {
269             this.client.executeMethod(httpget);
270             assertEquals(HttpStatus.SC_NOT_MODIFIED, httpget.getStatusCode());
271             assertEquals("/oldlocation/", httpget.getPath());
272             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
273         } finally {
274             httpget.releaseConnection();
275         }
276     }
277 
278     public void testBasicRedirect305() throws IOException {
279         String host = this.server.getLocalAddress();
280         int port = this.server.getLocalPort();
281         this.server.setHttpService(
282                 new BasicRedirectService(host, port, HttpStatus.SC_USE_PROXY));
283         GetMethod httpget = new GetMethod("/oldlocation/");
284         httpget.setFollowRedirects(true);
285         try {
286             this.client.executeMethod(httpget);
287             assertEquals(HttpStatus.SC_USE_PROXY, httpget.getStatusCode());
288             assertEquals("/oldlocation/", httpget.getPath());
289             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
290         } finally {
291             httpget.releaseConnection();
292         }
293     }
294 
295     public void testBasicRedirect307() throws IOException {
296         String host = this.server.getLocalAddress();
297         int port = this.server.getLocalPort();
298         this.server.setHttpService(
299                 new BasicRedirectService(host, port, HttpStatus.SC_TEMPORARY_REDIRECT));
300         GetMethod httpget = new GetMethod("/oldlocation/");
301         httpget.setFollowRedirects(true);
302         try {
303             this.client.executeMethod(httpget);
304             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
305             assertEquals("/newlocation/", httpget.getPath());
306             assertEquals(host, httpget.getURI().getHost());
307             assertEquals(port, httpget.getURI().getPort());
308             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
309         } finally {
310             httpget.releaseConnection();
311         }
312     }
313 
314     public void testNoRedirect() throws IOException {
315         String host = this.server.getLocalAddress();
316         int port = this.server.getLocalPort();
317         this.server.setHttpService(new BasicRedirectService(host, port));
318         GetMethod httpget = new GetMethod("/oldlocation/");
319         httpget.setFollowRedirects(false);
320         try {
321             this.client.executeMethod(httpget);
322             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httpget.getStatusCode());
323             assertEquals("/oldlocation/", httpget.getPath());
324             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
325         } finally {
326             httpget.releaseConnection();
327         }
328     }
329 
330     public void testMaxRedirectCheck() throws IOException {
331         this.server.setHttpService(new CircularRedirectService());
332         GetMethod httpget = new GetMethod("/circular-oldlocation/");
333         try {
334             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true);
335             this.client.getParams().setIntParameter(HttpClientParams.MAX_REDIRECTS, 5);
336             this.client.executeMethod(httpget);
337             fail("RedirectException exception should have been thrown");
338         }
339         catch (RedirectException e) {
340             // expected
341         } finally {
342             httpget.releaseConnection();
343         }
344     }
345 
346     public void testCircularRedirect() throws IOException {
347         this.server.setHttpService(new CircularRedirectService());
348         GetMethod httpget = new GetMethod("/circular-oldlocation/");
349         try {
350             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false);
351             this.client.executeMethod(httpget);
352             fail("CircularRedirectException exception should have been thrown");
353         } catch (CircularRedirectException expected) {
354         } finally {
355             httpget.releaseConnection();
356         }
357     }
358 
359     public void testPostRedirect() throws IOException {
360         String host = this.server.getLocalAddress();
361         int port = this.server.getLocalPort();
362         this.server.setHttpService(new BasicRedirectService(host, port));
363         PostMethod httppost = new PostMethod("/oldlocation/");
364         httppost.setRequestEntity(new StringRequestEntity("stuff"));
365         try {
366             this.client.executeMethod(httppost);
367             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httppost.getStatusCode());
368             assertEquals("/oldlocation/", httppost.getPath());
369             assertEquals(new URI("/oldlocation/", false), httppost.getURI());
370         } finally {
371         	httppost.releaseConnection();
372         }
373     }
374 
375     public void testRelativeRedirect() throws IOException {
376         String host = this.server.getLocalAddress();
377         int port = this.server.getLocalPort();
378         this.server.setHttpService(new RelativeRedirectService());
379         this.client.getParams().setBooleanParameter(
380                 HttpClientParams.REJECT_RELATIVE_REDIRECT, false);
381         GetMethod httpget = new GetMethod("/oldlocation/");
382         httpget.setFollowRedirects(true);
383         try {
384             this.client.executeMethod(httpget);
385             assertEquals("/relativelocation/", httpget.getPath());
386             assertEquals(host, httpget.getURI().getHost());
387             assertEquals(port, httpget.getURI().getPort());
388             assertEquals(new URI("http://" + host + ":" + port + "/relativelocation/", false), 
389             		httpget.getURI());
390         } finally {
391             httpget.releaseConnection();
392         }
393     }
394 
395     public void testRejectRelativeRedirect() throws IOException {
396         String host = this.server.getLocalAddress();
397         int port = this.server.getLocalPort();
398         this.server.setHttpService(new RelativeRedirectService());
399         this.client.getParams().setBooleanParameter(
400                 HttpClientParams.REJECT_RELATIVE_REDIRECT, true);
401         GetMethod httpget = new GetMethod("/oldlocation/");
402         httpget.setFollowRedirects(true);
403         try {
404             this.client.executeMethod(httpget);
405             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httpget.getStatusCode());
406             assertEquals("/oldlocation/", httpget.getPath());
407             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
408         } finally {
409             httpget.releaseConnection();
410         }
411     }
412 
413     public void testRejectBogusRedirectLocation() throws IOException {
414         String host = this.server.getLocalAddress();
415         int port = this.server.getLocalPort();
416         this.server.setHttpService(new BogusRedirectService("xxx://bogus"));
417         GetMethod httpget = new GetMethod("/oldlocation/");
418         httpget.setFollowRedirects(true);
419         try {
420             this.client.executeMethod(httpget);
421             fail("BogusRedirectService should have been thrown");
422         } catch (IllegalStateException e) {
423         	//expected
424         } finally {
425             httpget.releaseConnection();
426         }
427     }
428 
429     public void testCrossSiteRedirect() throws IOException {
430         String host = this.server.getLocalAddress();
431         int port = this.server.getLocalPort();
432         
433         SimpleHttpServer thatserver = new SimpleHttpServer();
434         this.server.setHttpService(new BasicRedirectService(host, port));
435         thatserver.setHttpService(new BasicRedirectService(host, port));
436         thatserver.setTestname(getName());
437         
438         HostConfiguration hostconfig = new HostConfiguration();
439         hostconfig.setHost(
440                 thatserver.getLocalAddress(), 
441                 thatserver.getLocalPort(),
442                 Protocol.getProtocol("http"));
443 
444         GetMethod httpget = new GetMethod("/oldlocation/");
445         httpget.setFollowRedirects(true);
446         try {
447             this.client.executeMethod(hostconfig, httpget);
448             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
449             assertEquals("/newlocation/", httpget.getPath());
450             assertEquals(host, httpget.getURI().getHost());
451             assertEquals(port, httpget.getURI().getPort());
452             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), 
453             		httpget.getURI());
454         } finally {
455             httpget.releaseConnection();
456         }
457         thatserver.destroy();
458     }
459 
460     public void testRedirectWithCookie() throws IOException {
461     	
462         client.getState().addCookie(new Cookie("localhost", "name", "value", "/", -1, false)); 
463 
464         String host = this.server.getLocalAddress();
465         int port = this.server.getLocalPort();
466 
467         this.server.setHttpService(new BasicRedirectService(host, port));
468         GetMethod httpget = new GetMethod("/oldlocation/");
469         httpget.setFollowRedirects(true);
470         try {
471             this.client.executeMethod(httpget);
472             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
473             assertEquals("/newlocation/", httpget.getPath());
474 
475             Header[] headers = httpget.getRequestHeaders();
476             int cookiecount = 0;
477             for (int i = 0; i < headers.length; i++) {
478                 if ("cookie".equalsIgnoreCase(headers[i].getName())) {
479                     ++cookiecount;
480                 }
481             }
482             assertEquals("There can only be one (cookie)", 1, cookiecount);            
483         } finally {
484             httpget.releaseConnection();
485         }
486     }
487 }