1   /*
2    * ====================================================================
3    *
4    *  Copyright 2003-2004 The Apache Software Foundation
5    *
6    *  Licensed under the Apache License, Version 2.0 (the "License");
7    *  you may not use this file except in compliance with the License.
8    *  You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   * ====================================================================
18   *
19   * This software consists of voluntary contributions made by many
20   * individuals on behalf of the Apache Software Foundation.  For more
21   * information on the Apache Software Foundation, please see
22   * <http://www.apache.org/>.
23   *
24   * [Additional notices, if required by prior licensing conditions]
25   *
26   */
27  package org.apache.commons.httpclient;
28  
29  import java.io.IOException;
30  
31  import junit.framework.*;
32  import org.apache.commons.httpclient.methods.*;
33  import org.apache.commons.httpclient.params.HttpMethodParams;
34  import org.apache.commons.httpclient.server.HttpRequestHandler;
35  import org.apache.commons.httpclient.server.ResponseWriter;
36  import org.apache.commons.httpclient.server.SimpleHttpServerConnection;
37  import org.apache.commons.httpclient.server.SimpleRequest;
38  
39  /***
40   * Tests handling of non-compliant responses.
41   * 
42   * @author Oleg Kalnichevski
43   * @author Jeff Dever
44   */
45  public class TestNoncompliant extends HttpClientTestBase {
46  
47      public TestNoncompliant(String s) throws IOException {
48          super(s);
49      }
50  
51      public static Test suite() {
52          TestSuite suite = new TestSuite(TestNoncompliant.class);
53          return suite;
54      }
55  
56      /***
57       * Tests if client is able able to recover gracefully when HTTP server or
58       * proxy fails to send 100 status code when expected. The client should
59       * resume sending the request body after a defined timeout without having
60       * received "continue" code.
61       */
62      public void testNoncompliantPostMethodString() {
63          this.server.setRequestHandler(new HttpRequestHandler() {
64              public boolean processRequest(SimpleHttpServerConnection conn,
65                      SimpleRequest request) throws IOException {
66                  ResponseWriter out = conn.getWriter();
67                  out.println("HTTP/1.1 200 OK");
68                  out.println("Connection: close");
69                  out.println("Content-Length: 0");
70                  out.println();
71                  out.flush();
72                  return true;
73              }
74          });
75  
76          PostMethod method = new PostMethod("/");
77          method.getParams().setBooleanParameter(
78                  HttpMethodParams.USE_EXPECT_CONTINUE, true);
79          method.setRequestEntity(new StringRequestEntity(
80                  "This is data to be sent in the body of an HTTP POST."));
81          try {
82              client.executeMethod(method);
83          } catch (Exception e) {
84              e.printStackTrace();
85              fail("Unexpected exception: " + e.toString());
86          }
87          assertEquals(200, method.getStatusCode());
88      }
89  
90      /***
91       * Tests that a response status line containing \r and \n is handled.
92       */
93      public void testNoncompliantStatusLine() {
94          this.server.setRequestHandler(new HttpRequestHandler() {
95              public boolean processRequest(SimpleHttpServerConnection conn,
96                      SimpleRequest request) throws IOException {
97                  ResponseWriter out = conn.getWriter();
98                  out.println("HTTP/1.1 444 This status message contains\n"
99                          + " a newline and a\r"
100                         + " carrage return but that should be OK.");
101                 out.println("Connection: close");
102                 out.println("Content-Length: 0");
103                 out.println();
104                 out.flush();
105                 return true;
106             }
107         });
108         GetMethod method = new GetMethod("/");
109         try {
110             client.executeMethod(method);
111         } catch (Exception e) {
112             e.printStackTrace();
113             fail("Unexpected exception: " + e.toString());
114         }
115         assertEquals(444, method.getStatusCode());
116     }
117 
118     /***
119      * Test if a response to HEAD method from non-compliant server that contains
120      * an unexpected body content can be correctly redirected
121      */
122     public void testNoncompliantHeadWithResponseBody() throws Exception {
123         final String body = "Test body";
124         this.server.setRequestHandler(new HttpRequestHandler() {
125             public boolean processRequest(SimpleHttpServerConnection conn,
126                     SimpleRequest request) throws IOException {
127                 ResponseWriter out = conn.getWriter();
128                 out.println("HTTP/1.1 200 OK");
129                 out.println("Connection: close");
130                 out.println("Content-Length: " + body.length());
131                 out.println();
132                 out.print(body);
133                 out.flush();
134                 return true;
135             }
136         });
137         HeadMethod method = new HeadMethod("/");
138         method.getParams().setIntParameter(
139                 HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50);
140         client.executeMethod(method);
141         assertEquals(200, method.getStatusCode());
142         method.releaseConnection();
143     }
144 
145     /***
146      * Test if a response to HEAD method from non-compliant server causes an
147      * HttpException to be thrown
148      */
149     public void testNoncompliantHeadStrictMode() throws Exception {
150         final String body = "Test body";
151         this.server.setRequestHandler(new HttpRequestHandler() {
152             public boolean processRequest(SimpleHttpServerConnection conn,
153                     SimpleRequest request) throws IOException {
154                 ResponseWriter out = conn.getWriter();
155                 out.println("HTTP/1.1 200 OK");
156                 out.println("Connection: close");
157                 out.println("Content-Length: " + body.length());
158                 out.println();
159                 out.print(body);
160                 out.flush();
161                 return true;
162             }
163         });
164         client.getParams().setBooleanParameter(
165                 HttpMethodParams.REJECT_HEAD_BODY, true);
166         HeadMethod method = new NoncompliantHeadMethod("/");
167         method.getParams().setIntParameter(
168                 HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50);
169         try {
170             client.executeMethod(method);
171             fail("HttpException should have been thrown");
172         } catch (HttpException e) {
173             // Expected
174         }
175         method.releaseConnection();
176     }
177 
178 }