1   /*
2    * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestRedirects.java,v 1.8 2004/11/13 12:21:28 olegk Exp $
3    * $Revision: 1.8 $
4    * $Date: 2004/11/13 12:21:28 $
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,v 1.8 2004/11/13 12:21:28 olegk Exp $
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         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().equals("/circular-oldlocation/")) {
126                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
127                 response.addHeader(new Header("Location", "/circular-location2/"));
128             } else if (reqline.getUri().equals("/circular-location2/")) {
129                 response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
130                 response.addHeader(new Header("Location", "/circular-oldlocation/"));
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         
164             public BogusRedirectService() {
165                 super();
166             }
167 
168             public boolean process(final SimpleRequest request, final SimpleResponse response)
169                 throws IOException
170             {
171                 RequestLine reqline = request.getRequestLine();
172                 HttpVersion ver = reqline.getHttpVersion();
173                 if (reqline.getUri().equals("/oldlocation/")) {
174                     response.setStatusLine(ver, HttpStatus.SC_MOVED_TEMPORARILY);
175                     response.addHeader(new Header("Location", "xxx://bogus"));
176                 } else if (reqline.getUri().equals("/relativelocation/")) {
177                     response.setStatusLine(ver, HttpStatus.SC_OK);
178                     response.setBodyString("Successful redirect");
179                 } else {
180                     response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
181                 }
182                 return true;
183             }
184         }
185     
186     public void testBasicRedirect300() throws IOException {
187         String host = this.server.getLocalAddress();
188         int port = this.server.getLocalPort();
189         this.server.setHttpService(
190                 new BasicRedirectService(host, port, HttpStatus.SC_MULTIPLE_CHOICES));
191         GetMethod httpget = new GetMethod("/oldlocation/");
192         httpget.setFollowRedirects(false);
193         try {
194             this.client.executeMethod(httpget);
195             assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, httpget.getStatusCode());
196             assertEquals("/oldlocation/", httpget.getPath());
197             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
198         } finally {
199             httpget.releaseConnection();
200         }
201     }
202 
203     public void testBasicRedirect301() throws IOException {
204         String host = this.server.getLocalAddress();
205         int port = this.server.getLocalPort();
206         this.server.setHttpService(
207                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_PERMANENTLY));
208         GetMethod httpget = new GetMethod("/oldlocation/");
209         httpget.setFollowRedirects(true);
210         try {
211             this.client.executeMethod(httpget);
212             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
213             assertEquals("/newlocation/", httpget.getPath());
214             assertEquals(host, httpget.getURI().getHost());
215             assertEquals(port, httpget.getURI().getPort());
216             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
217         } finally {
218             httpget.releaseConnection();
219         }
220     }
221 
222     public void testBasicRedirect302() throws IOException {
223         String host = this.server.getLocalAddress();
224         int port = this.server.getLocalPort();
225         this.server.setHttpService(
226                 new BasicRedirectService(host, port, HttpStatus.SC_MOVED_TEMPORARILY));
227         GetMethod httpget = new GetMethod("/oldlocation/");
228         httpget.setFollowRedirects(true);
229         try {
230             this.client.executeMethod(httpget);
231             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
232             assertEquals("/newlocation/", httpget.getPath());
233             assertEquals(host, httpget.getURI().getHost());
234             assertEquals(port, httpget.getURI().getPort());
235             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
236         } finally {
237             httpget.releaseConnection();
238         }
239     }
240 
241     public void testBasicRedirect303() throws IOException {
242         String host = this.server.getLocalAddress();
243         int port = this.server.getLocalPort();
244         this.server.setHttpService(
245                 new BasicRedirectService(host, port, HttpStatus.SC_SEE_OTHER));
246         GetMethod httpget = new GetMethod("/oldlocation/");
247         httpget.setFollowRedirects(true);
248         try {
249             this.client.executeMethod(httpget);
250             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
251             assertEquals("/newlocation/", httpget.getPath());
252             assertEquals(host, httpget.getURI().getHost());
253             assertEquals(port, httpget.getURI().getPort());
254             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
255         } finally {
256             httpget.releaseConnection();
257         }
258     }
259 
260     public void testBasicRedirect304() throws IOException {
261         String host = this.server.getLocalAddress();
262         int port = this.server.getLocalPort();
263         this.server.setHttpService(
264                 new BasicRedirectService(host, port, HttpStatus.SC_NOT_MODIFIED));
265         GetMethod httpget = new GetMethod("/oldlocation/");
266         httpget.setFollowRedirects(true);
267         try {
268             this.client.executeMethod(httpget);
269             assertEquals(HttpStatus.SC_NOT_MODIFIED, httpget.getStatusCode());
270             assertEquals("/oldlocation/", httpget.getPath());
271             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
272         } finally {
273             httpget.releaseConnection();
274         }
275     }
276 
277     public void testBasicRedirect305() throws IOException {
278         String host = this.server.getLocalAddress();
279         int port = this.server.getLocalPort();
280         this.server.setHttpService(
281                 new BasicRedirectService(host, port, HttpStatus.SC_USE_PROXY));
282         GetMethod httpget = new GetMethod("/oldlocation/");
283         httpget.setFollowRedirects(true);
284         try {
285             this.client.executeMethod(httpget);
286             assertEquals(HttpStatus.SC_USE_PROXY, httpget.getStatusCode());
287             assertEquals("/oldlocation/", httpget.getPath());
288             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
289         } finally {
290             httpget.releaseConnection();
291         }
292     }
293 
294     public void testBasicRedirect307() throws IOException {
295         String host = this.server.getLocalAddress();
296         int port = this.server.getLocalPort();
297         this.server.setHttpService(
298                 new BasicRedirectService(host, port, HttpStatus.SC_TEMPORARY_REDIRECT));
299         GetMethod httpget = new GetMethod("/oldlocation/");
300         httpget.setFollowRedirects(true);
301         try {
302             this.client.executeMethod(httpget);
303             assertEquals(HttpStatus.SC_OK, httpget.getStatusCode());
304             assertEquals("/newlocation/", httpget.getPath());
305             assertEquals(host, httpget.getURI().getHost());
306             assertEquals(port, httpget.getURI().getPort());
307             assertEquals(new URI("http://" + host + ":" + port + "/newlocation/", false), httpget.getURI());
308         } finally {
309             httpget.releaseConnection();
310         }
311     }
312 
313     public void testNoRedirect() throws IOException {
314         String host = this.server.getLocalAddress();
315         int port = this.server.getLocalPort();
316         this.server.setHttpService(new BasicRedirectService(host, port));
317         GetMethod httpget = new GetMethod("/oldlocation/");
318         httpget.setFollowRedirects(false);
319         try {
320             this.client.executeMethod(httpget);
321             assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, httpget.getStatusCode());
322             assertEquals("/oldlocation/", httpget.getPath());
323             assertEquals(new URI("/oldlocation/", false), httpget.getURI());
324         } finally {
325             httpget.releaseConnection();
326         }
327     }
328 
329     public void testMaxRedirectCheck() throws IOException {
330         this.server.setHttpService(new CircularRedirectService());
331         GetMethod httpget = new GetMethod("/circular-oldlocation/");
332         try {
333             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true);
334             this.client.getParams().setIntParameter(HttpClientParams.MAX_REDIRECTS, 5);
335             this.client.executeMethod(httpget);
336             fail("RedirectException exception should have been thrown");
337         }
338         catch (RedirectException e) {
339             // expected
340         } finally {
341             httpget.releaseConnection();
342         }
343     }
344 
345     public void testCircularRedirect() throws IOException {
346         this.server.setHttpService(new CircularRedirectService());
347         GetMethod httpget = new GetMethod("/circular-oldlocation/");
348         try {
349             this.client.getParams().setBooleanParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false);
350             this.client.executeMethod(httpget);
351             fail("RedirectException exception should have been thrown");
352         }
353         catch (RedirectException e) {
354             // 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 }