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  package org.apache.http.nio.client.integration;
28  
29  import java.io.IOException;
30  import java.net.InetSocketAddress;
31  import java.util.concurrent.CountDownLatch;
32  import java.util.concurrent.TimeUnit;
33  
34  import org.apache.http.HttpAsyncTestBase;
35  import org.apache.http.HttpConnection;
36  import org.apache.http.HttpException;
37  import org.apache.http.HttpHost;
38  import org.apache.http.HttpRequest;
39  import org.apache.http.HttpResponse;
40  import org.apache.http.client.methods.HttpGet;
41  import org.apache.http.concurrent.FutureCallback;
42  import org.apache.http.config.ConnectionConfig;
43  import org.apache.http.entity.ContentType;
44  import org.apache.http.impl.DefaultConnectionReuseStrategy;
45  import org.apache.http.impl.DefaultHttpResponseFactory;
46  import org.apache.http.impl.nio.DefaultNHttpServerConnection;
47  import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
48  import org.apache.http.impl.nio.client.HttpAsyncClients;
49  import org.apache.http.nio.ContentEncoder;
50  import org.apache.http.nio.IOControl;
51  import org.apache.http.nio.NHttpConnectionFactory;
52  import org.apache.http.nio.entity.NStringEntity;
53  import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
54  import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
55  import org.apache.http.nio.protocol.HttpAsyncExchange;
56  import org.apache.http.nio.protocol.HttpAsyncExpectationVerifier;
57  import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
58  import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
59  import org.apache.http.nio.protocol.HttpAsyncRequestHandlerMapper;
60  import org.apache.http.nio.protocol.HttpAsyncService;
61  import org.apache.http.nio.protocol.UriHttpAsyncRequestHandlerMapper;
62  import org.apache.http.nio.reactor.IOReactorStatus;
63  import org.apache.http.nio.reactor.ListenerEndpoint;
64  import org.apache.http.protocol.HttpContext;
65  import org.apache.http.protocol.HttpCoreContext;
66  import org.junit.After;
67  import org.junit.Assert;
68  import org.junit.Before;
69  import org.junit.Test;
70  
71  public class TestHttpAsyncPrematureTermination extends HttpAsyncTestBase {
72  
73      @Before
74      public void setUp() throws Exception {
75          initServer();
76          initConnectionManager();
77      }
78  
79      @After
80      public void tearDown() throws Exception {
81          shutDownClient();
82          shutDownServer();
83      }
84  
85      @Override
86      protected NHttpConnectionFactory<DefaultNHttpServerConnection> createServerConnectionFactory(
87              final ConnectionConfig config) throws Exception {
88          return new DefaultNHttpServerConnectionFactory(config);
89      }
90  
91      @Override
92      protected String getSchemeName() {
93          return "http";
94      }
95  
96      private HttpHost start(
97              final HttpAsyncRequestHandlerMapper requestHandlerResolver,
98              final HttpAsyncExpectationVerifier expectationVerifier) throws Exception {
99          final HttpAsyncService serviceHandler = new HttpAsyncService(
100                 this.serverHttpProc,
101                 DefaultConnectionReuseStrategy.INSTANCE,
102                 DefaultHttpResponseFactory.INSTANCE,
103                 requestHandlerResolver,
104                 expectationVerifier);
105 
106         this.httpclient = HttpAsyncClients.custom()
107                 .setConnectionManager(this.connMgr)
108                 .build();
109 
110         this.server.start(serviceHandler);
111         this.httpclient.start();
112 
113         final ListenerEndpoint endpoint = this.server.getListenerEndpoint();
114         endpoint.waitFor();
115 
116         Assert.assertEquals("Test server status", IOReactorStatus.ACTIVE, this.server.getStatus());
117         final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
118         return new HttpHost("localhost", address.getPort(), getSchemeName());
119     }
120 
121     @Test
122     public void testConnectionTerminatedProcessingRequest() throws Exception {
123         final UriHttpAsyncRequestHandlerMapper registry = new UriHttpAsyncRequestHandlerMapper();
124         registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() {
125 
126             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
127                     final HttpRequest request,
128                     final HttpContext context) throws HttpException, IOException {
129                 final HttpConnection conn = (HttpConnection) context.getAttribute(
130                         HttpCoreContext.HTTP_CONNECTION);
131                 conn.shutdown();
132                 return new BasicAsyncRequestConsumer();
133             }
134 
135             public void handle(
136                     final HttpRequest request,
137                     final HttpAsyncExchange httpExchange,
138                     final HttpContext context) throws HttpException, IOException {
139                 final HttpResponse response = httpExchange.getResponse();
140                 response.setEntity(new NStringEntity("all is well", ContentType.TEXT_PLAIN));
141                 httpExchange.submitResponse();
142             }
143 
144         });
145 
146         this.httpclient = HttpAsyncClients.custom()
147                 .setConnectionManager(this.connMgr)
148                 .build();
149 
150         final HttpHost target = start(registry, null);
151         final HttpGet httpget = new HttpGet("/");
152 
153         final CountDownLatch latch = new CountDownLatch(1);
154 
155         final FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
156 
157             public void cancelled() {
158                 latch.countDown();
159             }
160 
161             public void failed(final Exception ex) {
162                 latch.countDown();
163             }
164 
165             public void completed(final HttpResponse response) {
166                 Assert.fail();
167             }
168 
169         };
170 
171         this.httpclient.execute(target, httpget, callback);
172         Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
173     }
174 
175     @Test
176     public void testConnectionTerminatedHandlingRequest() throws Exception {
177         final UriHttpAsyncRequestHandlerMapper registry = new UriHttpAsyncRequestHandlerMapper();
178         registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() {
179 
180             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
181                     final HttpRequest request,
182                     final HttpContext context) throws HttpException, IOException {
183                 return new BasicAsyncRequestConsumer();
184             }
185 
186             public void handle(
187                     final HttpRequest request,
188                     final HttpAsyncExchange httpExchange,
189                     final HttpContext context) throws HttpException, IOException {
190                 final HttpConnection conn = (HttpConnection) context.getAttribute(
191                         HttpCoreContext.HTTP_CONNECTION);
192                 conn.shutdown();
193                 final HttpResponse response = httpExchange.getResponse();
194                 response.setEntity(new NStringEntity("all is well", ContentType.TEXT_PLAIN));
195                 httpExchange.submitResponse();
196             }
197 
198         });
199 
200         this.httpclient = HttpAsyncClients.custom()
201                 .setConnectionManager(this.connMgr)
202                 .build();
203 
204         final HttpHost target = start(registry, null);
205         final HttpGet httpget = new HttpGet("/");
206 
207         final CountDownLatch latch = new CountDownLatch(1);
208 
209         final FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
210 
211             public void cancelled() {
212                 latch.countDown();
213             }
214 
215             public void failed(final Exception ex) {
216                 latch.countDown();
217             }
218 
219             public void completed(final HttpResponse response) {
220                 Assert.fail();
221             }
222 
223         };
224 
225         this.httpclient.execute(target, httpget, callback);
226         Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
227     }
228 
229     @Test
230     public void testConnectionTerminatedSendingResponse() throws Exception {
231         final UriHttpAsyncRequestHandlerMapper registry = new UriHttpAsyncRequestHandlerMapper();
232         registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() {
233 
234             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
235                     final HttpRequest request,
236                     final HttpContext context) throws HttpException, IOException {
237                 return new BasicAsyncRequestConsumer();
238             }
239 
240             public void handle(
241                     final HttpRequest request,
242                     final HttpAsyncExchange httpExchange,
243                     final HttpContext context) throws HttpException, IOException {
244                 final HttpResponse response = httpExchange.getResponse();
245                 response.setEntity(new NStringEntity("all is well", ContentType.TEXT_PLAIN));
246                 httpExchange.submitResponse(new BasicAsyncResponseProducer(response) {
247 
248                     @Override
249                     public synchronized void produceContent(
250                             final ContentEncoder encoder,
251                             final IOControl ioctrl) throws IOException {
252                         ioctrl.shutdown();
253                     }
254 
255                 });
256             }
257 
258         });
259 
260         this.httpclient = HttpAsyncClients.custom()
261                 .setConnectionManager(this.connMgr)
262                 .build();
263 
264         final HttpHost target = start(registry, null);
265         final HttpGet httpget = new HttpGet("/");
266 
267         final CountDownLatch latch = new CountDownLatch(1);
268 
269         final FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
270 
271             public void cancelled() {
272                 latch.countDown();
273             }
274 
275             public void failed(final Exception ex) {
276                 latch.countDown();
277             }
278 
279             public void completed(final HttpResponse response) {
280                 Assert.fail();
281             }
282 
283         };
284 
285         this.httpclient.execute(target, httpget, callback);
286         Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
287     }
288 
289 }