Resolved a long standing problem with HttpClient not taking into account the user context when pooling / re-using connections. HttpClient now correctly handles stateful / user specific connections such as persistent NTLM connections and SSL connections with client side authentication.
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@658759 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
db8947ac50
commit
6d0c809900
|
@ -1,6 +1,12 @@
|
|||
Changes since 4.0 Alpha 4
|
||||
-------------------
|
||||
|
||||
* Resolved a long standing problem with HttpClient not taking into account
|
||||
the user context when pooling / re-using connections. HttpClient now
|
||||
correctly handles stateful / user specific connections such as persistent
|
||||
NTLM connections and SSL connections with client side authentication.
|
||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||
|
||||
* [HTTPCLIENT-773] Improved handling of the 'expires' attribute by the
|
||||
'Best Match' cookie spec.
|
||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* $HeadURL:$
|
||||
* $Revision:$
|
||||
* $Date:$
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.client;
|
||||
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
/**
|
||||
* A handler for determining if the given execution context is user specific
|
||||
* or not. The token object returned by this handler is expected to uniquely
|
||||
* identify the current user if the context is user specific or to be
|
||||
* <code>null</code> if the context does not contain any resources or details
|
||||
* specific to the current user.
|
||||
* <p/>
|
||||
* The user token will be used to ensure that user specific resouces will not
|
||||
* shared with or reused by other users.
|
||||
*
|
||||
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface UserTokenHandler {
|
||||
|
||||
/**
|
||||
* The token object returned by this method is expected to uniquely
|
||||
* identify the current user if the context is user specific or to be
|
||||
* <code>null</code> if it is not.
|
||||
*
|
||||
* @param context the execution context
|
||||
*
|
||||
* @return user token that uniquely identifies the user or
|
||||
* <code>null</null> if the context is not user specific.
|
||||
*/
|
||||
Object getUserToken(HttpContext context);
|
||||
|
||||
}
|
|
@ -47,5 +47,6 @@ public interface ClientContext {
|
|||
public static final String TARGET_AUTH_STATE = "http.auth.target-scope";
|
||||
public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
|
||||
public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
|
||||
public static final String USER_TOKEN = "http.user-token";
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.apache.http.client.CredentialsProvider;
|
|||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.RedirectHandler;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.protocol.ClientContext;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
|
@ -110,9 +111,12 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
/** The credentials provider. */
|
||||
private CredentialsProvider credsProvider;
|
||||
|
||||
/** The HttpRoutePlanner object. */
|
||||
/** The route planner. */
|
||||
private HttpRoutePlanner routePlanner;
|
||||
|
||||
/** The user token handler. */
|
||||
private UserTokenHandler userTokenHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new HTTP client.
|
||||
|
@ -169,18 +173,8 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
protected abstract HttpRoutePlanner createHttpRoutePlanner();
|
||||
|
||||
|
||||
public synchronized final HttpRoutePlanner getRoutePlanner() {
|
||||
if (this.routePlanner == null) {
|
||||
this.routePlanner = createHttpRoutePlanner();
|
||||
}
|
||||
return this.routePlanner;
|
||||
}
|
||||
protected abstract UserTokenHandler createUserTokenHandler();
|
||||
|
||||
|
||||
public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) {
|
||||
this.routePlanner = routePlanner;
|
||||
}
|
||||
|
||||
|
||||
// non-javadoc, see interface HttpClient
|
||||
public synchronized final HttpParams getParams() {
|
||||
|
@ -334,6 +328,32 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
}
|
||||
|
||||
|
||||
public synchronized final HttpRoutePlanner getRoutePlanner() {
|
||||
if (this.routePlanner == null) {
|
||||
this.routePlanner = createHttpRoutePlanner();
|
||||
}
|
||||
return this.routePlanner;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) {
|
||||
this.routePlanner = routePlanner;
|
||||
}
|
||||
|
||||
|
||||
public synchronized final UserTokenHandler getUserTokenHandler() {
|
||||
if (this.userTokenHandler == null) {
|
||||
this.userTokenHandler = createUserTokenHandler();
|
||||
}
|
||||
return this.userTokenHandler;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void setUserTokenHandler(final UserTokenHandler userTokenHandler) {
|
||||
this.userTokenHandler = userTokenHandler;
|
||||
}
|
||||
|
||||
|
||||
protected synchronized final BasicHttpProcessor getHttpProcessor() {
|
||||
if (httpProcessor == null) {
|
||||
httpProcessor = createHttpProcessor();
|
||||
|
@ -500,6 +520,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
getRedirectHandler(),
|
||||
getTargetAuthenticationHandler(),
|
||||
getProxyAuthenticationHandler(),
|
||||
getUserTokenHandler(),
|
||||
determineParams(request));
|
||||
}
|
||||
|
||||
|
@ -524,6 +545,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
final RedirectHandler redirectHandler,
|
||||
final AuthenticationHandler targetAuthHandler,
|
||||
final AuthenticationHandler proxyAuthHandler,
|
||||
final UserTokenHandler stateHandler,
|
||||
final HttpParams params) {
|
||||
return new DefaultClientRequestDirector(
|
||||
conman,
|
||||
|
@ -534,6 +556,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
redirectHandler,
|
||||
targetAuthHandler,
|
||||
proxyAuthHandler,
|
||||
stateHandler,
|
||||
params);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ import org.apache.http.client.CredentialsProvider;
|
|||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.RedirectException;
|
||||
import org.apache.http.client.RedirectHandler;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.methods.AbortableHttpRequest;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.params.ClientPNames;
|
||||
|
@ -134,6 +135,9 @@ public class DefaultClientRequestDirector
|
|||
/** The proxy authentication handler. */
|
||||
private final AuthenticationHandler proxyAuthHandler;
|
||||
|
||||
/** The user token handler. */
|
||||
private final UserTokenHandler userTokenHandler;
|
||||
|
||||
/** The HTTP parameters. */
|
||||
protected final HttpParams params;
|
||||
|
||||
|
@ -157,6 +161,7 @@ public class DefaultClientRequestDirector
|
|||
final RedirectHandler redirectHandler,
|
||||
final AuthenticationHandler targetAuthHandler,
|
||||
final AuthenticationHandler proxyAuthHandler,
|
||||
final UserTokenHandler userTokenHandler,
|
||||
final HttpParams params) {
|
||||
|
||||
if (conman == null) {
|
||||
|
@ -191,6 +196,10 @@ public class DefaultClientRequestDirector
|
|||
throw new IllegalArgumentException
|
||||
("Proxy authentication handler may not be null.");
|
||||
}
|
||||
if (userTokenHandler == null) {
|
||||
throw new IllegalArgumentException
|
||||
("User token handler may not be null.");
|
||||
}
|
||||
if (params == null) {
|
||||
throw new IllegalArgumentException
|
||||
("HTTP parameters may not be null");
|
||||
|
@ -203,6 +212,7 @@ public class DefaultClientRequestDirector
|
|||
this.redirectHandler = redirectHandler;
|
||||
this.targetAuthHandler = targetAuthHandler;
|
||||
this.proxyAuthHandler = proxyAuthHandler;
|
||||
this.userTokenHandler = userTokenHandler;
|
||||
this.params = params;
|
||||
this.requestExec = new HttpRequestExecutor();
|
||||
|
||||
|
@ -283,10 +293,13 @@ public class DefaultClientRequestDirector
|
|||
RequestWrapper wrapper = roureq.getRequest();
|
||||
HttpRoute route = roureq.getRoute();
|
||||
|
||||
// See if we have a user token bound to the execution context
|
||||
Object userToken = context.getAttribute(ClientContext.USER_TOKEN);
|
||||
|
||||
// Allocate connection if needed
|
||||
if (managedConn == null) {
|
||||
ClientConnectionRequest connRequest = connManager.requestConnection(
|
||||
route, null);
|
||||
route, userToken);
|
||||
if (orig instanceof AbortableHttpRequest) {
|
||||
((AbortableHttpRequest) orig).setConnectionRequest(connRequest);
|
||||
}
|
||||
|
@ -415,6 +428,12 @@ public class DefaultClientRequestDirector
|
|||
followup.getRequest().clearHeaders();
|
||||
roureq = followup;
|
||||
}
|
||||
|
||||
userToken = this.userTokenHandler.getUserToken(context);
|
||||
context.setAttribute(ClientContext.USER_TOKEN, userToken);
|
||||
if (managedConn != null) {
|
||||
managedConn.setState(userToken);
|
||||
}
|
||||
} // while not done
|
||||
|
||||
// The connection is in or can be brought to a re-usable state.
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.apache.http.client.CookieStore;
|
|||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.RedirectHandler;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.params.AuthPolicy;
|
||||
import org.apache.http.client.params.ClientPNames;
|
||||
import org.apache.http.client.params.CookiePolicy;
|
||||
|
@ -289,11 +290,16 @@ public class DefaultHttpClient extends AbstractHttpClient {
|
|||
}
|
||||
|
||||
|
||||
// non-javadoc, see base class AbstractHttpClient
|
||||
@Override
|
||||
protected HttpRoutePlanner createHttpRoutePlanner() {
|
||||
return new DefaultHttpRoutePlanner
|
||||
(getConnectionManager().getSchemeRegistry());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected UserTokenHandler createUserTokenHandler() {
|
||||
return new DefaultUserTokenHandler();
|
||||
}
|
||||
|
||||
} // class DefaultHttpClient
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* $HeadURL:$
|
||||
* $Revision:$
|
||||
* $Date:$
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.client.AuthState;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.protocol.ClientContext;
|
||||
import org.apache.http.conn.ManagedClientConnection;
|
||||
import org.apache.http.protocol.ExecutionContext;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
public class DefaultUserTokenHandler implements UserTokenHandler {
|
||||
|
||||
public Object getUserToken(final HttpContext context) {
|
||||
|
||||
Principal userPrincipal = null;
|
||||
|
||||
AuthState targetAuthState = (AuthState) context.getAttribute(
|
||||
ClientContext.TARGET_AUTH_STATE);
|
||||
if (targetAuthState != null) {
|
||||
userPrincipal = getAuthPrincipal(targetAuthState);
|
||||
if (userPrincipal == null) {
|
||||
AuthState proxyAuthState = (AuthState) context.getAttribute(
|
||||
ClientContext.PROXY_AUTH_STATE);
|
||||
userPrincipal = getAuthPrincipal(proxyAuthState);
|
||||
}
|
||||
}
|
||||
|
||||
if (userPrincipal == null) {
|
||||
ManagedClientConnection conn = (ManagedClientConnection) context.getAttribute(
|
||||
ExecutionContext.HTTP_CONNECTION);
|
||||
if (conn.isOpen()) {
|
||||
SSLSession sslsession = conn.getSSLSession();
|
||||
if (sslsession != null) {
|
||||
userPrincipal = sslsession.getLocalPrincipal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return userPrincipal;
|
||||
}
|
||||
|
||||
private static Principal getAuthPrincipal(final AuthState authState) {
|
||||
AuthScheme scheme = authState.getAuthScheme();
|
||||
if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
|
||||
Credentials creds = authState.getCredentials();
|
||||
if (creds != null) {
|
||||
return creds.getUserPrincipal();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -45,6 +45,7 @@ public class TestAllHttpClientImpl extends TestCase {
|
|||
suite.addTest(TestBasicCredentialsProvider.suite());
|
||||
suite.addTest(TestRequestWrapper.suite());
|
||||
suite.addTest(TestDefaultClientRequestDirector.suite());
|
||||
suite.addTest(TestStatefulConnManagement.suite());
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
* ====================================================================
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpException;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.params.HttpClientParams;
|
||||
import org.apache.http.conn.ManagedClientConnection;
|
||||
import org.apache.http.conn.params.ConnPerRouteBean;
|
||||
import org.apache.http.conn.params.HttpConnectionManagerParams;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.localserver.ServerTestBase;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.ExecutionContext;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.protocol.HttpRequestHandler;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultClientRequestDirector}
|
||||
*/
|
||||
public class TestStatefulConnManagement extends ServerTestBase {
|
||||
|
||||
public TestStatefulConnManagement(final String testName) throws IOException {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
String[] testCaseName = { TestStatefulConnManagement.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return new TestSuite(TestStatefulConnManagement.class);
|
||||
}
|
||||
|
||||
private class SimpleService implements HttpRequestHandler {
|
||||
|
||||
public SimpleService() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void handle(
|
||||
final HttpRequest request,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
response.setStatusCode(HttpStatus.SC_OK);
|
||||
StringEntity entity = new StringEntity("Whatever");
|
||||
response.setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStatefulConnections() throws Exception {
|
||||
|
||||
int workerCount = 5;
|
||||
int requestCount = 5;
|
||||
|
||||
int port = this.localServer.getServicePort();
|
||||
this.localServer.register("*", new SimpleService());
|
||||
|
||||
HttpHost target = new HttpHost("localhost", port);
|
||||
|
||||
HttpParams params = defaultParams.copy();
|
||||
HttpConnectionManagerParams.setMaxTotalConnections(params, workerCount);
|
||||
HttpConnectionManagerParams.setMaxConnectionsPerRoute(params,
|
||||
new ConnPerRouteBean(workerCount));
|
||||
HttpClientParams.setConnectionManagerTimeout(params, 10L);
|
||||
|
||||
ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(
|
||||
params, supportedSchemes);
|
||||
|
||||
DefaultHttpClient client = new DefaultHttpClient(mgr, params);
|
||||
|
||||
HttpContext[] contexts = new HttpContext[workerCount];
|
||||
HttpWorker[] workers = new HttpWorker[workerCount];
|
||||
for (int i = 0; i < contexts.length; i++) {
|
||||
HttpContext context = new BasicHttpContext();
|
||||
context.setAttribute("user", Integer.valueOf(i));
|
||||
contexts[i] = context;
|
||||
workers[i] = new HttpWorker(context, requestCount, target, client);
|
||||
}
|
||||
|
||||
client.setUserTokenHandler(new UserTokenHandler() {
|
||||
|
||||
public Object getUserToken(final HttpContext context) {
|
||||
Integer id = (Integer) context.getAttribute("user");
|
||||
return id;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
for (int i = 0; i < workers.length; i++) {
|
||||
workers[i].start();
|
||||
}
|
||||
for (int i = 0; i < workers.length; i++) {
|
||||
workers[i].join(10000);
|
||||
}
|
||||
for (int i = 0; i < workers.length; i++) {
|
||||
Exception ex = workers[i].getException();
|
||||
if (ex != null) {
|
||||
throw ex;
|
||||
}
|
||||
assertEquals(requestCount, workers[i].getCount());
|
||||
}
|
||||
|
||||
for (int i = 0; i < contexts.length; i++) {
|
||||
HttpContext context = contexts[i];
|
||||
Integer id = (Integer) context.getAttribute("user");
|
||||
|
||||
for (int r = 0; r < requestCount; r++) {
|
||||
Integer state = (Integer) context.getAttribute("r" + r);
|
||||
assertNotNull(state);
|
||||
assertEquals(id, state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class HttpWorker extends Thread {
|
||||
|
||||
private final HttpContext context;
|
||||
private final int requestCount;
|
||||
private final HttpHost target;
|
||||
private final HttpClient httpclient;
|
||||
|
||||
private volatile Exception exception;
|
||||
private volatile int count;
|
||||
|
||||
public HttpWorker(
|
||||
final HttpContext context,
|
||||
int requestCount,
|
||||
final HttpHost target,
|
||||
final HttpClient httpclient) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.requestCount = requestCount;
|
||||
this.target = target;
|
||||
this.httpclient = httpclient;
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return this.exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (int r = 0; r < this.requestCount; r++) {
|
||||
HttpGet httpget = new HttpGet("/");
|
||||
HttpResponse response = this.httpclient.execute(
|
||||
this.target,
|
||||
httpget,
|
||||
this.context);
|
||||
this.count++;
|
||||
|
||||
ManagedClientConnection conn = (ManagedClientConnection) this.context.getAttribute(
|
||||
ExecutionContext.HTTP_CONNECTION);
|
||||
|
||||
this.context.setAttribute("r" + r, conn.getState());
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
entity.consumeContent();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
this.exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue