* Redesigned the way the local execution context is handled: If a custom context is given, it gets wrapped with the DefaultedHttpContext that defaults to the parent execution context containing default values of all mandatory execution attributes. Therefore the local context can now contain only those attributes the user wishes to override. There is no longer a need to populate the local context with all mandatory attributes.

* Added a new context parameter for preferred auth schemes 

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@654886 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2008-05-09 17:06:12 +00:00
parent 8c8174514e
commit e4f8eee752
13 changed files with 100 additions and 89 deletions

View File

@ -59,10 +59,8 @@ public class ClientCustomContext {
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Obtain default HTTP context
HttpContext defaultContext = httpclient.getDefaultContext();
// Create local HTTP context
HttpContext localContext = new BasicHttpContext(defaultContext);
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

View File

@ -56,9 +56,8 @@ public class ClientInteractiveAuthentication {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
// Create custom execution context
// We'll need it in order to get hold of the authentication state object
HttpContext localContext = new BasicHttpContext(httpclient.getDefaultContext());
// Create local execution context
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("http://localhost/test");

View File

@ -110,7 +110,7 @@ public class ClientMultiThreadedExecution {
public GetThread(HttpClient httpClient, HttpGet httpget, int id) {
this.httpClient = httpClient;
this.context = new BasicHttpContext(httpClient.getDefaultContext());
this.context = new BasicHttpContext();
this.httpget = httpget;
this.id = id;
}

View File

@ -61,17 +61,6 @@ import org.apache.http.conn.ClientConnectionManager;
public interface HttpClient {
/**
* Obtains the default context used by this client populated with
* default attributes. This context will be used by default when
* executing requests with this client.
*
* @return the default context
*/
HttpContext getDefaultContext()
;
/**
* Obtains the parameters for this client.
* These parameters will become defaults for all requests being

View File

@ -45,5 +45,7 @@ public interface ClientContext {
public static final String COOKIE_ORIGIN = "http.cookie-origin";
public static final String CREDS_PROVIDER = "http.auth.credentials-provider";
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 PROXY_AUTH_STATE = "http.auth.proxy-scope";
public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
}

View File

@ -1,7 +1,7 @@
/*
* $HeadURL:$
* $Revision:$
* $Date:$
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@ -31,20 +31,42 @@
package org.apache.http.client.protocol;
import java.util.List;
import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.cookie.CookieSpecRegistry;
import org.apache.http.protocol.HttpContext;
public class ClientContextConfigurer {
public class ClientContextConfigurer implements ClientContext {
private final HttpContext context;
public ClientContextConfigurer (final HttpContext context) {
if (context == null)
throw new IllegalArgumentException("'context' must be set");
throw new IllegalArgumentException("HTTP context may not be null");
this.context = context;
}
public void setCookieStore (final CookieStore cookieStore) {
context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
public void setCookieSpecRegistry(final CookieSpecRegistry registry) {
this.context.setAttribute(COOKIESPEC_REGISTRY, registry);
}
public void setAuthSchemeRegistry(final AuthSchemeRegistry registry) {
this.context.setAttribute(AUTHSCHEME_REGISTRY, registry);
}
public void setCookieStore(final CookieStore store) {
this.context.setAttribute(COOKIE_STORE, store);
}
public void setCredentialsProvider(final CredentialsProvider provider) {
this.context.setAttribute(CREDS_PROVIDER, provider);
}
public void setAuthSchemePref(final List<String> list) {
this.context.setAttribute(AUTH_SCHEME_PREF, list);
}
}

View File

@ -60,6 +60,7 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
private static final Log LOG = LogFactory.getLog(AbstractAuthenticationHandler.class);
private static final List<String> DEFAULT_SCHEME_PRIORITY = Arrays.asList(new String[] {
"ntlm",
"digest",
"basic"
});
@ -116,14 +117,20 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
throw new IllegalStateException("AuthScheme registry not set in HTTP context");
}
List<String> authPrefs = getAuthPreferences();
List<?> authPrefs = (List<?>) context.getAttribute(
ClientContext.AUTH_SCHEME_PREF);
if (authPrefs == null) {
authPrefs = getAuthPreferences();
}
if (LOG.isDebugEnabled()) {
LOG.debug("Supported authentication schemes in the order of preference: "
LOG.debug("Authentication schemes in the order of preference: "
+ authPrefs);
}
AuthScheme authScheme = null;
for (String id : authPrefs) {
for (int i = 0; i < authPrefs.size(); i++) {
String id = (String) authPrefs.get(i);
Header challenge = challenges.get(id.toLowerCase(Locale.ENGLISH));
if (challenge != null) {
@ -132,10 +139,13 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
}
try {
authScheme = registry.getAuthScheme(id, response.getParams());
break;
} catch (IllegalStateException e) {
throw new AuthenticationException(e.getMessage());
if (LOG.isWarnEnabled()) {
LOG.warn("Authentication scheme " + id + " not supported");
// Try again
}
}
break;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Challenge for " + id + " authentication scheme not available");

View File

@ -50,11 +50,13 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.RedirectHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.routing.HttpRoutePlanner;
import org.apache.http.cookie.CookieSpecRegistry;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.DefaultedHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpProcessor;
@ -72,9 +74,6 @@ import org.apache.http.protocol.HttpProcessor;
*/
public abstract class AbstractHttpClient implements HttpClient {
/** The default context. */
private HttpContext defaultContext;
/** The parameters. */
private HttpParams defaultParams;
@ -167,9 +166,6 @@ public abstract class AbstractHttpClient implements HttpClient {
protected abstract CredentialsProvider createCredentialsProvider();
protected abstract void populateContext(HttpContext context);
protected abstract HttpRoutePlanner createHttpRoutePlanner();
@ -346,15 +342,6 @@ public abstract class AbstractHttpClient implements HttpClient {
}
public synchronized final HttpContext getDefaultContext() {
if (defaultContext == null) {
defaultContext = createHttpContext();
}
populateContext(defaultContext);
return defaultContext;
}
public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) {
getHttpProcessor().addInterceptor(itcp);
}
@ -477,13 +464,31 @@ public abstract class AbstractHttpClient implements HttpClient {
// a null target may be acceptable, this depends on the route planner
// a null context is acceptable, default context created below
HttpContext execContext = null;
ClientRequestDirector director = null;
// Initialize the request execution context making copies of
// all shared objects that are potentially threading unsafe.
synchronized (this) {
HttpContext defaultContext = new BasicHttpContext(null);
defaultContext.setAttribute(
ClientContext.AUTHSCHEME_REGISTRY,
getAuthSchemes());
defaultContext.setAttribute(
ClientContext.COOKIESPEC_REGISTRY,
getCookieSpecs());
defaultContext.setAttribute(
ClientContext.COOKIE_STORE,
getCookieStore());
defaultContext.setAttribute(
ClientContext.CREDS_PROVIDER,
getCredentialsProvider());
if (context == null) {
context = new BasicHttpContext(getDefaultContext());
execContext = defaultContext;
} else {
execContext = new DefaultedHttpContext(context, defaultContext);
}
// Create a director for this request
director = createClientRequestDirector(
@ -498,7 +503,7 @@ public abstract class AbstractHttpClient implements HttpClient {
determineParams(request));
}
HttpResponse response = director.execute(target, request, context);
HttpResponse response = director.execute(target, request, execContext);
// If the response depends on the connection, the director
// will have set up an auto-release input stream.

View File

@ -42,7 +42,6 @@ import org.apache.http.client.RedirectHandler;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.client.protocol.RequestAddCookies;
import org.apache.http.client.protocol.RequestDefaultHeaders;
import org.apache.http.client.protocol.RequestProxyAuthentication;
@ -290,23 +289,6 @@ public class DefaultHttpClient extends AbstractHttpClient {
}
@Override
protected void populateContext(final HttpContext context) {
context.setAttribute(
ClientContext.AUTHSCHEME_REGISTRY,
getAuthSchemes());
context.setAttribute(
ClientContext.COOKIESPEC_REGISTRY,
getCookieSpecs());
context.setAttribute(
ClientContext.COOKIE_STORE,
getCookieStore());
context.setAttribute(
ClientContext.CREDS_PROVIDER,
getCredentialsProvider());
}
// non-javadoc, see base class AbstractHttpClient
@Override
protected HttpRoutePlanner createHttpRoutePlanner() {

View File

@ -53,6 +53,7 @@ import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.localserver.ServerTestBase;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
@ -105,7 +106,7 @@ public class TestCookie2Support extends ServerTestBase {
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
CookieStore cookieStore = new BasicCookieStore();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("/test/");
@ -156,7 +157,7 @@ public class TestCookie2Support extends ServerTestBase {
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
CookieStore cookieStore = new BasicCookieStore();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("/test/");
@ -205,7 +206,7 @@ public class TestCookie2Support extends ServerTestBase {
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
CookieStore cookieStore = new BasicCookieStore();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("/test/");
@ -256,7 +257,7 @@ public class TestCookie2Support extends ServerTestBase {
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
CookieStore cookieStore = new BasicCookieStore();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("/test/");

View File

@ -55,6 +55,7 @@ import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.localserver.ServerTestBase;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
@ -237,7 +238,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_MULTIPLE_CHOICES));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -261,7 +262,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_MOVED_PERMANENTLY));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -289,7 +290,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_MOVED_TEMPORARILY));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -317,7 +318,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_SEE_OTHER));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -345,7 +346,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_NOT_MODIFIED));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -369,7 +370,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_USE_PROXY));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -393,7 +394,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port, HttpStatus.SC_TEMPORARY_REDIRECT));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -453,7 +454,7 @@ public class TestRedirects extends ServerTestBase {
this.localServer.register("*", new BasicRedirectService(host, port));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpPost httppost = new HttpPost("/oldlocation/");
httppost.setEntity(new StringEntity("stuff"));
@ -478,7 +479,7 @@ public class TestRedirects extends ServerTestBase {
this.localServer.register("*", new RelativeRedirectService());
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
client.getParams().setBooleanParameter(
ClientPNames.REJECT_RELATIVE_REDIRECT, false);
@ -507,7 +508,7 @@ public class TestRedirects extends ServerTestBase {
this.localServer.register("*", new RelativeRedirectService2());
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
client.getParams().setBooleanParameter(
ClientPNames.REJECT_RELATIVE_REDIRECT, false);
@ -598,7 +599,7 @@ public class TestRedirects extends ServerTestBase {
cookieStore.addCookie(cookie);
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
HttpGet httpget = new HttpGet("/oldlocation/");
@ -626,7 +627,7 @@ public class TestRedirects extends ServerTestBase {
new BasicRedirectService(host, port));
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
List<Header> defaultHeaders = new ArrayList<Header>(1);
defaultHeaders.add(new BasicHeader(HTTP.USER_AGENT, "my-test-client"));

View File

@ -66,6 +66,7 @@ import org.apache.http.message.BasicHeader;
import org.apache.http.mockup.SocketFactoryMockup;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
@ -99,7 +100,7 @@ public class TestDefaultClientRequestDirector extends ServerTestBase {
final AtomicReference<Throwable> throwableRef = new AtomicReference<Throwable>();
final CountDownLatch getLatch = new CountDownLatch(1);
final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
final HttpContext context = client.getDefaultContext();
final HttpContext context = new BasicHttpContext();
final HttpGet httpget = new HttpGet("http://www.example.com/a");
new Thread(new Runnable() {
@ -140,7 +141,7 @@ public class TestDefaultClientRequestDirector extends ServerTestBase {
final AtomicReference<Throwable> throwableRef = new AtomicReference<Throwable>();
final CountDownLatch getLatch = new CountDownLatch(1);
final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
final HttpContext context = client.getDefaultContext();
final HttpContext context = new BasicHttpContext();
final HttpGet httpget = new CustomGet("a", releaseLatch);
new Thread(new Runnable() {
@ -181,7 +182,7 @@ public class TestDefaultClientRequestDirector extends ServerTestBase {
final CountDownLatch getLatch = new CountDownLatch(1);
final CountDownLatch startLatch = new CountDownLatch(1);
final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
final HttpContext context = client.getDefaultContext();
final HttpContext context = new BasicHttpContext();
final HttpGet httpget = new HttpGet("a");
new Thread(new Runnable() {
@ -228,7 +229,7 @@ public class TestDefaultClientRequestDirector extends ServerTestBase {
final AtomicReference<Throwable> throwableRef = new AtomicReference<Throwable>();
final CountDownLatch getLatch = new CountDownLatch(1);
final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
final HttpContext context = client.getDefaultContext();
final HttpContext context = new BasicHttpContext();
final HttpGet httpget = new HttpGet("a");
new Thread(new Runnable() {
@ -263,7 +264,7 @@ public class TestDefaultClientRequestDirector extends ServerTestBase {
public void testSocketConnectFailureReleasesConnection() throws Exception {
final ConnMan2 conMan = new ConnMan2();
final DefaultHttpClient client = new DefaultHttpClient(conMan, new BasicHttpParams());
final HttpContext context = client.getDefaultContext();
final HttpContext context = new BasicHttpContext();
final HttpGet httpget = new HttpGet("http://www.example.com/a");
try {

View File

@ -42,6 +42,7 @@ import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.StringEntity;
import org.apache.http.localserver.ServerTestBase;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
@ -91,7 +92,7 @@ public class TestRequestWrapper extends ServerTestBase {
this.localServer.register("*", new SimpleService());
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
String s = "http://localhost:" + port + "/path";
HttpGet httpget = new HttpGet(s);
@ -116,7 +117,7 @@ public class TestRequestWrapper extends ServerTestBase {
this.localServer.register("*", new SimpleService());
DefaultHttpClient client = new DefaultHttpClient();
HttpContext context = client.getDefaultContext();
HttpContext context = new BasicHttpContext();
String s = "http://localhost:" + port;
HttpGet httpget = new HttpGet(s);