1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/test/org/apache/commons/httpclient/TestResponseHeaders.java $
3    * $Revision: 1425331 $
4    * $Date: 2012-12-22 19:29:41 +0100 (Sat, 22 Dec 2012) $
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   * [Additional notices, if required by prior licensing conditions]
29   *
30   */
31  
32  package org.apache.commons.httpclient;
33  
34  import java.io.IOException;
35  
36  import junit.framework.Test;
37  import junit.framework.TestSuite;
38  
39  import org.apache.commons.httpclient.methods.GetMethod;
40  import org.apache.commons.httpclient.server.HttpRequestHandler;
41  import org.apache.commons.httpclient.server.HttpService;
42  import org.apache.commons.httpclient.server.ResponseWriter;
43  import org.apache.commons.httpclient.server.SimpleHttpServerConnection;
44  import org.apache.commons.httpclient.server.SimpleRequest;
45  import org.apache.commons.httpclient.server.SimpleResponse;
46  
47  /***
48   * Tests for reading response headers.
49   *
50   * @author <a href="mailto:dims@apache.org">Davanum Srinivas</a>
51   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
52   * @author <a href="mailto:adrian@intencha.com">Adrian Sutton</a>
53   * @version $Id: TestResponseHeaders.java 608014 2008-01-02 05:48:53Z rolandw $
54   */
55  public class TestResponseHeaders extends HttpClientTestBase {
56  
57      private AccessibleHttpConnectionManager connectionManager;
58      
59      // ------------------------------------------------------------ Constructor
60      public TestResponseHeaders(final String testName) throws IOException {
61          super(testName);
62      }
63      
64      public void setUp() throws IOException {
65          super.setUp();
66          this.connectionManager = new AccessibleHttpConnectionManager();
67          this.client.setHttpConnectionManager(connectionManager);
68      }
69  
70      // ------------------------------------------------------------------- Main
71      public static void main(String args[]) {
72          String[] testCaseName = {TestResponseHeaders.class.getName()};
73          junit.textui.TestRunner.main(testCaseName);
74      }
75  
76      // ------------------------------------------------------- TestCase Methods
77      public static Test suite() {
78          return new TestSuite(TestResponseHeaders.class);
79      }
80  
81      // ----------------------------------------------------------- Test Methods
82      public void testHeaders() throws Exception {
83          final String body = "XXX\r\nYYY\r\nZZZ";
84          this.server.setHttpService(new HttpService() {
85              public boolean process(SimpleRequest request,
86                      SimpleResponse response) throws IOException {
87                  response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
88                  response.addHeader(new Header("Connection", "close"));
89                  response.addHeader(new Header("Content-Length", Integer.toString(body.length())));
90                  response.addHeader(new Header("Content-Type", "text/xml; charset=utf-8"));
91                  response.addHeader(new Header("Date", "Wed, 28 Mar 2001 05:05:04 GMT"));
92                  response.addHeader(new Header("Server", "UserLand Frontier/7.0-WinNT"));
93                  response.setBodyString(body);
94                  return true;
95              }
96          });
97          
98          HttpMethod method = new GetMethod();
99          client.executeMethod(method);
100         assertEquals("close", method.getResponseHeader("Connection").getValue());
101         assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
102         assertEquals("text/xml; charset=utf-8", method.getResponseHeader("Content-Type").getValue());
103         assertEquals("Wed, 28 Mar 2001 05:05:04 GMT", method.getResponseHeader("Date").getValue());
104         assertEquals("UserLand Frontier/7.0-WinNT", method.getResponseHeader("Server").getValue());
105     }
106 
107     /***
108      * Tests that having a duplicate content length causes no problems.
109      */    
110     public void testDuplicateContentLength() throws Exception {
111         
112         final String body = "XXX\r\nYYY\r\nZZZ";
113         this.server.setHttpService(new HttpService() {
114             public boolean process(SimpleRequest request,
115                     SimpleResponse response) throws IOException {
116                 response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
117                 response.addHeader(new Header("Content-Length", Integer.toString(body.length())));
118                 response.addHeader(new Header("Content-Length", Integer.toString(body.length())));
119                 response.setBodyString(body);
120                 return true;
121             }
122         });
123         HttpMethod method = new GetMethod();
124         client.executeMethod(method);
125         assertNotNull( "Response body is null.", method.getResponseBodyAsStream() );
126     }
127 
128     public void testDuplicateConnection() throws Exception {
129         
130         this.server.setHttpService(new HttpService() {
131             public boolean process(SimpleRequest request,
132                     SimpleResponse response) throws IOException {
133                 response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
134                 response.addHeader(new Header("Connection", "close"));
135                 response.addHeader(new Header("Connection", "close"));
136                 return true;
137             }
138         });
139 
140         GetMethod method = new GetMethod("/");
141         client.executeMethod(method);
142         method.getResponseBodyAsString();
143         
144         assertFalse(connectionManager.getConection().isOpen());
145 
146         this.server.setHttpService(new HttpService() {
147             public boolean process(SimpleRequest request,
148                     SimpleResponse response) throws IOException {
149                 response.setStatusLine(HttpVersion.HTTP_1_0, 200);
150                 response.addHeader(new Header("Connection", "keep-alive"));
151                 response.addHeader(new Header("Connection", "keep-alive"));
152                 response.setBodyString("aa");
153                 return true;
154             }
155         });
156 
157         method = new GetMethod("/");
158         client.executeMethod(method);
159         method.getResponseBodyAsString();
160         
161         assertTrue(connectionManager.getConection().isOpen());
162     }
163     
164     public void testNoContentLength() throws Exception {
165         // test with connection header
166         this.server.setRequestHandler(new HttpRequestHandler() {
167             public boolean processRequest(SimpleHttpServerConnection conn,
168                     SimpleRequest request) throws IOException {
169                 ResponseWriter out = conn.getWriter();
170                 out.println("HTTP/1.1 200 OK");
171                 out.println("Connection: keep-alive");
172                 out.println();
173                 out.println("12345");
174                 out.flush();
175                 return true;
176             }
177         });
178 
179         GetMethod method = new GetMethod("/");
180         client.executeMethod(method);
181         method.getResponseBodyAsString();
182         
183         assertFalse(connectionManager.getConection().isOpen());
184         
185         // test without connection header
186         this.server.setRequestHandler(new HttpRequestHandler() {
187             public boolean processRequest(SimpleHttpServerConnection conn,
188                     SimpleRequest request) throws IOException {
189                 ResponseWriter out = conn.getWriter();
190                 out.println("HTTP/1.1 200 OK");
191                 out.println();
192                 out.println("12345");
193                 out.flush();
194                 return true;
195             }
196         });
197 
198         // test with connection header
199         method = new GetMethod("/");
200         client.executeMethod(method);
201         method.getResponseBodyAsString();
202         
203         assertFalse(connectionManager.getConection().isOpen());
204     }
205 
206     public void testInvalidContentLength1() throws Exception {
207         this.server.setHttpService(new HttpService() {
208             public boolean process(SimpleRequest request,
209                     SimpleResponse response) throws IOException {
210                 response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
211                 response.addHeader(new Header("Content-Length", "5"));
212                 response.addHeader(new Header("Content-Length", "stuff"));
213                 response.setBodyString("12345");
214                 return true;
215             }
216         });
217         GetMethod method = new GetMethod("/");
218         client.executeMethod(method);
219         assertEquals(5, method.getResponseContentLength()); 
220     }
221 
222     public void testInvalidContentLength2() throws Exception {
223         this.server.setHttpService(new HttpService() {
224             public boolean process(SimpleRequest request,
225                     SimpleResponse response) throws IOException {
226                 response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
227                 response.addHeader(new Header("Content-Length", "stuff"));
228                 response.addHeader(new Header("Content-Length", "5"));
229                 response.setBodyString("12345");
230                 return true;
231             }
232         });
233         GetMethod method = new GetMethod("/");
234         client.executeMethod(method);
235         assertEquals(5, method.getResponseContentLength()); 
236     }
237 
238     public void testProxyNoContentLength() throws Exception {
239         // test with proxy-connection header
240         this.server.setRequestHandler(new HttpRequestHandler() {
241             public boolean processRequest(SimpleHttpServerConnection conn,
242                     SimpleRequest request) throws IOException {
243                 ResponseWriter out = conn.getWriter();
244                 out.println("HTTP/1.1 200 OK");
245                 out.println("proxy-connection: keep-alive");
246                 out.println();
247                 out.println("12345");
248                 out.flush();
249                 return true;
250             }
251         });
252 
253         client.getHostConfiguration().setProxy(server.getLocalAddress(), server.getLocalPort());
254         GetMethod method = new GetMethod("/");
255         client.executeMethod(method);
256         method.getResponseBodyAsString();
257         
258         assertFalse(connectionManager.getConection().isOpen());
259 
260         // test without proxy-connection header
261         this.server.setRequestHandler(new HttpRequestHandler() {
262             public boolean processRequest(SimpleHttpServerConnection conn,
263                     SimpleRequest request) throws IOException {
264                 ResponseWriter out = conn.getWriter();
265                 out.println("HTTP/1.1 200 OK");
266                 out.println();
267                 out.println("12345");
268                 out.flush();
269                 return true;
270             }
271         });
272 
273         method = new GetMethod("/");
274         client.executeMethod(method);
275         method.getResponseBodyAsString();
276         
277         assertFalse(connectionManager.getConection().isOpen());
278     }
279 
280     public void testNullHeaders() throws Exception {
281         this.server.setHttpService(new HttpService() {
282             public boolean process(SimpleRequest request,
283                     SimpleResponse response) throws IOException {
284                 response.setStatusLine(request.getRequestLine().getHttpVersion(), 200);
285                 response.addHeader(new Header("Connection", "close"));
286                 response.setBodyString("XXX\r\nYYY\r\nZZZ");
287                 return true;
288             }
289         });
290         HttpMethod method = new GetMethod("/");
291         client.executeMethod(method);
292         assertEquals(null, method.getResponseHeader(null));
293         assertEquals(null, method.getResponseHeader("bogus"));
294     }
295     
296     public void testFoldedHeaders() throws Exception {
297         final String body = "XXX\r\nYYY\r\nZZZ";
298         this.server.setRequestHandler(new HttpRequestHandler() {
299             public boolean processRequest(SimpleHttpServerConnection conn,
300                     SimpleRequest request) throws IOException {
301                 ResponseWriter out = conn.getWriter();
302                 out.println("HTTP/1.1 200 OK");
303                 out.println("Connection: close");
304                 out.println("Content-Length: " + body.length());
305                 out.println("Content-Type: text/xml; charset=utf-8");
306                 out.println("\tboundary=XXXX");
307                 out.println("Date: Wed, 28 Mar 2001");
308                 out.println(" 05:05:04 GMT");
309                 out.println("Server: UserLand Frontier/7.0-WinNT");
310                 out.println();
311                 out.println(body);
312                 out.flush();
313                 return true;
314             }
315         });
316         HttpMethod method = new GetMethod("/");
317         client.executeMethod(method);
318         assertEquals("close", method.getResponseHeader("Connection").getValue());
319         assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
320         assertEquals("text/xml; charset=utf-8 boundary=XXXX", method.getResponseHeader("Content-Type").getValue());
321         assertEquals("Wed, 28 Mar 2001 05:05:04 GMT", method.getResponseHeader("Date").getValue());
322         assertEquals("UserLand Frontier/7.0-WinNT", method.getResponseHeader("Server").getValue());
323         assertTrue(method.getResponseHeader("Content-Type").toString().indexOf("boundary") != -1);
324     }
325 
326 
327 	public void testForceCloseConnection() throws Exception {
328         this.server.setRequestHandler(new HttpRequestHandler() {
329             public boolean processRequest(SimpleHttpServerConnection conn,
330                     SimpleRequest request) throws IOException {
331                 ResponseWriter out = conn.getWriter();
332                 out.println("HTTP/1.1 200 OK");
333                 out.println("Content-Type: garbage");
334                 out.println();
335                 out.println("stuff");
336                 out.flush();
337                 return true;
338             }
339         });
340         FakeHttpMethod method = new FakeHttpMethod();
341         client.executeMethod(method);
342 		assertTrue("Connection should be closed", 
343                 method.shouldCloseConnection(connectionManager.getConection()));
344 		assertTrue("Connection should be force-closed", method.isConnectionCloseForced());
345 	}
346     
347 	public void testForceCloseConnection2() throws Exception {
348         this.server.setRequestHandler(new HttpRequestHandler() {
349             public boolean processRequest(SimpleHttpServerConnection conn,
350                     SimpleRequest request) throws IOException {
351                 ResponseWriter out = conn.getWriter();
352                 out.println("HTTP/1.1 200 OK");
353                 out.println("Content-Type: garbage");
354                 out.println("Connection: close");
355                 out.println();
356                 out.println("stuff");
357                 out.flush();
358                 return true;
359             }
360         });
361         FakeHttpMethod method = new FakeHttpMethod();
362         client.executeMethod(method);
363 		assertTrue("Connection should be closed", 
364                 method.shouldCloseConnection(connectionManager.getConection()));
365 		assertFalse("Connection should NOT be closed", method.isConnectionCloseForced());
366 	}
367     
368     public void testNoContent() throws Exception {
369         // test with connection header
370         this.server.setRequestHandler(new HttpRequestHandler() {
371             public boolean processRequest(SimpleHttpServerConnection conn,
372                     SimpleRequest request) throws IOException {
373                 ResponseWriter out = conn.getWriter();
374                 out.println("HTTP/1.1 204 NO CONTENT");
375                 out.println();
376                 out.flush();
377                 return true;
378             }
379         });
380 
381         GetMethod method = new GetMethod("/");
382         client.executeMethod(method);
383         method.getResponseBodyAsString();
384 
385         assertTrue(connectionManager.getConection().isOpen());
386 
387         // test without connection header
388         this.server.setRequestHandler(new HttpRequestHandler() {
389             public boolean processRequest(SimpleHttpServerConnection conn,
390                     SimpleRequest request) throws IOException {
391                 ResponseWriter out = conn.getWriter();
392                 out.println("HTTP/1.1 204 NO CONTENT");
393                 out.println("Connection: keep-alive");
394                 out.println();
395                 out.flush();
396                 return true;
397             }
398         });
399 
400         // test with connection header
401         method = new GetMethod("/");
402         client.executeMethod(method);
403         method.getResponseBodyAsString();
404 
405         assertTrue(connectionManager.getConection().isOpen());
406     }
407     
408 }