• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/protocol/HttpRequestExecutor.java $
3  * $Revision: 576073 $
4  * $Date: 2007-09-16 03:53:13 -0700 (Sun, 16 Sep 2007) $
5  *
6  * ====================================================================
7  * Licensed to the Apache Software Foundation (ASF) under one
8  * or more contributor license agreements.  See the NOTICE file
9  * distributed with this work for additional information
10  * regarding copyright ownership.  The ASF licenses this file
11  * to you under the Apache License, Version 2.0 (the
12  * "License"); you may not use this file except in compliance
13  * with the License.  You may obtain a copy of the License at
14  *
15  *   http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing,
18  * software distributed under the License is distributed on an
19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20  * KIND, either express or implied.  See the License for the
21  * specific language governing permissions and limitations
22  * under the License.
23  * ====================================================================
24  *
25  * This software consists of voluntary contributions made by many
26  * individuals on behalf of the Apache Software Foundation.  For more
27  * information on the Apache Software Foundation, please see
28  * <http://www.apache.org/>.
29  *
30  */
31 
32 package org.apache.http.protocol;
33 
34 import java.io.IOException;
35 import java.net.ProtocolException;
36 
37 import org.apache.http.HttpClientConnection;
38 import org.apache.http.HttpEntityEnclosingRequest;
39 import org.apache.http.HttpException;
40 import org.apache.http.HttpRequest;
41 import org.apache.http.HttpResponse;
42 import org.apache.http.HttpStatus;
43 import org.apache.http.HttpVersion;
44 import org.apache.http.ProtocolVersion;
45 import org.apache.http.params.CoreProtocolPNames;
46 
47 /**
48  * Sends HTTP requests and receives the responses.
49  * Takes care of request preprocessing and response postprocessing
50  * by the respective interceptors.
51  *
52  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
53  *
54  * @version $Revision: 576073 $
55  *
56  * @since 4.0
57  *
58  * @deprecated Please use {@link java.net.URL#openConnection} instead.
59  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
60  *     for further details.
61  */
62 @Deprecated
63 public class HttpRequestExecutor {
64 
65     /**
66      * Create a new request executor.
67      */
HttpRequestExecutor()68     public HttpRequestExecutor() {
69         super();
70     }
71 
72     /**
73      * Decide whether a response comes with an entity.
74      * The implementation in this class is based on RFC 2616.
75      * Unknown methods and response codes are supposed to
76      * indicate responses with an entity.
77      * <br/>
78      * Derived executors can override this method to handle
79      * methods and response codes not specified in RFC 2616.
80      *
81      * @param request   the request, to obtain the executed method
82      * @param response  the response, to obtain the status code
83      */
canResponseHaveBody(final HttpRequest request, final HttpResponse response)84     protected boolean canResponseHaveBody(final HttpRequest request,
85                                           final HttpResponse response) {
86 
87         if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
88             return false;
89         }
90         int status = response.getStatusLine().getStatusCode();
91         return status >= HttpStatus.SC_OK
92             && status != HttpStatus.SC_NO_CONTENT
93             && status != HttpStatus.SC_NOT_MODIFIED
94             && status != HttpStatus.SC_RESET_CONTENT;
95     }
96 
97     /**
98      * Synchronously send a request and obtain the response.
99      *
100      * @param request   the request to send. It will be preprocessed.
101      * @param conn      the open connection over which to send
102      *
103      * @return  the response to the request, postprocessed
104      *
105      * @throws HttpException      in case of a protocol or processing problem
106      * @throws IOException        in case of an I/O problem
107      */
execute( final HttpRequest request, final HttpClientConnection conn, final HttpContext context)108     public HttpResponse execute(
109             final HttpRequest request,
110             final HttpClientConnection conn,
111             final HttpContext context)
112                 throws IOException, HttpException {
113         if (request == null) {
114             throw new IllegalArgumentException("HTTP request may not be null");
115         }
116         if (conn == null) {
117             throw new IllegalArgumentException("Client connection may not be null");
118         }
119         if (context == null) {
120             throw new IllegalArgumentException("HTTP context may not be null");
121         }
122 
123         try {
124             HttpResponse response = doSendRequest(request, conn, context);
125             if (response == null) {
126                 response = doReceiveResponse(request, conn, context);
127             }
128             return response;
129         } catch (IOException ex) {
130             conn.close();
131             throw ex;
132         } catch (HttpException ex) {
133             conn.close();
134             throw ex;
135         } catch (RuntimeException ex) {
136             conn.close();
137             throw ex;
138         }
139     }
140 
141     /**
142      * Prepare a request for sending.
143      *
144      * @param request   the request to prepare
145      * @param processor the processor to use
146      * @param context   the context for sending the request
147      *
148      * @throws HttpException      in case of a protocol or processing problem
149      * @throws IOException        in case of an I/O problem
150      */
preProcess( final HttpRequest request, final HttpProcessor processor, final HttpContext context)151     public void preProcess(
152             final HttpRequest request,
153             final HttpProcessor processor,
154             final HttpContext context)
155                 throws HttpException, IOException {
156         if (request == null) {
157             throw new IllegalArgumentException("HTTP request may not be null");
158         }
159         if (processor == null) {
160             throw new IllegalArgumentException("HTTP processor may not be null");
161         }
162         if (context == null) {
163             throw new IllegalArgumentException("HTTP context may not be null");
164         }
165         processor.process(request, context);
166     }
167 
168     /**
169      * Send a request over a connection.
170      * This method also handles the expect-continue handshake if necessary.
171      * If it does not have to handle an expect-continue handshake, it will
172      * not use the connection for reading or anything else that depends on
173      * data coming in over the connection.
174      *
175      * @param request   the request to send, already
176      *                  {@link #preProcess preprocessed}
177      * @param conn      the connection over which to send the request,
178      *                  already established
179      * @param context   the context for sending the request
180      *
181      * @return  a terminal response received as part of an expect-continue
182      *          handshake, or
183      *          <code>null</code> if the expect-continue handshake is not used
184      *
185      * @throws HttpException      in case of a protocol or processing problem
186      * @throws IOException        in case of an I/O problem
187      */
doSendRequest( final HttpRequest request, final HttpClientConnection conn, final HttpContext context)188     protected HttpResponse doSendRequest(
189             final HttpRequest request,
190             final HttpClientConnection conn,
191             final HttpContext context)
192                 throws IOException, HttpException {
193         if (request == null) {
194             throw new IllegalArgumentException("HTTP request may not be null");
195         }
196         if (conn == null) {
197             throw new IllegalArgumentException("HTTP connection may not be null");
198         }
199         if (context == null) {
200             throw new IllegalArgumentException("HTTP context may not be null");
201         }
202 
203         HttpResponse response = null;
204         context.setAttribute(ExecutionContext.HTTP_REQ_SENT, Boolean.FALSE);
205 
206         conn.sendRequestHeader(request);
207         if (request instanceof HttpEntityEnclosingRequest) {
208             // Check for expect-continue handshake. We have to flush the
209             // headers and wait for an 100-continue response to handle it.
210             // If we get a different response, we must not send the entity.
211             boolean sendentity = true;
212             final ProtocolVersion ver =
213                 request.getRequestLine().getProtocolVersion();
214             if (((HttpEntityEnclosingRequest) request).expectContinue() &&
215                 !ver.lessEquals(HttpVersion.HTTP_1_0)) {
216 
217                 conn.flush();
218                 // As suggested by RFC 2616 section 8.2.3, we don't wait for a
219                 // 100-continue response forever. On timeout, send the entity.
220                 int tms = request.getParams().getIntParameter(
221                         CoreProtocolPNames.WAIT_FOR_CONTINUE, 2000);
222 
223                 if (conn.isResponseAvailable(tms)) {
224                     response = conn.receiveResponseHeader();
225                     if (canResponseHaveBody(request, response)) {
226                         conn.receiveResponseEntity(response);
227                     }
228                     int status = response.getStatusLine().getStatusCode();
229                     if (status < 200) {
230                         if (status != HttpStatus.SC_CONTINUE) {
231                             throw new ProtocolException(
232                                     "Unexpected response: " + response.getStatusLine());
233                         }
234                         // discard 100-continue
235                         response = null;
236                     } else {
237                         sendentity = false;
238                     }
239                 }
240             }
241             if (sendentity) {
242                 conn.sendRequestEntity((HttpEntityEnclosingRequest) request);
243             }
244         }
245         conn.flush();
246         context.setAttribute(ExecutionContext.HTTP_REQ_SENT, Boolean.TRUE);
247         return response;
248     }
249 
250     /**
251      * Wait for and receive a response.
252      * This method will automatically ignore intermediate responses
253      * with status code 1xx.
254      *
255      * @param request   the request for which to obtain the response
256      * @param conn      the connection over which the request was sent
257      * @param context   the context for receiving the response
258      *
259      * @return  the final response, not yet post-processed
260      *
261      * @throws HttpException      in case of a protocol or processing problem
262      * @throws IOException        in case of an I/O problem
263      */
doReceiveResponse( final HttpRequest request, final HttpClientConnection conn, final HttpContext context)264     protected HttpResponse doReceiveResponse(
265             final HttpRequest          request,
266             final HttpClientConnection conn,
267             final HttpContext          context)
268                 throws HttpException, IOException {
269         if (request == null) {
270             throw new IllegalArgumentException("HTTP request may not be null");
271         }
272         if (conn == null) {
273             throw new IllegalArgumentException("HTTP connection may not be null");
274         }
275         if (context == null) {
276             throw new IllegalArgumentException("HTTP context may not be null");
277         }
278 
279         HttpResponse response = null;
280         int statuscode = 0;
281 
282         while (response == null || statuscode < HttpStatus.SC_OK) {
283 
284             response = conn.receiveResponseHeader();
285             if (canResponseHaveBody(request, response)) {
286                 conn.receiveResponseEntity(response);
287             }
288             statuscode = response.getStatusLine().getStatusCode();
289 
290         } // while intermediate response
291 
292         return response;
293 
294     }
295 
296     /**
297      * Finish a response.
298      * This includes post-processing of the response object.
299      * It does <i>not</i> read the response entity, if any.
300      * It does <i>not</i> allow for immediate re-use of the
301      * connection over which the response is coming in.
302      *
303      * @param response  the response object to finish
304      * @param processor the processor to use
305      * @param context   the context for post-processing the response
306      *
307      * @throws HttpException      in case of a protocol or processing problem
308      * @throws IOException        in case of an I/O problem
309      */
postProcess( final HttpResponse response, final HttpProcessor processor, final HttpContext context)310     public void postProcess(
311             final HttpResponse response,
312             final HttpProcessor processor,
313             final HttpContext context)
314                 throws HttpException, IOException {
315         if (response == null) {
316             throw new IllegalArgumentException("HTTP response may not be null");
317         }
318         if (processor == null) {
319             throw new IllegalArgumentException("HTTP processor may not be null");
320         }
321         if (context == null) {
322             throw new IllegalArgumentException("HTTP context may not be null");
323         }
324         processor.process(response, context);
325     }
326 
327 } // class HttpRequestExecutor
328