View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.impl;
29  
30  import org.apache.http.ConnectionReuseStrategy;
31  import org.apache.http.HttpRequest;
32  import org.apache.http.HttpResponse;
33  import org.apache.http.HttpStatus;
34  import org.apache.http.HttpVersion;
35  import org.apache.http.message.BasicHttpRequest;
36  import org.apache.http.message.BasicHttpResponse;
37  import org.apache.http.protocol.BasicHttpContext;
38  import org.apache.http.protocol.HttpContext;
39  import org.apache.http.protocol.HttpCoreContext;
40  import org.junit.Assert;
41  import org.junit.Before;
42  import org.junit.Test;
43  
44  public class TestDefaultConnectionReuseStrategy {
45  
46      /** HTTP context. */
47      private HttpContext context;
48  
49      /** The reuse strategy to be tested. */
50      private ConnectionReuseStrategy reuseStrategy;
51  
52      @Before
53      public void setUp() {
54          reuseStrategy = DefaultConnectionReuseStrategy.INSTANCE;
55          context = new BasicHttpContext(null);
56      }
57  
58      @Test(expected=IllegalArgumentException.class)
59      public void testIllegalResponseArg() throws Exception {
60          reuseStrategy.keepAlive(null, this.context);
61      }
62  
63      @Test(expected=IllegalArgumentException.class)
64      public void testIllegalContextArg() throws Exception {
65          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
66          reuseStrategy.keepAlive(response, null);
67      }
68  
69      @Test
70      public void testNoContentLengthResponseHttp1_0() throws Exception {
71          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
72          Assert.assertFalse(reuseStrategy.keepAlive(response, context));
73      }
74  
75      @Test
76      public void testNoContentLengthResponseHttp1_1() throws Exception {
77          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
78          Assert.assertFalse(reuseStrategy.keepAlive(response, context));
79      }
80  
81      @Test
82      public void testChunkedContent() throws Exception {
83          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
84          response.addHeader("Transfer-Encoding", "chunked");
85          Assert.assertTrue(reuseStrategy.keepAlive(response, context));
86      }
87  
88      @Test
89      public void testIgnoreInvalidKeepAlive() throws Exception {
90          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
91          response.addHeader("Connection", "keep-alive");
92          Assert.assertFalse(reuseStrategy.keepAlive(response, context));
93      }
94  
95      @Test
96      public void testExplicitClose() throws Exception {
97          // Use HTTP 1.1
98          final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
99          response.addHeader("Transfer-Encoding", "chunked");
100         response.addHeader("Connection", "close");
101         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
102     }
103 
104     @Test
105     public void testExplicitKeepAlive() throws Exception {
106         // Use HTTP 1.0
107         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
108         response.addHeader("Content-Length", "10");
109         response.addHeader("Connection", "keep-alive");
110 
111         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
112     }
113 
114     @Test
115     public void testHTTP10Default() throws Exception {
116         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
117         response.addHeader("Content-Length", "10");
118         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
119     }
120 
121     @Test
122     public void testHTTP11Default() throws Exception {
123         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
124         response.addHeader("Content-Length", "10");
125         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
126     }
127 
128     @Test
129     public void testFutureHTTP() throws Exception {
130         final HttpResponse response = new BasicHttpResponse(new HttpVersion(3, 45), 200, "OK");
131         response.addHeader("Content-Length", "10");
132         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
133     }
134 
135     @Test
136     public void testBrokenConnectionDirective1() throws Exception {
137         // Use HTTP 1.0
138         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
139         response.addHeader("Content-Length", "10");
140         response.addHeader("Connection", "keep--alive");
141         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
142     }
143 
144     @Test
145     public void testBrokenConnectionDirective2() throws Exception {
146         // Use HTTP 1.0
147         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK");
148         response.addHeader("Content-Length", "10");
149         response.addHeader("Connection", null);
150         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
151     }
152 
153     @Test
154     public void testConnectionTokens1() throws Exception {
155         // Use HTTP 1.1
156         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
157         response.addHeader("Transfer-Encoding", "chunked");
158         response.addHeader("Connection", "yadda, cLOSe, dumdy");
159         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
160     }
161 
162     @Test
163     public void testConnectionTokens2() throws Exception {
164         // Use HTTP 1.1
165         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
166         response.addHeader("Transfer-Encoding", "chunked");
167         response.addHeader("Connection", "yadda, kEEP-alive, dumdy");
168         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
169     }
170 
171     @Test
172     public void testConnectionTokens3() throws Exception {
173         // Use HTTP 1.1
174         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
175         response.addHeader("Transfer-Encoding", "chunked");
176         response.addHeader("Connection", "yadda, keep-alive, close, dumdy");
177         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
178     }
179 
180     @Test
181     public void testConnectionTokens4() throws Exception {
182         // Use HTTP 1.1
183         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
184         response.addHeader("Transfer-Encoding", "chunked");
185         response.addHeader("Connection", "yadda, close, dumdy");
186         response.addHeader("Proxy-Connection", "keep-alive");
187         // Connection takes precedence over Proxy-Connection
188         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
189     }
190 
191     @Test
192     public void testConnectionTokens5() throws Exception {
193         // Use HTTP 1.1
194         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
195         response.addHeader("Transfer-Encoding", "chunked");
196         response.addHeader("Connection", "yadda, dumdy");
197         response.addHeader("Proxy-Connection", "close");
198         // Connection takes precedence over Proxy-Connection,
199         // even if it doesn't contain a recognized token.
200         // Default for HTTP/1.1 is to keep alive.
201         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
202     }
203 
204     @Test
205     public void testConnectionTokens6() throws Exception {
206         // Use HTTP 1.1
207         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
208         response.addHeader("Transfer-Encoding", "chunked");
209         response.addHeader("Connection", "");
210         response.addHeader("Proxy-Connection", "close");
211         // Connection takes precedence over Proxy-Connection,
212         // even if it is empty. Default for HTTP/1.1 is to keep alive.
213         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
214     }
215 
216     @Test
217     public void testConnectionTokensInvalid() throws Exception {
218         // Use HTTP 1.1
219         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
220         response.addHeader("Transfer-Encoding", "chunked");
221         response.addHeader("Connection", "keep-alive=true");
222         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
223     }
224 
225     @Test
226     public void testMultipleContentLength() throws Exception {
227         // Use HTTP 1.1
228         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
229         response.addHeader("Content-Length", "10");
230         response.addHeader("Content-Length", "11");
231         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
232     }
233 
234     @Test
235     public void testInvalidContentLength() throws Exception {
236         // Use HTTP 1.1
237         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
238         response.addHeader("Content-Length", "crap");
239         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
240     }
241 
242     @Test
243     public void testInvalidNegativeContentLength() throws Exception {
244         // Use HTTP 1.1
245         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
246         response.addHeader("Content-Length", "-10");
247         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
248     }
249 
250     @Test
251     public void testNoContentResponse() throws Exception {
252         // Use HTTP 1.1
253         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
254                 HttpStatus.SC_NO_CONTENT, "No Content");
255         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
256     }
257 
258     @Test
259     public void testNoContentResponseHttp10() throws Exception {
260         // Use HTTP 1.0
261         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0,
262                 HttpStatus.SC_NO_CONTENT, "No Content");
263         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
264     }
265 
266     @Test
267     public void testRequestClose() throws Exception {
268         final HttpRequest request = new BasicHttpRequest("GET", "/");
269         request.addHeader("Connection", "close");
270         context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
271         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
272         response.addHeader("Content-Length", "10");
273         response.addHeader("Connection", "keep-alive");
274 
275         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
276     }
277 
278     @Test
279     public void testHeadRequestWithout() throws Exception {
280         final HttpRequest request = new BasicHttpRequest("HEAD", "/");
281         context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
282         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
283 
284         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
285     }
286 
287     @Test
288     public void testHttp204ContentLengthGreaterThanZero() throws Exception {
289         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 204, "OK");
290         response.addHeader("Content-Length", "10");
291         response.addHeader("Connection", "keep-alive");
292         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
293     }
294 
295     @Test
296     public void testHttp204ContentLengthEqualToZero() throws Exception {
297         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 204, "OK");
298         response.addHeader("Content-Length", "0");
299         response.addHeader("Connection", "keep-alive");
300         Assert.assertTrue(reuseStrategy.keepAlive(response, context));
301     }
302 
303     @Test
304     public void testHttp204ChunkedContent() throws Exception {
305         final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 204, "OK");
306         response.addHeader("Transfer-Encoding", "chunked");
307         response.addHeader("Connection", "keep-alive");
308         Assert.assertFalse(reuseStrategy.keepAlive(response, context));
309     }
310 }
311