Changelog:

* Decoupled the process of request preparation and response finalization from the process of request execution (something Roland long insisted upon). This makes it possible to retry the request execution in case of an I/O failure without re-running HTTP protocol interceptors on the failed request 


git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@535512 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2007-05-05 12:02:53 +00:00
parent d6159be52e
commit 060a84532e
5 changed files with 86 additions and 32 deletions

View File

@ -52,7 +52,6 @@
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.HttpRequestInterceptorList;
import org.apache.http.protocol.HttpResponseInterceptorList;
@ -363,16 +362,12 @@ public final HttpResponse execute(RoutedRequest roureq, HttpContext context)
// Populate the context for this request
populateContext(context);
}
// Create a copy of the HTTP processor
BasicHttpProcessor httpproc = getHttpProcessor().copy();
// Create an HTTP request executor for this request
HttpRequestExecutor reqexec = new HttpRequestExecutor(httpproc);
reqexec.setParams(getParams());
// Create a director for this request
director = new DefaultClientRequestDirector(
getConnectionManager(),
getConnectionReuseStrategy(),
reqexec);
getHttpProcessor().copy(),
getParams());
}
HttpResponse response = director.execute(roureq, context);

View File

@ -48,8 +48,10 @@
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.RouteDirector;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpRequestExecutor;
@ -79,18 +81,22 @@ public class DefaultClientRequestDirector
/** The request executor. */
protected final HttpRequestExecutor requestExec;
/** The HTTP protocol processor. */
protected final HttpProcessor httpProcessor;
/** The currently allocated connection. */
protected ManagedClientConnection managedConn;
public DefaultClientRequestDirector(ClientConnectionManager conman,
ConnectionReuseStrategy reustrat,
HttpRequestExecutor reqexec) {
HttpProcessor httpProcessor,
HttpParams params) {
this.connManager = conman;
this.reuseStrategy = reustrat;
this.requestExec = reqexec;
this.requestExec = new HttpRequestExecutor(params);
this.httpProcessor = httpProcessor;
this.managedConn = null;
//@@@ authentication?
@ -124,6 +130,11 @@ public HttpResponse execute(RoutedRequest roureq, HttpContext context)
allocateConnection(roureq.getRoute());
establishRoute(roureq.getRoute(), context);
context.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
roureq.getRoute().getTargetHost());
context.setAttribute(HttpExecutionContext.HTTP_CONNECTION,
managedConn);
HttpRequest prepreq = prepareRequest(roureq, context);
//@@@ handle authentication here or via interceptor?
@ -131,10 +142,13 @@ public HttpResponse execute(RoutedRequest roureq, HttpContext context)
((AbortableHttpRequest) prepreq).setReleaseTrigger(managedConn);
}
context.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
roureq.getRoute().getTargetHost());
context.setAttribute(HttpExecutionContext.HTTP_REQUEST,
prepreq);
response = requestExec.execute(prepreq, managedConn, context);
finalizeResponse(response, context);
RoutedRequest followup =
handleResponse(roureq, prepreq, response, context);
if (followup == null) {
@ -336,10 +350,11 @@ protected HttpRequest createConnectRequest(HttpRoute route,
*/
protected HttpRequest prepareRequest(RoutedRequest roureq,
HttpContext context)
throws HttpException {
throws IOException, HttpException {
HttpRequest prepared = roureq.getRequest();
requestExec.preProcess(prepared, httpProcessor, context);
//@@@ Instantiate a wrapper to prevent modification of the original
//@@@ request object? It might be needed for retries.
//@@@ If proxied and non-tunnelled, make sure an absolute URL is
@ -350,6 +365,20 @@ protected HttpRequest prepareRequest(RoutedRequest roureq,
} // prepareRequest
/**
* Finalizes the response received as a result of the request execution.
*
* @param response the response received
* @param context the context used for the current request execution
*/
protected void finalizeResponse(HttpResponse response,
HttpContext context)
throws IOException, HttpException {
requestExec.postProcess(response, httpProcessor, context);
} // finalizeResponse
/**
* Analyzes a response to check need for a followup.
*

View File

@ -42,6 +42,7 @@
import org.apache.http.entity.StringEntity;
import org.apache.http.localserver.LocalTestServer;
import org.apache.http.localserver.ServerTestBase;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.util.EntityUtils;
@ -77,8 +78,20 @@ public void testEcho() throws Exception {
request.setEntity(new StringEntity(message, charset));
HttpClientConnection conn = connectTo(target);
httpContext.setAttribute(
HttpExecutionContext.HTTP_CONNECTION, conn);
httpContext.setAttribute(
HttpExecutionContext.HTTP_TARGET_HOST, target);
httpContext.setAttribute(
HttpExecutionContext.HTTP_REQUEST, request);
httpExecutor.preProcess
(request, httpProcessor, httpContext);
HttpResponse response = httpExecutor.execute
(request, conn, httpContext);
httpExecutor.postProcess
(response, httpProcessor, httpContext);
assertEquals("wrong status in response", HttpStatus.SC_OK,
response.getStatusLine().getStatusCode());
@ -106,8 +119,20 @@ public void testRandom() throws Exception {
HttpGet request = new HttpGet(uri);
HttpClientConnection conn = connectTo(target);
httpContext.setAttribute(
HttpExecutionContext.HTTP_CONNECTION, conn);
httpContext.setAttribute(
HttpExecutionContext.HTTP_TARGET_HOST, target);
httpContext.setAttribute(
HttpExecutionContext.HTTP_REQUEST, request);
httpExecutor.preProcess
(request, httpProcessor, httpContext);
HttpResponse response = httpExecutor.execute
(request, conn, httpContext);
httpExecutor.postProcess
(response, httpProcessor, httpContext);
assertEquals("(" + sizes[i] + ") wrong status in response",
HttpStatus.SC_OK,

View File

@ -31,30 +31,24 @@
package org.apache.http.impl.conn;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.params.HttpParams;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.util.EntityUtils;
import org.apache.http.conn.Scheme;
import org.apache.http.conn.SchemeRegistry;
import org.apache.http.conn.SocketFactory;
import org.apache.http.conn.PlainSocketFactory;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.conn.HttpRoute;
import org.apache.http.conn.HostConfiguration; //@@@ deprecated
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.SchemeRegistry;
import org.apache.http.conn.params.HttpConnectionManagerParams;
import org.apache.http.localserver.ServerTestBase;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpExecutionContext;
import org.apache.http.util.EntityUtils;
/**
@ -126,7 +120,8 @@ public void testSkeleton() throws Exception {
ThreadSafeClientConnManager mgr = createTSCCM(mgrpar, null);
final HttpRoute route = new HttpRoute(getServerHttp(), null, false);
HttpHost target = getServerHttp();
final HttpRoute route = new HttpRoute(target, null, false);
final String uri = "/random/8"; // read 8 bytes
HttpRequest request =
@ -135,8 +130,19 @@ public void testSkeleton() throws Exception {
ManagedClientConnection conn = mgr.getConnection(route);
conn.open(route, httpContext, defaultParams);
httpContext.setAttribute(
HttpExecutionContext.HTTP_CONNECTION, conn);
httpContext.setAttribute(
HttpExecutionContext.HTTP_TARGET_HOST, target);
httpContext.setAttribute(
HttpExecutionContext.HTTP_REQUEST, request);
httpExecutor.preProcess
(request, httpProcessor, httpContext);
HttpResponse response =
httpExecutor.execute(request, conn, httpContext);
httpExecutor.postProcess
(response, httpProcessor, httpContext);
assertEquals("wrong status in response",
HttpStatus.SC_OK,

View File

@ -136,8 +136,7 @@ protected void setUp() throws Exception {
}
if (httpExecutor == null) {
httpExecutor = new HttpRequestExecutor(httpProcessor);
httpExecutor.setParams(defaultParams);
httpExecutor = new HttpRequestExecutor(defaultParams);
}
if (localServer == null) {