HTTPCLIENT-862: Extended client's redirect handling interface to allow control of the content of the redirect
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@883855 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f6699b27ff
commit
51645b1cdf
|
@ -1,6 +1,10 @@
|
||||||
Changes since 4.0
|
Changes since 4.0
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* [HTTPCLIENT-862] Extended client's redirect handling interface to allow
|
||||||
|
control of the content of the redirect.
|
||||||
|
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||||
|
|
||||||
* [HTTPCLIENT-872] HttpClient can now persist authentication data between request
|
* [HTTPCLIENT-872] HttpClient can now persist authentication data between request
|
||||||
executions as long as they share the same execution context. It has also become
|
executions as long as they share the same execution context. It has also become
|
||||||
much easier to make HttpClient authenticate preemptively by pre-populating
|
much easier to make HttpClient authenticate preemptively by pre-populating
|
||||||
|
|
|
@ -43,7 +43,10 @@ import org.apache.http.protocol.HttpContext;
|
||||||
* from multiple threads.
|
* from multiple threads.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated use {@link RedirectStrategy}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface RedirectHandler {
|
public interface RedirectHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* ====================================================================
|
||||||
|
* 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.HttpRequest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A strategy for determining if an HTTP request should be redirected to
|
||||||
|
* a new location in response to an HTTP response received from the target
|
||||||
|
* server.
|
||||||
|
* <p>
|
||||||
|
* 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.1
|
||||||
|
*/
|
||||||
|
public interface RedirectStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a request should be redirected to a new location
|
||||||
|
* given the response from the target server.
|
||||||
|
*
|
||||||
|
* @param request the executed request
|
||||||
|
* @param response the response received from the target server
|
||||||
|
* @param context the context for the request execution
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the request should be redirected, <code>false</code>
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
boolean isRedirected(
|
||||||
|
HttpRequest request,
|
||||||
|
HttpResponse response,
|
||||||
|
HttpContext context) throws ProtocolException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the redirect location given the response from the target
|
||||||
|
* server and the current request execution context and generates a new
|
||||||
|
* request to be sent to the location.
|
||||||
|
*
|
||||||
|
* @param request the executed request
|
||||||
|
* @param response the response received from the target server
|
||||||
|
* @param context the context for the request execution
|
||||||
|
*
|
||||||
|
* @return redirected request
|
||||||
|
*/
|
||||||
|
HttpUriRequest getRedirect(
|
||||||
|
HttpRequest request,
|
||||||
|
HttpResponse response,
|
||||||
|
HttpContext context) throws ProtocolException;
|
||||||
|
|
||||||
|
}
|
|
@ -47,13 +47,13 @@ import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.auth.AuthSchemeRegistry;
|
import org.apache.http.auth.AuthSchemeRegistry;
|
||||||
import org.apache.http.client.AuthenticationHandler;
|
import org.apache.http.client.AuthenticationHandler;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.RedirectStrategy;
|
||||||
import org.apache.http.client.RequestDirector;
|
import org.apache.http.client.RequestDirector;
|
||||||
import org.apache.http.client.ResponseHandler;
|
import org.apache.http.client.ResponseHandler;
|
||||||
import org.apache.http.client.CookieStore;
|
import org.apache.http.client.CookieStore;
|
||||||
import org.apache.http.client.CredentialsProvider;
|
import org.apache.http.client.CredentialsProvider;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.HttpRequestRetryHandler;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
||||||
import org.apache.http.client.RedirectHandler;
|
|
||||||
import org.apache.http.client.UserTokenHandler;
|
import org.apache.http.client.UserTokenHandler;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
|
@ -127,10 +127,10 @@ import org.apache.http.protocol.ImmutableHttpProcessor;
|
||||||
* may involve multiple intermediate hops.
|
* may involve multiple intermediate hops.
|
||||||
* The {@link #createHttpRoutePlanner()} must be implemented
|
* The {@link #createHttpRoutePlanner()} must be implemented
|
||||||
* by concrete super classes to instantiate this object.
|
* by concrete super classes to instantiate this object.
|
||||||
* <li>{@link RedirectHandler}</li> object used to determine if an HTTP
|
* <li>{@link RedirectStrategy}</li> object used to determine if an HTTP
|
||||||
* request should be redirected to a new location in response to an HTTP
|
* request should be redirected to a new location in response to an HTTP
|
||||||
* response received from the target server.
|
* response received from the target server.
|
||||||
* The {@link #createRedirectHandler()} must be implemented
|
* The {@link #createRedirectStrategy()} must be implemented
|
||||||
* by concrete super classes to instantiate this object.
|
* by concrete super classes to instantiate this object.
|
||||||
* <li>{@link UserTokenHandler}</li> object used to determine if the
|
* <li>{@link UserTokenHandler}</li> object used to determine if the
|
||||||
* execution context is user identity specific.
|
* execution context is user identity specific.
|
||||||
|
@ -200,7 +200,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
|
|
||||||
/** The redirect handler. */
|
/** The redirect handler. */
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private RedirectHandler redirectHandler;
|
private RedirectStrategy redirectStrategy;
|
||||||
|
|
||||||
/** The target authentication handler. */
|
/** The target authentication handler. */
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
|
@ -270,7 +270,13 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
protected abstract HttpRequestRetryHandler createHttpRequestRetryHandler();
|
protected abstract HttpRequestRetryHandler createHttpRequestRetryHandler();
|
||||||
|
|
||||||
|
|
||||||
protected abstract RedirectHandler createRedirectHandler();
|
@Deprecated
|
||||||
|
protected abstract org.apache.http.client.RedirectHandler createRedirectHandler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
protected abstract RedirectStrategy createRedirectStrategy();
|
||||||
|
|
||||||
|
|
||||||
protected abstract AuthenticationHandler createTargetAuthenticationHandler();
|
protected abstract AuthenticationHandler createTargetAuthenticationHandler();
|
||||||
|
@ -392,16 +398,32 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized final RedirectHandler getRedirectHandler() {
|
@Deprecated
|
||||||
if (redirectHandler == null) {
|
public synchronized final org.apache.http.client.RedirectHandler getRedirectHandler() {
|
||||||
redirectHandler = createRedirectHandler();
|
return createRedirectHandler();
|
||||||
}
|
|
||||||
return redirectHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized void setRedirectHandler(final RedirectHandler redirectHandler) {
|
@Deprecated
|
||||||
this.redirectHandler = redirectHandler;
|
public synchronized void setRedirectHandler(final org.apache.http.client.RedirectHandler redirectHandler) {
|
||||||
|
this.redirectStrategy = new DefaultRedirectStrategyAdaptor(redirectHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public synchronized final RedirectStrategy getRedirectStrategy() {
|
||||||
|
if (redirectStrategy == null) {
|
||||||
|
redirectStrategy = createRedirectStrategy();
|
||||||
|
}
|
||||||
|
return redirectStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public synchronized void setRedirectStrategy(final RedirectStrategy redirectStrategy) {
|
||||||
|
this.redirectStrategy = redirectStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -677,6 +699,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
protected RequestDirector createClientRequestDirector(
|
protected RequestDirector createClientRequestDirector(
|
||||||
final HttpRequestExecutor requestExec,
|
final HttpRequestExecutor requestExec,
|
||||||
final ClientConnectionManager conman,
|
final ClientConnectionManager conman,
|
||||||
|
@ -685,7 +708,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
final HttpRoutePlanner rouplan,
|
final HttpRoutePlanner rouplan,
|
||||||
final HttpProcessor httpProcessor,
|
final HttpProcessor httpProcessor,
|
||||||
final HttpRequestRetryHandler retryHandler,
|
final HttpRequestRetryHandler retryHandler,
|
||||||
final RedirectHandler redirectHandler,
|
final org.apache.http.client.RedirectHandler redirectHandler,
|
||||||
final AuthenticationHandler targetAuthHandler,
|
final AuthenticationHandler targetAuthHandler,
|
||||||
final AuthenticationHandler proxyAuthHandler,
|
final AuthenticationHandler proxyAuthHandler,
|
||||||
final UserTokenHandler stateHandler,
|
final UserTokenHandler stateHandler,
|
||||||
|
@ -705,6 +728,36 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||||
params);
|
params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
protected RequestDirector createClientRequestDirector(
|
||||||
|
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 AuthenticationHandler targetAuthHandler,
|
||||||
|
final AuthenticationHandler proxyAuthHandler,
|
||||||
|
final UserTokenHandler stateHandler,
|
||||||
|
final HttpParams params) {
|
||||||
|
return new DefaultRequestDirector(
|
||||||
|
requestExec,
|
||||||
|
conman,
|
||||||
|
reustrat,
|
||||||
|
kastrat,
|
||||||
|
rouplan,
|
||||||
|
httpProcessor,
|
||||||
|
retryHandler,
|
||||||
|
redirectStrategy,
|
||||||
|
targetAuthHandler,
|
||||||
|
proxyAuthHandler,
|
||||||
|
stateHandler,
|
||||||
|
params);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Obtains parameters for executing a request.
|
* Obtains parameters for executing a request.
|
||||||
* The default implementation in this class creates a new
|
* The default implementation in this class creates a new
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.apache.http.client.AuthenticationHandler;
|
||||||
import org.apache.http.client.CookieStore;
|
import org.apache.http.client.CookieStore;
|
||||||
import org.apache.http.client.CredentialsProvider;
|
import org.apache.http.client.CredentialsProvider;
|
||||||
import org.apache.http.client.HttpRequestRetryHandler;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
||||||
import org.apache.http.client.RedirectHandler;
|
import org.apache.http.client.RedirectStrategy;
|
||||||
import org.apache.http.client.UserTokenHandler;
|
import org.apache.http.client.UserTokenHandler;
|
||||||
import org.apache.http.client.params.AuthPolicy;
|
import org.apache.http.client.params.AuthPolicy;
|
||||||
import org.apache.http.client.params.ClientPNames;
|
import org.apache.http.client.params.ClientPNames;
|
||||||
|
@ -354,10 +354,19 @@ public class DefaultHttpClient extends AbstractHttpClient {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RedirectHandler createRedirectHandler() {
|
@Deprecated
|
||||||
|
protected org.apache.http.client.RedirectHandler createRedirectHandler() {
|
||||||
return new DefaultRedirectHandler();
|
return new DefaultRedirectHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected RedirectStrategy createRedirectStrategy() {
|
||||||
|
return new DefaultRedirectStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AuthenticationHandler createTargetAuthenticationHandler() {
|
protected AuthenticationHandler createTargetAuthenticationHandler() {
|
||||||
|
|
|
@ -54,8 +54,11 @@ import org.apache.http.protocol.ExecutionContext;
|
||||||
* Default implementation of {@link RedirectHandler}.
|
* Default implementation of {@link RedirectHandler}.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated use {@link DefaultRedirectStrategy}.
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
|
@Deprecated
|
||||||
public class DefaultRedirectHandler implements RedirectHandler {
|
public class DefaultRedirectHandler implements RedirectHandler {
|
||||||
|
|
||||||
private final Log log = LogFactory.getLog(getClass());
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* ====================================================================
|
||||||
|
* 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.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.apache.http.annotation.Immutable;
|
||||||
|
|
||||||
|
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.HttpRequest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
|
import org.apache.http.client.CircularRedirectException;
|
||||||
|
import org.apache.http.client.RedirectStrategy;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpHead;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.client.params.ClientPNames;
|
||||||
|
import org.apache.http.client.utils.URIUtils;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
import org.apache.http.protocol.ExecutionContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link RedirectStrategy}.
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||||
|
|
||||||
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
|
||||||
|
|
||||||
|
public DefaultRedirectStrategy() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRedirected(
|
||||||
|
final HttpRequest request,
|
||||||
|
final HttpResponse response,
|
||||||
|
final HttpContext context) throws ProtocolException {
|
||||||
|
if (response == null) {
|
||||||
|
throw new IllegalArgumentException("HTTP response may not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
|
switch (statusCode) {
|
||||||
|
case HttpStatus.SC_MOVED_TEMPORARILY:
|
||||||
|
case HttpStatus.SC_MOVED_PERMANENTLY:
|
||||||
|
case HttpStatus.SC_TEMPORARY_REDIRECT:
|
||||||
|
String method = request.getRequestLine().getMethod();
|
||||||
|
return method.equalsIgnoreCase(HttpGet.METHOD_NAME)
|
||||||
|
|| method.equalsIgnoreCase(HttpHead.METHOD_NAME);
|
||||||
|
case HttpStatus.SC_SEE_OTHER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
} //end of switch
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getLocationURI(
|
||||||
|
final HttpRequest request,
|
||||||
|
final HttpResponse response,
|
||||||
|
final HttpContext context) throws ProtocolException {
|
||||||
|
if (response == null) {
|
||||||
|
throw new IllegalArgumentException("HTTP response may not be null");
|
||||||
|
}
|
||||||
|
//get the location header to find out where to redirect to
|
||||||
|
Header locationHeader = response.getFirstHeader("location");
|
||||||
|
if (locationHeader == null) {
|
||||||
|
// got a redirect response, but no location header
|
||||||
|
throw new ProtocolException(
|
||||||
|
"Received redirect response " + response.getStatusLine()
|
||||||
|
+ " but no location header");
|
||||||
|
}
|
||||||
|
String location = locationHeader.getValue();
|
||||||
|
if (this.log.isDebugEnabled()) {
|
||||||
|
this.log.debug("Redirect requested to location '" + location + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(location);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
throw new ProtocolException("Invalid redirect URI: " + location, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpParams params = response.getParams();
|
||||||
|
// rfc2616 demands the location value be a complete URI
|
||||||
|
// Location = "Location" ":" absoluteURI
|
||||||
|
if (!uri.isAbsolute()) {
|
||||||
|
if (params.isParameterTrue(ClientPNames.REJECT_RELATIVE_REDIRECT)) {
|
||||||
|
throw new ProtocolException("Relative redirect location '"
|
||||||
|
+ uri + "' not allowed");
|
||||||
|
}
|
||||||
|
// Adjust location URI
|
||||||
|
HttpHost target = (HttpHost) context.getAttribute(
|
||||||
|
ExecutionContext.HTTP_TARGET_HOST);
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalStateException("Target host not available " +
|
||||||
|
"in the HTTP context");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
URI requestURI = new URI(request.getRequestLine().getUri());
|
||||||
|
URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, true);
|
||||||
|
uri = URIUtils.resolve(absoluteRequestURI, uri);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
throw new ProtocolException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.isParameterFalse(ClientPNames.ALLOW_CIRCULAR_REDIRECTS)) {
|
||||||
|
|
||||||
|
RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute(
|
||||||
|
REDIRECT_LOCATIONS);
|
||||||
|
|
||||||
|
if (redirectLocations == null) {
|
||||||
|
redirectLocations = new RedirectLocations();
|
||||||
|
context.setAttribute(REDIRECT_LOCATIONS, redirectLocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
URI redirectURI;
|
||||||
|
if (uri.getFragment() != null) {
|
||||||
|
try {
|
||||||
|
HttpHost target = new HttpHost(
|
||||||
|
uri.getHost(),
|
||||||
|
uri.getPort(),
|
||||||
|
uri.getScheme());
|
||||||
|
redirectURI = URIUtils.rewriteURI(uri, target, true);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
throw new ProtocolException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
redirectURI = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirectLocations.contains(redirectURI)) {
|
||||||
|
throw new CircularRedirectException("Circular redirect to '" +
|
||||||
|
redirectURI + "'");
|
||||||
|
} else {
|
||||||
|
redirectLocations.add(redirectURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUriRequest getRedirect(
|
||||||
|
final HttpRequest request,
|
||||||
|
final HttpResponse response,
|
||||||
|
final HttpContext context) throws ProtocolException {
|
||||||
|
URI uri = getLocationURI(request, response, context);
|
||||||
|
String method = request.getRequestLine().getMethod();
|
||||||
|
if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
|
||||||
|
return new HttpHead(uri);
|
||||||
|
} else {
|
||||||
|
return new HttpGet(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,35 +29,49 @@ package org.apache.http.impl.client;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
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.RedirectStrategy;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpHead;
|
import org.apache.http.client.methods.HttpHead;
|
||||||
import org.apache.http.client.methods.HttpRequestBase;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect request (can be either GET or HEAD).
|
* @since 4.1
|
||||||
*
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@Immutable
|
||||||
class HttpRedirect extends HttpRequestBase {
|
@Deprecated
|
||||||
|
class DefaultRedirectStrategyAdaptor implements RedirectStrategy {
|
||||||
|
|
||||||
private String method;
|
private final org.apache.http.client.RedirectHandler handler;
|
||||||
|
|
||||||
public HttpRedirect(final String method, final URI uri) {
|
@Deprecated
|
||||||
|
public DefaultRedirectStrategyAdaptor(final org.apache.http.client.RedirectHandler handler) {
|
||||||
super();
|
super();
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRedirected(
|
||||||
|
final HttpRequest request,
|
||||||
|
final HttpResponse response,
|
||||||
|
final HttpContext context) throws ProtocolException {
|
||||||
|
return this.handler.isRedirectRequested(response, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUriRequest getRedirect(
|
||||||
|
final HttpRequest request,
|
||||||
|
final HttpResponse response,
|
||||||
|
final HttpContext context) throws ProtocolException {
|
||||||
|
URI uri = this.handler.getLocationURI(response, context);
|
||||||
|
String method = request.getRequestLine().getMethod();
|
||||||
if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
|
if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
|
||||||
this.method = HttpHead.METHOD_NAME;
|
return new HttpHead(uri);
|
||||||
} else {
|
} else {
|
||||||
this.method = HttpGet.METHOD_NAME;
|
return new HttpGet(uri);
|
||||||
}
|
}
|
||||||
setURI(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMethod() {
|
|
||||||
return this.method;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -56,14 +56,15 @@ import org.apache.http.auth.AuthenticationException;
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.client.AuthenticationHandler;
|
import org.apache.http.client.AuthenticationHandler;
|
||||||
|
import org.apache.http.client.RedirectStrategy;
|
||||||
import org.apache.http.client.RequestDirector;
|
import org.apache.http.client.RequestDirector;
|
||||||
import org.apache.http.client.CredentialsProvider;
|
import org.apache.http.client.CredentialsProvider;
|
||||||
import org.apache.http.client.HttpRequestRetryHandler;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
||||||
import org.apache.http.client.NonRepeatableRequestException;
|
import org.apache.http.client.NonRepeatableRequestException;
|
||||||
import org.apache.http.client.RedirectException;
|
import org.apache.http.client.RedirectException;
|
||||||
import org.apache.http.client.RedirectHandler;
|
|
||||||
import org.apache.http.client.UserTokenHandler;
|
import org.apache.http.client.UserTokenHandler;
|
||||||
import org.apache.http.client.methods.AbortableHttpRequest;
|
import org.apache.http.client.methods.AbortableHttpRequest;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.params.ClientPNames;
|
import org.apache.http.client.params.ClientPNames;
|
||||||
import org.apache.http.client.params.HttpClientParams;
|
import org.apache.http.client.params.HttpClientParams;
|
||||||
import org.apache.http.client.protocol.ClientContext;
|
import org.apache.http.client.protocol.ClientContext;
|
||||||
|
@ -158,7 +159,11 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
protected final HttpRequestRetryHandler retryHandler;
|
protected final HttpRequestRetryHandler retryHandler;
|
||||||
|
|
||||||
/** The redirect handler. */
|
/** The redirect handler. */
|
||||||
protected final RedirectHandler redirectHandler;
|
@Deprecated
|
||||||
|
protected final org.apache.http.client.RedirectHandler redirectHandler = null;
|
||||||
|
|
||||||
|
/** The redirect strategy. */
|
||||||
|
protected final RedirectStrategy redirectStrategy;
|
||||||
|
|
||||||
/** The target authentication handler. */
|
/** The target authentication handler. */
|
||||||
protected final AuthenticationHandler targetAuthHandler;
|
protected final AuthenticationHandler targetAuthHandler;
|
||||||
|
@ -185,6 +190,7 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
|
|
||||||
private HttpHost virtualHost;
|
private HttpHost virtualHost;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public DefaultRequestDirector(
|
public DefaultRequestDirector(
|
||||||
final HttpRequestExecutor requestExec,
|
final HttpRequestExecutor requestExec,
|
||||||
final ClientConnectionManager conman,
|
final ClientConnectionManager conman,
|
||||||
|
@ -193,7 +199,29 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
final HttpRoutePlanner rouplan,
|
final HttpRoutePlanner rouplan,
|
||||||
final HttpProcessor httpProcessor,
|
final HttpProcessor httpProcessor,
|
||||||
final HttpRequestRetryHandler retryHandler,
|
final HttpRequestRetryHandler retryHandler,
|
||||||
final RedirectHandler redirectHandler,
|
final org.apache.http.client.RedirectHandler redirectHandler,
|
||||||
|
final AuthenticationHandler targetAuthHandler,
|
||||||
|
final AuthenticationHandler proxyAuthHandler,
|
||||||
|
final UserTokenHandler userTokenHandler,
|
||||||
|
final HttpParams params) {
|
||||||
|
this(requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler,
|
||||||
|
new DefaultRedirectStrategyAdaptor(redirectHandler),
|
||||||
|
targetAuthHandler, proxyAuthHandler, userTokenHandler, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
public DefaultRequestDirector(
|
||||||
|
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 AuthenticationHandler targetAuthHandler,
|
final AuthenticationHandler targetAuthHandler,
|
||||||
final AuthenticationHandler proxyAuthHandler,
|
final AuthenticationHandler proxyAuthHandler,
|
||||||
final UserTokenHandler userTokenHandler,
|
final UserTokenHandler userTokenHandler,
|
||||||
|
@ -227,9 +255,9 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
("HTTP request retry handler may not be null.");
|
("HTTP request retry handler may not be null.");
|
||||||
}
|
}
|
||||||
if (redirectHandler == null) {
|
if (redirectStrategy == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
("Redirect handler may not be null.");
|
("Redirect strategy may not be null.");
|
||||||
}
|
}
|
||||||
if (targetAuthHandler == null) {
|
if (targetAuthHandler == null) {
|
||||||
throw new IllegalArgumentException
|
throw new IllegalArgumentException
|
||||||
|
@ -254,7 +282,7 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
this.routePlanner = rouplan;
|
this.routePlanner = rouplan;
|
||||||
this.httpProcessor = httpProcessor;
|
this.httpProcessor = httpProcessor;
|
||||||
this.retryHandler = retryHandler;
|
this.retryHandler = retryHandler;
|
||||||
this.redirectHandler = redirectHandler;
|
this.redirectStrategy = redirectStrategy;
|
||||||
this.targetAuthHandler = targetAuthHandler;
|
this.targetAuthHandler = targetAuthHandler;
|
||||||
this.proxyAuthHandler = proxyAuthHandler;
|
this.proxyAuthHandler = proxyAuthHandler;
|
||||||
this.userTokenHandler = userTokenHandler;
|
this.userTokenHandler = userTokenHandler;
|
||||||
|
@ -810,7 +838,6 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
|
||||||
int status = response.getStatusLine().getStatusCode(); // can't be null
|
int status = response.getStatusLine().getStatusCode(); // can't be null
|
||||||
|
|
||||||
if (status > 299) {
|
if (status > 299) {
|
||||||
|
@ -936,7 +963,7 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
|
|
||||||
HttpParams params = request.getParams();
|
HttpParams params = request.getParams();
|
||||||
if (HttpClientParams.isRedirecting(params) &&
|
if (HttpClientParams.isRedirecting(params) &&
|
||||||
this.redirectHandler.isRedirectRequested(response, context)) {
|
this.redirectStrategy.isRedirected(request, response, context)) {
|
||||||
|
|
||||||
if (redirectCount >= maxRedirects) {
|
if (redirectCount >= maxRedirects) {
|
||||||
throw new RedirectException("Maximum redirects ("
|
throw new RedirectException("Maximum redirects ("
|
||||||
|
@ -947,7 +974,11 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
// Virtual host cannot be used any longer
|
// Virtual host cannot be used any longer
|
||||||
virtualHost = null;
|
virtualHost = null;
|
||||||
|
|
||||||
URI uri = this.redirectHandler.getLocationURI(response, context);
|
HttpUriRequest redirect = redirectStrategy.getRedirect(request, response, context);
|
||||||
|
HttpRequest orig = request.getOriginal();
|
||||||
|
redirect.setHeaders(orig.getAllHeaders());
|
||||||
|
|
||||||
|
URI uri = redirect.getURI();
|
||||||
|
|
||||||
HttpHost newTarget = new HttpHost(
|
HttpHost newTarget = new HttpHost(
|
||||||
uri.getHost(),
|
uri.getHost(),
|
||||||
|
@ -967,10 +998,6 @@ public class DefaultRequestDirector implements RequestDirector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpRedirect redirect = new HttpRedirect(request.getMethod(), uri);
|
|
||||||
HttpRequest orig = request.getOriginal();
|
|
||||||
redirect.setHeaders(orig.getAllHeaders());
|
|
||||||
|
|
||||||
RequestWrapper wrapper = new RequestWrapper(redirect);
|
RequestWrapper wrapper = new RequestWrapper(redirect);
|
||||||
wrapper.setParams(params);
|
wrapper.setParams(params);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue