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.hc.core5.http.impl;
29  
30  import org.apache.hc.core5.http.ConnectionReuseStrategy;
31  import org.apache.hc.core5.http.HttpRequest;
32  import org.apache.hc.core5.http.HttpResponse;
33  import org.apache.hc.core5.http.HttpStatus;
34  import org.apache.hc.core5.http.HttpVersion;
35  import org.apache.hc.core5.http.Method;
36  import org.apache.hc.core5.http.message.BasicHttpRequest;
37  import org.apache.hc.core5.http.message.BasicHttpResponse;
38  import org.apache.hc.core5.http.protocol.BasicHttpContext;
39  import org.apache.hc.core5.http.protocol.HttpContext;
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=NullPointerException.class)
59      public void testInvalidResponseArg() throws Exception {
60          reuseStrategy.keepAlive(null, null, this.context);
61      }
62  
63      @Test
64      public void testNoContentLengthResponseHttp1_0() throws Exception {
65          context.setProtocolVersion(HttpVersion.HTTP_1_0);
66          final HttpResponse response = new BasicHttpResponse(200, "OK");
67          Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
68      }
69  
70      @Test
71      public void testNoContentLengthResponseHttp1_1() throws Exception {
72          final HttpResponse response = new BasicHttpResponse(200, "OK");
73          Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
74      }
75  
76      @Test
77      public void testChunkedContent() throws Exception {
78          final HttpResponse response = new BasicHttpResponse(200, "OK");
79          response.addHeader("Transfer-Encoding", "chunked");
80          Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
81      }
82  
83      @Test
84      public void testIgnoreInvalidKeepAlive() throws Exception {
85          context.setProtocolVersion(HttpVersion.HTTP_1_0);
86          final HttpResponse response = new BasicHttpResponse(200, "OK");
87          response.addHeader("Connection", "keep-alive");
88          Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
89      }
90  
91      @Test
92      public void testExplicitClose() throws Exception {
93          // Use HTTP 1.1
94          final HttpResponse response = new BasicHttpResponse(200, "OK");
95          response.addHeader("Transfer-Encoding", "chunked");
96          response.addHeader("Connection", "close");
97          Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
98      }
99  
100     @Test
101     public void testExplicitKeepAlive() throws Exception {
102         // Use HTTP 1.0
103         context.setProtocolVersion(HttpVersion.HTTP_1_0);
104         final HttpResponse response = new BasicHttpResponse(200, "OK");
105         response.addHeader("Content-Length", "10");
106         response.addHeader("Connection", "keep-alive");
107 
108         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
109     }
110 
111     @Test
112     public void testHTTP10Default() throws Exception {
113         context.setProtocolVersion(HttpVersion.HTTP_1_0);
114         final HttpResponse response = new BasicHttpResponse(200, "OK");
115         response.addHeader("Content-Length", "10");
116         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
117     }
118 
119     @Test
120     public void testHTTP11Default() throws Exception {
121         final HttpResponse response = new BasicHttpResponse(200, "OK");
122         response.addHeader("Content-Length", "10");
123         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
124     }
125 
126     @Test
127     public void testBrokenConnectionDirective1() throws Exception {
128         // Use HTTP 1.0
129         context.setProtocolVersion(HttpVersion.HTTP_1_0);
130         final HttpResponse response = new BasicHttpResponse(200, "OK");
131         response.addHeader("Content-Length", "10");
132         response.addHeader("Connection", "keep--alive");
133         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
134     }
135 
136     @Test
137     public void testBrokenConnectionDirective2() throws Exception {
138         // Use HTTP 1.0
139         context.setProtocolVersion(HttpVersion.HTTP_1_0);
140         final HttpResponse response = new BasicHttpResponse(200, "OK");
141         response.addHeader("Content-Length", "10");
142         response.addHeader("Connection", null);
143         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
144     }
145 
146     @Test
147     public void testConnectionTokens1() throws Exception {
148         // Use HTTP 1.1
149         final HttpResponse response = new BasicHttpResponse(200, "OK");
150         response.addHeader("Transfer-Encoding", "chunked");
151         response.addHeader("Connection", "yadda, cLOSe, dumdy");
152         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
153     }
154 
155     @Test
156     public void testConnectionTokens2() throws Exception {
157         // Use HTTP 1.1
158         final HttpResponse response = new BasicHttpResponse(200, "OK");
159         response.addHeader("Transfer-Encoding", "chunked");
160         response.addHeader("Connection", "yadda, kEEP-alive, dumdy");
161         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
162     }
163 
164     @Test
165     public void testConnectionTokens3() throws Exception {
166         // Use HTTP 1.1
167         final HttpResponse response = new BasicHttpResponse(200, "OK");
168         response.addHeader("Transfer-Encoding", "chunked");
169         response.addHeader("Connection", "yadda, keep-alive, close, dumdy");
170         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
171     }
172 
173     @Test
174     public void testConnectionTokens4() throws Exception {
175         // Use HTTP 1.1
176         final HttpResponse response = new BasicHttpResponse(200, "OK");
177         response.addHeader("Transfer-Encoding", "chunked");
178         response.addHeader("Connection", "yadda, close, dumdy");
179         response.addHeader("Proxy-Connection", "keep-alive");
180         // Connection takes precedence over Proxy-Connection
181         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
182     }
183 
184     @Test
185     public void testConnectionTokens5() throws Exception {
186         // Use HTTP 1.1
187         final HttpResponse response = new BasicHttpResponse(200, "OK");
188         response.addHeader("Transfer-Encoding", "chunked");
189         response.addHeader("Connection", "yadda, dumdy");
190         response.addHeader("Proxy-Connection", "close");
191         // Connection takes precedence over Proxy-Connection,
192         // even if it doesn't contain a recognized token.
193         // Default for HTTP/1.1 is to keep alive.
194         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
195     }
196 
197     @Test
198     public void testConnectionTokens6() throws Exception {
199         // Use HTTP 1.1
200         final HttpResponse response = new BasicHttpResponse(200, "OK");
201         response.addHeader("Transfer-Encoding", "chunked");
202         response.addHeader("Connection", "");
203         response.addHeader("Proxy-Connection", "close");
204         // Connection takes precedence over Proxy-Connection,
205         // even if it is empty. Default for HTTP/1.1 is to keep alive.
206         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
207     }
208 
209     @Test
210     public void testMultipleContentLength() throws Exception {
211         // Use HTTP 1.1
212         final HttpResponse response = new BasicHttpResponse(200, "OK");
213         response.addHeader("Content-Length", "10");
214         response.addHeader("Content-Length", "11");
215         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
216     }
217 
218     @Test
219     public void testNoContentResponse() throws Exception {
220         // Use HTTP 1.1
221         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content");
222         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
223     }
224 
225     @Test
226     public void testNoContentResponseHttp10() throws Exception {
227         // Use HTTP 1.0
228         context.setProtocolVersion(HttpVersion.HTTP_1_0);
229         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content");
230         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
231     }
232 
233     @Test
234     public void testRequestExplicitClose() throws Exception {
235         final HttpRequest request = new BasicHttpRequest(Method.GET, "/");
236         request.addHeader("Connection", "close");
237 
238         final HttpResponse response = new BasicHttpResponse(200, "OK");
239         response.addHeader("Transfer-Encoding", "chunked");
240         response.addHeader("Connection", "keep-alive");
241         Assert.assertFalse(reuseStrategy.keepAlive(request, response, context));
242     }
243 
244     @Test
245     public void testRequestNoExplicitClose() throws Exception {
246         final HttpRequest request = new BasicHttpRequest(Method.GET, "/");
247         request.addHeader("Connection", "blah, blah, blah");
248 
249         final HttpResponse response = new BasicHttpResponse(200, "OK");
250         response.addHeader("Transfer-Encoding", "chunked");
251         response.addHeader("Connection", "keep-alive");
252         Assert.assertTrue(reuseStrategy.keepAlive(request, response, context));
253     }
254 
255     @Test
256     public void testRequestExplicitCloseMultipleTokens() throws Exception {
257         final HttpRequest request = new BasicHttpRequest(Method.GET, "/");
258         request.addHeader("Connection", "blah, blah, blah");
259         request.addHeader("Connection", "keep-alive");
260         request.addHeader("Connection", "close");
261 
262         final HttpResponse response = new BasicHttpResponse(200, "OK");
263         response.addHeader("Transfer-Encoding", "chunked");
264         response.addHeader("Connection", "keep-alive");
265         Assert.assertFalse(reuseStrategy.keepAlive(request, response, context));
266     }
267 
268     @Test
269     public void testRequestClose() throws Exception {
270         final HttpRequest request = new BasicHttpRequest(Method.GET, "/");
271         request.addHeader("Connection", "close");
272 
273         final HttpResponse response = new BasicHttpResponse(200, "OK");
274         response.addHeader("Content-Length", "10");
275         response.addHeader("Connection", "keep-alive");
276 
277         Assert.assertFalse(reuseStrategy.keepAlive(request, response, context));
278     }
279 
280     @Test
281     public void testHeadRequestWithout() throws Exception {
282         final HttpRequest request = new BasicHttpRequest(Method.HEAD, "/");
283         final HttpResponse response = new BasicHttpResponse(200, "OK");
284 
285         Assert.assertTrue(reuseStrategy.keepAlive(request, response, context));
286     }
287 
288     @Test
289     public void testHttp204ContentLengthGreaterThanZero() throws Exception {
290         final HttpResponse response = new BasicHttpResponse(204, "OK");
291         response.addHeader("Content-Length", "10");
292         response.addHeader("Connection", "keep-alive");
293         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
294     }
295 
296     @Test
297     public void testHttp204ContentLengthEqualToZero() throws Exception {
298         final HttpResponse response = new BasicHttpResponse(204, "OK");
299         response.addHeader("Content-Length", "0");
300         response.addHeader("Connection", "keep-alive");
301         Assert.assertTrue(reuseStrategy.keepAlive(null, response, context));
302     }
303 
304     @Test
305     public void testHttp204ChunkedContent() throws Exception {
306         final HttpResponse response = new BasicHttpResponse(204, "OK");
307         response.addHeader("Transfer-Encoding", "chunked");
308         response.addHeader("Connection", "keep-alive");
309         Assert.assertFalse(reuseStrategy.keepAlive(null, response, context));
310     }
311 }
312