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.nio.integration;
29  
30  import java.io.BufferedWriter;
31  import java.io.IOException;
32  import java.io.OutputStream;
33  import java.io.OutputStreamWriter;
34  import java.net.InetSocketAddress;
35  import java.net.Socket;
36  import java.util.concurrent.CountDownLatch;
37  import java.util.concurrent.TimeUnit;
38  
39  import org.apache.http.HttpCoreNIOTestBase;
40  import org.apache.http.HttpException;
41  import org.apache.http.HttpRequest;
42  import org.apache.http.HttpResponse;
43  import org.apache.http.HttpVersion;
44  import org.apache.http.LoggingClientConnectionFactory;
45  import org.apache.http.LoggingServerConnectionFactory;
46  import org.apache.http.concurrent.Cancellable;
47  import org.apache.http.entity.BasicHttpEntity;
48  import org.apache.http.entity.ContentType;
49  import org.apache.http.impl.DefaultConnectionReuseStrategy;
50  import org.apache.http.impl.DefaultHttpResponseFactory;
51  import org.apache.http.impl.nio.DefaultNHttpClientConnection;
52  import org.apache.http.impl.nio.DefaultNHttpServerConnection;
53  import org.apache.http.message.BasicHttpResponse;
54  import org.apache.http.nio.ContentEncoder;
55  import org.apache.http.nio.IOControl;
56  import org.apache.http.nio.NHttpConnectionFactory;
57  import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
58  import org.apache.http.nio.protocol.HttpAsyncExchange;
59  import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
60  import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
61  import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
62  import org.apache.http.nio.protocol.HttpAsyncResponseProducer;
63  import org.apache.http.nio.protocol.HttpAsyncService;
64  import org.apache.http.nio.reactor.IOReactorStatus;
65  import org.apache.http.nio.reactor.ListenerEndpoint;
66  import org.apache.http.params.HttpParams;
67  import org.apache.http.protocol.HttpContext;
68  import org.junit.After;
69  import org.junit.Assert;
70  import org.junit.Before;
71  import org.junit.Test;
72  
73  public class TestHttpAsyncHandlerCancellable extends HttpCoreNIOTestBase {
74  
75      @Before
76      public void setUp() throws Exception {
77          initServer();
78      }
79  
80      @After
81      public void tearDown() throws Exception {
82          shutDownServer();
83      }
84  
85      @Override
86      protected NHttpConnectionFactory<DefaultNHttpServerConnection> createServerConnectionFactory(
87              final HttpParams params) throws Exception {
88          return new LoggingServerConnectionFactory(params);
89      }
90  
91      @Override
92      protected NHttpConnectionFactory<DefaultNHttpClientConnection> createClientConnectionFactory(
93              final HttpParams params) throws Exception {
94          return new LoggingClientConnectionFactory(params);
95      }
96  
97      @Test
98      public void testResponsePrematureTermination() throws Exception {
99          
100         final CountDownLatch latch = new CountDownLatch(1);
101         final HttpAsyncResponseProducer responseProducer = new HttpAsyncResponseProducer() {
102             
103             public HttpResponse generateResponse() {
104                 HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
105                 BasicHttpEntity entity = new BasicHttpEntity();
106                 entity.setContentType(ContentType.DEFAULT_BINARY.toString());
107                 entity.setChunked(true);
108                 response.setEntity(entity);
109                 return response;
110             }
111             
112             public void close() throws IOException {
113                 latch.countDown();
114             }
115             
116             public void responseCompleted(final HttpContext context) {
117             }
118             
119             public void produceContent(
120                     final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
121                 // suspend output
122                 ioctrl.suspendOutput();
123             }
124             
125             public void failed(final Exception ex) {
126             }
127 
128         };
129         
130         HttpAsyncRequestHandlerRegistry registry = new HttpAsyncRequestHandlerRegistry();
131         registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() {
132 
133             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
134                     final HttpRequest request,
135                     final HttpContext context) throws HttpException, IOException {
136                 return new BasicAsyncRequestConsumer();
137             }
138 
139             public void handle(
140                     final HttpRequest data, 
141                     final HttpAsyncExchange httpExchange, 
142                     final HttpContext context)
143                     throws HttpException, IOException {
144                 httpExchange.submitResponse(responseProducer);
145             }
146             
147         });
148         HttpAsyncService serviceHandler = new HttpAsyncService(
149                 this.serverHttpProc,
150                 new DefaultConnectionReuseStrategy(),
151                 new DefaultHttpResponseFactory(),
152                 registry,
153                 null,
154                 this.serverParams);
155         this.server.start(serviceHandler);
156 
157         ListenerEndpoint endpoint = this.server.getListenerEndpoint();
158         endpoint.waitFor();
159 
160         Assert.assertEquals("Test server status", IOReactorStatus.ACTIVE, this.server.getStatus());
161         InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
162         Socket socket = new Socket("localhost", address.getPort());
163         try {
164             OutputStream outstream = socket.getOutputStream();
165             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outstream, "US-ASCII"));
166             writer.write("GET /long HTTP/1.1\r\n");
167             writer.write("Host: localhost\r\n");
168             writer.write("\r\n");
169             writer.flush();
170             
171             Thread.sleep(250);
172             
173             writer.close();
174         } finally {
175             socket.close();
176         }
177 
178         Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
179     }
180 
181     @Test
182     public void testRequestCancelled() throws Exception {
183         
184         final CountDownLatch latch = new CountDownLatch(1);
185         final Cancellable cancellable = new Cancellable() {
186             
187             public boolean cancel() {
188                 latch.countDown();
189                 return true;
190             }
191         };
192         
193         HttpAsyncRequestHandlerRegistry registry = new HttpAsyncRequestHandlerRegistry();
194         registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() {
195 
196             public HttpAsyncRequestConsumer<HttpRequest> processRequest(
197                     final HttpRequest request,
198                     final HttpContext context) throws HttpException, IOException {
199                 return new BasicAsyncRequestConsumer();
200             }
201 
202             public void handle(
203                     final HttpRequest data, 
204                     final HttpAsyncExchange httpExchange, 
205                     final HttpContext context)
206                     throws HttpException, IOException {
207                 httpExchange.setCallback(cancellable);
208                 // do not submit a response;
209             }
210             
211         });
212         HttpAsyncService serviceHandler = new HttpAsyncService(
213                 this.serverHttpProc,
214                 new DefaultConnectionReuseStrategy(),
215                 new DefaultHttpResponseFactory(),
216                 registry,
217                 null,
218                 this.serverParams);
219         this.server.start(serviceHandler);
220 
221         ListenerEndpoint endpoint = this.server.getListenerEndpoint();
222         endpoint.waitFor();
223 
224         Assert.assertEquals("Test server status", IOReactorStatus.ACTIVE, this.server.getStatus());
225         InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
226         Socket socket = new Socket("localhost", address.getPort());
227         try {
228             OutputStream outstream = socket.getOutputStream();
229             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outstream, "US-ASCII"));
230             writer.write("GET /long HTTP/1.1\r\n");
231             writer.write("Host: localhost\r\n");
232             writer.write("\r\n");
233             writer.flush();
234             
235             Thread.sleep(250);
236             
237             writer.close();
238         } finally {
239             socket.close();
240         }
241 
242         Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
243     }
244 
245 }