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