    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: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    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 480424 2006-11-29 05:56:49Z bayard $
    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 }