diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthOption.java b/httpclient/src/main/java/org/apache/http/auth/AuthOption.java
new file mode 100644
index 000000000..97c0c58b4
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/auth/AuthOption.java
@@ -0,0 +1,66 @@
+/*
+ * ====================================================================
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.auth;
+
+import org.apache.http.annotation.Immutable;
+
+/**
+ * @since 4.2
+ */
+@Immutable
+public final class AuthOption {
+
+ private final AuthScheme authScheme;
+ private final Credentials creds;
+
+ public AuthOption(final AuthScheme authScheme, final Credentials creds) {
+ super();
+ if (authScheme == null) {
+ throw new IllegalArgumentException("Auth scheme may not be null");
+ }
+ if (creds == null) {
+ throw new IllegalArgumentException("User credentials may not be null");
+ }
+ this.authScheme = authScheme;
+ this.creds = creds;
+ }
+
+ public AuthScheme getAuthScheme() {
+ return this.authScheme;
+ }
+
+ public Credentials getCredentials() {
+ return this.creds;
+ }
+
+ @Override
+ public String toString() {
+ return this.authScheme.toString();
+ }
+
+}
+
diff --git a/httpclient/src/main/java/org/apache/http/client/AuthenticationHandler.java b/httpclient/src/main/java/org/apache/http/client/AuthenticationHandler.java
index 2d0da4217..afce2838c 100644
--- a/httpclient/src/main/java/org/apache/http/client/AuthenticationHandler.java
+++ b/httpclient/src/main/java/org/apache/http/client/AuthenticationHandler.java
@@ -47,7 +47,10 @@ import org.apache.http.protocol.HttpContext;
* from multiple threads.
*
* @since 4.0
+ *
+ * @deprecated use {@link AuthenticationStrategy}
*/
+@Deprecated
public interface AuthenticationHandler {
/**
diff --git a/httpclient/src/main/java/org/apache/http/client/AuthenticationStrategy.java b/httpclient/src/main/java/org/apache/http/client/AuthenticationStrategy.java
new file mode 100644
index 000000000..e43bbc43d
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/client/AuthenticationStrategy.java
@@ -0,0 +1,97 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.client;
+
+import java.util.Map;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthOption;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.protocol.HttpContext;
+
+/**
+/**
+ * A handler for determining if an HTTP response represents an authentication challenge that was
+ * sent back to the client as a result of authentication failure.
+ *
+ * Implementations of this interface must be thread-safe. Access to shared data must be
+ * synchronized as methods of this interface may be executed from multiple threads.
+ *
+ * @since 4.2
+ */
+public interface AuthenticationStrategy {
+
+ /**
+ * Determines if the given HTTP response response represents
+ * an authentication challenge that was sent back as a result
+ * of authentication failure
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return true
if user authentication is required,
+ * false
otherwise.
+ */
+ boolean isAuthenticationRequested(
+ HttpResponse response,
+ HttpContext context);
+
+ /**
+ * Extracts from the given HTTP response a collection of authentication
+ * challenges, each of which represents an authentication scheme supported
+ * by the authentication host.
+ *
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return a collection of challenges keyed by names of corresponding
+ * authentication schemes.
+ * @throws MalformedChallengeException if one of the authentication
+ * challenges is not valid or malformed.
+ */
+ Map getChallenges(
+ HttpResponse response,
+ HttpContext context) throws MalformedChallengeException;
+
+ /**
+ * Selects one authentication challenge out of all available and
+ * creates and generates {@link AuthOption} instance capable of
+ * processing that challenge.
+ * @param challenges collection of challenges.
+ * @param response HTTP response.
+ * @param context HTTP context.
+ * @return authentication scheme to use for authentication.
+ * @throws MalformedChallengeException if one of the authentication
+ * challenges is not valid or malformed.
+ */
+ AuthOption select(
+ Map challenges,
+ HttpHost authhost,
+ HttpResponse response,
+ HttpContext context) throws MalformedChallengeException;
+
+}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AbstractAuthenticationHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/AbstractAuthenticationHandler.java
index a347ef5d3..038fdbeb8 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/AbstractAuthenticationHandler.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/AbstractAuthenticationHandler.java
@@ -46,6 +46,7 @@ import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.client.AuthenticationHandler;
+import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.protocol.HTTP;
@@ -56,7 +57,10 @@ import org.apache.http.util.CharArrayBuffer;
* Base class for {@link AuthenticationHandler} implementations.
*
* @since 4.0
+ *
+ * @deprecated use {@link AuthenticationStrategy}
*/
+@Deprecated
@Immutable
public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java
new file mode 100644
index 000000000..99cc3a2fa
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyAdaptor.java
@@ -0,0 +1,122 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.AuthOption;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.client.AuthenticationHandler;
+import org.apache.http.client.AuthenticationStrategy;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * @since 4.2
+ */
+@SuppressWarnings("deprecation")
+@Immutable
+@Deprecated
+class AuthenticationStrategyAdaptor implements AuthenticationStrategy {
+
+ private final Log log = LogFactory.getLog(getClass());
+
+ private final AuthenticationHandler handler;
+
+ @Deprecated
+ public AuthenticationStrategyAdaptor(final AuthenticationHandler handler) {
+ super();
+ this.handler = handler;
+ }
+
+ public boolean isAuthenticationRequested(final HttpResponse response, final HttpContext context) {
+ return this.handler.isAuthenticationRequested(response, context);
+ }
+
+ public Map getChallenges(
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ return this.handler.getChallenges(response, context);
+ }
+
+ public AuthOption select(
+ final Map challenges,
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
+ ClientContext.CREDS_PROVIDER);
+ if (credsProvider == null) {
+ this.log.debug("Credentials provider not set in the context");
+ return null;
+ }
+
+ AuthScheme authScheme;
+ try {
+ authScheme = this.handler.selectScheme(challenges, response, context);
+ } catch (AuthenticationException ex) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn(ex.getMessage(), ex);
+ }
+ return null;
+ }
+ String id = authScheme.getSchemeName();
+ Header challenge = challenges.get(id.toLowerCase(Locale.US));
+ authScheme.processChallenge(challenge);
+
+ AuthScope authScope = new AuthScope(
+ authhost.getHostName(),
+ authhost.getPort(),
+ authScheme.getRealm(),
+ authScheme.getSchemeName());
+
+ Credentials credentials = credsProvider.getCredentials(authScope);
+ if (credentials != null) {
+ return new AuthOption(authScheme, credentials);
+ } else {
+ return null;
+ }
+ }
+
+ public AuthenticationHandler getHandler() {
+ return this.handler;
+ }
+
+}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java
new file mode 100644
index 000000000..2c4df0fa2
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java
@@ -0,0 +1,200 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.FormattedHeader;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.AuthOption;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.client.AuthenticationStrategy;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.params.AuthPolicy;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.CharArrayBuffer;
+
+@Immutable
+class AuthenticationStrategyImpl implements AuthenticationStrategy {
+
+ private final Log log = LogFactory.getLog(getClass());
+
+ private static final List DEFAULT_SCHEME_PRIORITY =
+ Collections.unmodifiableList(Arrays.asList(new String[] {
+ AuthPolicy.SPNEGO,
+ AuthPolicy.NTLM,
+ AuthPolicy.DIGEST,
+ AuthPolicy.BASIC
+ }));
+
+ private final int challengeCode;
+ private final String headerName;
+ private final String prefParamName;
+
+ AuthenticationStrategyImpl(int challengeCode, final String headerName, final String prefParamName) {
+ super();
+ this.challengeCode = challengeCode;
+ this.headerName = headerName;
+ this.prefParamName = prefParamName;
+ }
+
+ public boolean isAuthenticationRequested(final HttpResponse response, final HttpContext context) {
+ if (response == null) {
+ throw new IllegalArgumentException("HTTP response may not be null");
+ }
+ int status = response.getStatusLine().getStatusCode();
+ return status == this.challengeCode;
+ }
+
+ public Map getChallenges(
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ if (response == null) {
+ throw new IllegalArgumentException("HTTP response may not be null");
+ }
+ Header[] headers = response.getHeaders(this.headerName);
+ Map map = new HashMap(headers.length);
+ for (Header header : headers) {
+ CharArrayBuffer buffer;
+ int pos;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ pos = ((FormattedHeader) header).getValuePos();
+ } else {
+ String s = header.getValue();
+ if (s == null) {
+ throw new MalformedChallengeException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ pos = 0;
+ }
+ while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ int beginIndex = pos;
+ while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ int endIndex = pos;
+ String s = buffer.substring(beginIndex, endIndex);
+ map.put(s.toLowerCase(Locale.US), header);
+ }
+ return map;
+ }
+
+ public AuthOption select(
+ final Map challenges,
+ final HttpHost authhost,
+ final HttpResponse response,
+ final HttpContext context) throws MalformedChallengeException {
+ if (challenges == null) {
+ throw new IllegalArgumentException("Map of auth challenges may not be null");
+ }
+ if (authhost == null) {
+ throw new IllegalArgumentException("Host may not be null");
+ }
+ if (response == null) {
+ throw new IllegalArgumentException("HTTP response may not be null");
+ }
+ if (context == null) {
+ throw new IllegalArgumentException("HTTP context may not be null");
+ }
+
+ AuthSchemeRegistry registry = (AuthSchemeRegistry) context.getAttribute(
+ ClientContext.AUTHSCHEME_REGISTRY);
+ if (registry == null) {
+ this.log.debug("Auth scheme registry not set in the context");
+ return null;
+ }
+ CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
+ ClientContext.CREDS_PROVIDER);
+ if (credsProvider == null) {
+ this.log.debug("Credentials provider not set in the context");
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ List authPrefs = (List) response.getParams().getParameter(this.prefParamName);
+ if (authPrefs == null) {
+ authPrefs = DEFAULT_SCHEME_PRIORITY;
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Authentication schemes in the order of preference: " + authPrefs);
+ }
+
+ for (String id: authPrefs) {
+ Header challenge = challenges.get(id.toLowerCase(Locale.US));
+ if (challenge != null) {
+ try {
+ AuthScheme authScheme = registry.getAuthScheme(id, response.getParams());
+ authScheme.processChallenge(challenge);
+
+ AuthScope authScope = new AuthScope(
+ authhost.getHostName(),
+ authhost.getPort(),
+ authScheme.getRealm(),
+ authScheme.getSchemeName());
+
+ Credentials credentials = credsProvider.getCredentials(authScope);
+ if (credentials != null) {
+ return new AuthOption(authScheme, credentials);
+ }
+ } catch (IllegalStateException e) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Authentication scheme " + id + " not supported");
+ // Try again
+ }
+ }
+ } else {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Challenge for " + id + " authentication scheme not available");
+ // Try again
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java
index e3a96d189..72f191ad6 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultProxyAuthenticationHandler.java
@@ -46,7 +46,10 @@ import org.apache.http.protocol.HttpContext;
* authentication.
*
* @since 4.0
+ *
+ * @deprecated use {@link ProxyAuthenticationStrategy}
*/
+@Deprecated
@Immutable
public class DefaultProxyAuthenticationHandler extends AbstractAuthenticationHandler {
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java
index a4da7fd43..f7254e8ba 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRedirectStrategyAdaptor.java
@@ -33,6 +33,7 @@ import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.RedirectHandler;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
@@ -42,14 +43,15 @@ import org.apache.http.protocol.HttpContext;
/**
* @since 4.1
*/
+@SuppressWarnings("deprecation")
@Immutable
@Deprecated
class DefaultRedirectStrategyAdaptor implements RedirectStrategy {
- private final org.apache.http.client.RedirectHandler handler;
+ private final RedirectHandler handler;
@Deprecated
- public DefaultRedirectStrategyAdaptor(final org.apache.http.client.RedirectHandler handler) {
+ public DefaultRedirectStrategyAdaptor(final RedirectHandler handler) {
super();
this.handler = handler;
}
@@ -74,4 +76,8 @@ class DefaultRedirectStrategyAdaptor implements RedirectStrategy {
}
}
+ public RedirectHandler getHandler() {
+ return this.handler;
+ }
+
}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java
index 4e9104bad..2ace5b4d8 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultRequestDirector.java
@@ -49,10 +49,11 @@ import org.apache.http.auth.AuthChallengeState;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthState;
import org.apache.http.client.AuthenticationHandler;
-import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.NonRepeatableRequestException;
import org.apache.http.client.RedirectException;
+import org.apache.http.client.RedirectHandler;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.RequestDirector;
import org.apache.http.client.UserTokenHandler;
@@ -124,6 +125,7 @@ import org.apache.http.util.EntityUtils;
*
* @since 4.0
*/
+@SuppressWarnings("deprecation")
@NotThreadSafe // e.g. managedConn
public class DefaultRequestDirector implements RequestDirector {
@@ -152,17 +154,25 @@ public class DefaultRequestDirector implements RequestDirector {
/** The redirect handler. */
@Deprecated
- protected final org.apache.http.client.RedirectHandler redirectHandler = null;
+ protected final RedirectHandler redirectHandler;
/** The redirect strategy. */
protected final RedirectStrategy redirectStrategy;
/** The target authentication handler. */
+ @Deprecated
protected final AuthenticationHandler targetAuthHandler;
+ /** The target authentication handler. */
+ protected final AuthenticationStrategy targetAuthStrategy;
+
/** The proxy authentication handler. */
+ @Deprecated
protected final AuthenticationHandler proxyAuthHandler;
+ /** The proxy authentication handler. */
+ protected final AuthenticationStrategy proxyAuthStrategy;
+
/** The user token handler. */
protected final UserTokenHandler userTokenHandler;
@@ -195,7 +205,7 @@ public class DefaultRequestDirector implements RequestDirector {
final HttpRoutePlanner rouplan,
final HttpProcessor httpProcessor,
final HttpRequestRetryHandler retryHandler,
- final org.apache.http.client.RedirectHandler redirectHandler,
+ final RedirectHandler redirectHandler,
final AuthenticationHandler targetAuthHandler,
final AuthenticationHandler proxyAuthHandler,
final UserTokenHandler userTokenHandler,
@@ -203,13 +213,14 @@ public class DefaultRequestDirector implements RequestDirector {
this(LogFactory.getLog(DefaultRequestDirector.class),
requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler,
new DefaultRedirectStrategyAdaptor(redirectHandler),
- targetAuthHandler, proxyAuthHandler, userTokenHandler, params);
+ new AuthenticationStrategyAdaptor(targetAuthHandler),
+ new AuthenticationStrategyAdaptor(proxyAuthHandler),
+ userTokenHandler,
+ params);
}
- /**
- * @since 4.1
- */
+ @Deprecated
public DefaultRequestDirector(
final Log log,
final HttpRequestExecutor requestExec,
@@ -224,6 +235,32 @@ public class DefaultRequestDirector implements RequestDirector {
final AuthenticationHandler proxyAuthHandler,
final UserTokenHandler userTokenHandler,
final HttpParams params) {
+ this(LogFactory.getLog(DefaultRequestDirector.class),
+ requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler,
+ redirectStrategy,
+ new AuthenticationStrategyAdaptor(targetAuthHandler),
+ new AuthenticationStrategyAdaptor(proxyAuthHandler),
+ userTokenHandler,
+ params);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public DefaultRequestDirector(
+ final Log log,
+ final HttpRequestExecutor requestExec,
+ final ClientConnectionManager conman,
+ final ConnectionReuseStrategy reustrat,
+ final ConnectionKeepAliveStrategy kastrat,
+ final HttpRoutePlanner rouplan,
+ final HttpProcessor httpProcessor,
+ final HttpRequestRetryHandler retryHandler,
+ final RedirectStrategy redirectStrategy,
+ final AuthenticationStrategy targetAuthStrategy,
+ final AuthenticationStrategy proxyAuthStrategy,
+ final UserTokenHandler userTokenHandler,
+ final HttpParams params) {
if (log == null) {
throw new IllegalArgumentException
@@ -261,13 +298,13 @@ public class DefaultRequestDirector implements RequestDirector {
throw new IllegalArgumentException
("Redirect strategy may not be null.");
}
- if (targetAuthHandler == null) {
+ if (targetAuthStrategy == null) {
throw new IllegalArgumentException
- ("Target authentication handler may not be null.");
+ ("Target authentication strategy may not be null.");
}
- if (proxyAuthHandler == null) {
+ if (proxyAuthStrategy == null) {
throw new IllegalArgumentException
- ("Proxy authentication handler may not be null.");
+ ("Proxy authentication strategy may not be null.");
}
if (userTokenHandler == null) {
throw new IllegalArgumentException
@@ -279,27 +316,43 @@ public class DefaultRequestDirector implements RequestDirector {
}
this.log = log;
this.authenticator = new HttpAuthenticator(log);
- this.requestExec = requestExec;
- this.connManager = conman;
- this.reuseStrategy = reustrat;
- this.keepAliveStrategy = kastrat;
- this.routePlanner = rouplan;
- this.httpProcessor = httpProcessor;
- this.retryHandler = retryHandler;
- this.redirectStrategy = redirectStrategy;
- this.targetAuthHandler = targetAuthHandler;
- this.proxyAuthHandler = proxyAuthHandler;
- this.userTokenHandler = userTokenHandler;
- this.params = params;
+ this.requestExec = requestExec;
+ this.connManager = conman;
+ this.reuseStrategy = reustrat;
+ this.keepAliveStrategy = kastrat;
+ this.routePlanner = rouplan;
+ this.httpProcessor = httpProcessor;
+ this.retryHandler = retryHandler;
+ this.redirectStrategy = redirectStrategy;
+ this.targetAuthStrategy = targetAuthStrategy;
+ this.proxyAuthStrategy = proxyAuthStrategy;
+ this.userTokenHandler = userTokenHandler;
+ this.params = params;
- this.managedConn = null;
+ if (redirectStrategy instanceof DefaultRedirectStrategyAdaptor) {
+ this.redirectHandler = ((DefaultRedirectStrategyAdaptor) redirectStrategy).getHandler();
+ } else {
+ this.redirectHandler = null;
+ }
+ if (targetAuthStrategy instanceof AuthenticationStrategyAdaptor) {
+ this.targetAuthHandler = ((AuthenticationStrategyAdaptor) targetAuthStrategy).getHandler();
+ } else {
+ this.targetAuthHandler = null;
+ }
+ if (proxyAuthStrategy instanceof AuthenticationStrategyAdaptor) {
+ this.proxyAuthHandler = ((AuthenticationStrategyAdaptor) proxyAuthStrategy).getHandler();
+ } else {
+ this.proxyAuthHandler = null;
+ }
+
+ this.managedConn = null;
this.execCount = 0;
this.redirectCount = 0;
this.maxRedirects = this.params.getIntParameter(ClientPNames.MAX_REDIRECTS, 100);
this.targetAuthState = new AuthState();
this.proxyAuthState = new AuthState();
- } // constructor
+ }
private RequestWrapper wrapRequest(
@@ -842,16 +895,11 @@ public class DefaultRequestDirector implements RequestDirector {
response.getStatusLine());
}
- CredentialsProvider credsProvider = (CredentialsProvider)
- context.getAttribute(ClientContext.CREDS_PROVIDER);
-
- if (credsProvider != null && HttpClientParams.isAuthenticating(this.params)) {
+ if (HttpClientParams.isAuthenticating(this.params)) {
if (this.authenticator.isAuthenticationRequested(response,
- this.proxyAuthHandler, this.proxyAuthState, context)) {
- if (this.authenticator.authenticate(
- proxy, response,
- this.proxyAuthHandler, this.proxyAuthState,
- credsProvider, context)) {
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ if (this.authenticator.authenticate(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
// Retry request
if (this.reuseStrategy.keepAlive(response, context)) {
this.log.debug("Connection kept alive");
@@ -1046,13 +1094,9 @@ public class DefaultRequestDirector implements RequestDirector {
return newRequest;
}
- CredentialsProvider credsProvider = (CredentialsProvider)
- context.getAttribute(ClientContext.CREDS_PROVIDER);
-
- if (credsProvider != null && HttpClientParams.isAuthenticating(params)) {
-
+ if (HttpClientParams.isAuthenticating(params)) {
if (this.authenticator.isAuthenticationRequested(response,
- this.targetAuthHandler, this.targetAuthState, context)) {
+ this.targetAuthStrategy, this.targetAuthState, context)) {
HttpHost target = (HttpHost)
context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
@@ -1064,10 +1108,8 @@ public class DefaultRequestDirector implements RequestDirector {
target = new HttpHost(
target.getHostName(), scheme.getDefaultPort(), target.getSchemeName());
}
- if (this.authenticator.authenticate(
- target, response,
- this.targetAuthHandler, this.targetAuthState,
- credsProvider, context)) {
+ if (this.authenticator.authenticate(target, response,
+ this.targetAuthStrategy, this.targetAuthState, context)) {
// Re-try the same request via the same route
return roureq;
} else {
@@ -1076,12 +1118,10 @@ public class DefaultRequestDirector implements RequestDirector {
}
if (this.authenticator.isAuthenticationRequested(response,
- this.proxyAuthHandler, this.proxyAuthState, context)) {
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
HttpHost proxy = route.getProxyHost();
- if (this.authenticator.authenticate(
- proxy, response,
- this.proxyAuthHandler, this.proxyAuthState,
- credsProvider, context)) {
+ if (this.authenticator.authenticate(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
// Re-try the same request via the same route
return roureq;
} else {
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java b/httpclient/src/main/java/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java
index 1850c153c..127253409 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/DefaultTargetAuthenticationHandler.java
@@ -46,7 +46,10 @@ import org.apache.http.protocol.HttpContext;
* authentication.
*
* @since 4.0
+ *
+ * @deprecated use {@link TargetAuthenticationStrategy}
*/
+@Deprecated
@Immutable
public class DefaultTargetAuthenticationHandler extends AbstractAuthenticationHandler {
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/HttpAuthenticator.java b/httpclient/src/main/java/org/apache/http/impl/client/HttpAuthenticator.java
index fc1f54f1c..7d66eb322 100644
--- a/httpclient/src/main/java/org/apache/http/impl/client/HttpAuthenticator.java
+++ b/httpclient/src/main/java/org/apache/http/impl/client/HttpAuthenticator.java
@@ -36,14 +36,11 @@ import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthChallengeState;
+import org.apache.http.auth.AuthOption;
import org.apache.http.auth.AuthScheme;
-import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
-import org.apache.http.auth.AuthenticationException;
-import org.apache.http.auth.Credentials;
import org.apache.http.auth.MalformedChallengeException;
-import org.apache.http.client.AuthenticationHandler;
-import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.protocol.HttpContext;
public class HttpAuthenticator {
@@ -61,10 +58,10 @@ public class HttpAuthenticator {
public boolean isAuthenticationRequested(
final HttpResponse response,
- final AuthenticationHandler authHandler,
+ final AuthenticationStrategy authStrategy,
final AuthState authState,
final HttpContext context) {
- if (authHandler.isAuthenticationRequested(response, context)) {
+ if (authStrategy.isAuthenticationRequested(response, context)) {
return true;
} else {
if (authState.getChallengeState() == AuthChallengeState.CHALLENGED) {
@@ -79,79 +76,53 @@ public class HttpAuthenticator {
public boolean authenticate(
final HttpHost host,
final HttpResponse response,
- final AuthenticationHandler authHandler,
+ final AuthenticationStrategy authStrategy,
final AuthState authState,
- final CredentialsProvider credsProvider,
final HttpContext context) {
try {
if (this.log.isDebugEnabled()) {
this.log.debug(host.toHostString() + " requested authentication");
}
- Map challenges = authHandler.getChallenges(response, context);
+ Map challenges = authStrategy.getChallenges(response, context);
if (challenges.isEmpty()) {
this.log.debug("Response contains no authentication challenges");
return false;
}
AuthScheme authScheme = authState.getAuthScheme();
- if (authScheme == null) {
- // Authentication not attempted before
- authScheme = authHandler.selectScheme(challenges, response, context);
- authState.setAuthScheme(authScheme);
- }
- String id = authScheme.getSchemeName();
- Header challenge = challenges.get(id.toLowerCase(Locale.US));
- if (challenge == null) {
- // Retry authentication with a different scheme
- authState.invalidate();
- authScheme = authHandler.selectScheme(challenges, response, context);
- authState.setAuthScheme(authScheme);
- id = authScheme.getSchemeName();
- challenge = challenges.get(id.toLowerCase(Locale.US));
- }
- authState.setChallengeState(AuthChallengeState.CHALLENGED);
- authScheme.processChallenge(challenge);
- this.log.debug("Authorization challenge processed");
-
- AuthScope authScope = new AuthScope(
- host.getHostName(),
- host.getPort(),
- authScheme.getRealm(),
- authScheme.getSchemeName());
-
- if (this.log.isDebugEnabled()) {
- this.log.debug("Authentication scope: " + authScope);
- }
- Credentials creds = authState.getCredentials();
- if (creds == null) {
- creds = credsProvider.getCredentials(authScope);
- if (this.log.isDebugEnabled()) {
- if (creds != null) {
- this.log.debug("Found credentials");
+ if (authScheme != null) {
+ String id = authScheme.getSchemeName();
+ Header challenge = challenges.get(id.toLowerCase(Locale.US));
+ if (challenge != null) {
+ this.log.debug("Authorization challenge processed");
+ authScheme.processChallenge(challenge);
+ if (authScheme.isComplete()) {
+ this.log.debug("Authentication failed");
+ authState.setChallengeState(AuthChallengeState.FAILURE);
+ authState.setCredentials(null);
+ return false;
} else {
- this.log.debug("Credentials not found");
+ authState.setChallengeState(AuthChallengeState.CHALLENGED);
+ return true;
}
- }
- } else {
- if (authScheme.isComplete()) {
- this.log.debug("Authentication failed");
- authState.setChallengeState(AuthChallengeState.FAILURE);
- creds = null;
+ } else {
+ authState.invalidate();
+ // Retry authentication with a different scheme
}
}
- authState.setCredentials(creds);
- return creds != null;
+ AuthOption authOption = authStrategy.select(challenges, host, response, context);
+ if (authOption == null) {
+ return false;
+ }
+ authState.setAuthScheme(authOption.getAuthScheme());
+ authState.setCredentials(authOption.getCredentials());
+ authState.setChallengeState(AuthChallengeState.CHALLENGED);
+ return true;
} catch (MalformedChallengeException ex) {
if (this.log.isWarnEnabled()) {
this.log.warn("Malformed challenge: " + ex.getMessage());
}
authState.invalidate();
return false;
- } catch (AuthenticationException ex) {
- if (this.log.isWarnEnabled()) {
- this.log.warn("Authentication error: " + ex.getMessage());
- }
- authState.invalidate();
- return false;
}
}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java
new file mode 100644
index 000000000..ff74c3988
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/impl/client/ProxyAuthenticationStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import org.apache.http.HttpStatus;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.params.AuthPNames;
+import org.apache.http.client.AuthenticationStrategy;
+
+/**
+ * Default {@link AuthenticationStrategy} implementation for proxy host authentication.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class ProxyAuthenticationStrategy extends AuthenticationStrategyImpl {
+
+ public ProxyAuthenticationStrategy() {
+ super(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED, AUTH.PROXY_AUTH, AuthPNames.PROXY_AUTH_PREF);
+ }
+
+}
diff --git a/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java b/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java
new file mode 100644
index 000000000..eb2cc8dd2
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/impl/client/TargetAuthenticationStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import org.apache.http.HttpStatus;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.params.AuthPNames;
+import org.apache.http.client.AuthenticationStrategy;
+
+/**
+ * Default {@link AuthenticationStrategy} implementation for proxy host authentication.
+ *
+ * @since 4.2
+ */
+@Immutable
+public class TargetAuthenticationStrategy extends AuthenticationStrategyImpl {
+
+ public TargetAuthenticationStrategy() {
+ super(HttpStatus.SC_UNAUTHORIZED, AUTH.WWW_AUTH, AuthPNames.TARGET_AUTH_PREF);
+ }
+
+}