Initial port of the redirect handling code
git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@537378 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9a534e7e8d
commit
c04bd63e47
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* $HeadURL$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.http.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A handler 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>
|
||||||
|
* Classes implementing this interface must synchronize access to shared
|
||||||
|
* data as methods of this interfrace may be executed from multiple threads
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
|
||||||
|
*/
|
||||||
|
public interface RedirectHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a request should be redirected to a new location
|
||||||
|
* given the response from the target server.
|
||||||
|
*
|
||||||
|
* @param response the response received from the target server
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the request should be redirected, <code>false</code>
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
boolean isRedirectNeeded(HttpResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the location request is expected to be redirected to
|
||||||
|
* given the response from the target server and the current request
|
||||||
|
* execution context.
|
||||||
|
*
|
||||||
|
* @param response the response received from the target server
|
||||||
|
* @param context the context for the request execution
|
||||||
|
*
|
||||||
|
* @return redirect URI
|
||||||
|
*/
|
||||||
|
URI getLocationURI(HttpResponse response, HttpContext context)
|
||||||
|
throws ProtocolException;
|
||||||
|
|
||||||
|
}
|
|
@ -69,6 +69,14 @@ public class HttpClientParams {
|
||||||
*/
|
*/
|
||||||
public static final String PREEMPTIVE_AUTHENTICATION = "http.authentication.preemptive";
|
public static final String PREEMPTIVE_AUTHENTICATION = "http.authentication.preemptive";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines whether redirects should be handled automatically
|
||||||
|
* <p>
|
||||||
|
* This parameter expects a value of type {@link Boolean}.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static final String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines whether relative redirects should be rejected.
|
* Defines whether relative redirects should be rejected.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -104,6 +112,15 @@ public class HttpClientParams {
|
||||||
*/
|
*/
|
||||||
public static final String COOKIE_POLICY = "http.protocol.cookie-policy";
|
public static final String COOKIE_POLICY = "http.protocol.cookie-policy";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the request headers to be sent per default with each request.
|
||||||
|
* <p>
|
||||||
|
* This parameter expects a value of type {@link java.util.Collection}. The
|
||||||
|
* collection is expected to contain {@link org.apache.http.Header}s.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_HEADERS = "http.default-headers";
|
||||||
|
|
||||||
private HttpClientParams() {
|
private HttpClientParams() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,17 @@ public final class HttpRoute {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new direct insecure route.
|
||||||
|
* That is a route without a proxy.
|
||||||
|
*
|
||||||
|
* @param target the host to which to route
|
||||||
|
*/
|
||||||
|
public HttpRoute(HttpHost target) {
|
||||||
|
this(target, null, null, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new route through a proxy.
|
* Creates a new route through a proxy.
|
||||||
* When using this constructor, the <code>proxy</code> MUST be given.
|
* When using this constructor, the <code>proxy</code> MUST be given.
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.apache.http.client.ClientRequestDirector;
|
||||||
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.HttpState;
|
import org.apache.http.client.HttpState;
|
||||||
|
import org.apache.http.client.RedirectHandler;
|
||||||
import org.apache.http.client.RoutedRequest;
|
import org.apache.http.client.RoutedRequest;
|
||||||
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;
|
||||||
|
@ -99,6 +100,9 @@ public abstract class AbstractHttpClient
|
||||||
/** The request retry handler. */
|
/** The request retry handler. */
|
||||||
private HttpRequestRetryHandler retryHandler;
|
private HttpRequestRetryHandler retryHandler;
|
||||||
|
|
||||||
|
/** The redirect handler. */
|
||||||
|
private RedirectHandler redirectHandler;
|
||||||
|
|
||||||
/** The default HTTP state. */
|
/** The default HTTP state. */
|
||||||
private HttpState defaultState;
|
private HttpState defaultState;
|
||||||
|
|
||||||
|
@ -140,6 +144,9 @@ public abstract class AbstractHttpClient
|
||||||
protected abstract HttpRequestRetryHandler createHttpRequestRetryHandler();
|
protected abstract HttpRequestRetryHandler createHttpRequestRetryHandler();
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract RedirectHandler createRedirectHandler();
|
||||||
|
|
||||||
|
|
||||||
protected abstract HttpState createHttpState();
|
protected abstract HttpState createHttpState();
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,6 +238,19 @@ public abstract class AbstractHttpClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized final RedirectHandler getRedirectHandler() {
|
||||||
|
if (redirectHandler == null) {
|
||||||
|
redirectHandler = createRedirectHandler();
|
||||||
|
}
|
||||||
|
return redirectHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void setRedirectHandler(final RedirectHandler redirectHandler) {
|
||||||
|
this.redirectHandler = redirectHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized final HttpState getState() {
|
public synchronized final HttpState getState() {
|
||||||
if (defaultState == null) {
|
if (defaultState == null) {
|
||||||
defaultState = createHttpState();
|
defaultState = createHttpState();
|
||||||
|
@ -397,6 +417,7 @@ public abstract class AbstractHttpClient
|
||||||
getConnectionReuseStrategy(),
|
getConnectionReuseStrategy(),
|
||||||
getHttpProcessor().copy(),
|
getHttpProcessor().copy(),
|
||||||
getHttpRequestRetryHandler(),
|
getHttpRequestRetryHandler(),
|
||||||
|
getRedirectHandler(),
|
||||||
getParams());
|
getParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,16 @@
|
||||||
package org.apache.http.impl.client;
|
package org.apache.http.impl.client;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.http.ConnectionReuseStrategy;
|
import org.apache.http.ConnectionReuseStrategy;
|
||||||
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpEntityEnclosingRequest;
|
import org.apache.http.HttpEntityEnclosingRequest;
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
|
@ -48,8 +52,10 @@ import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.ProtocolException;
|
import org.apache.http.ProtocolException;
|
||||||
import org.apache.http.client.ClientRequestDirector;
|
import org.apache.http.client.ClientRequestDirector;
|
||||||
import org.apache.http.client.HttpRequestRetryHandler;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
||||||
|
import org.apache.http.client.RedirectHandler;
|
||||||
import org.apache.http.client.RoutedRequest;
|
import org.apache.http.client.RoutedRequest;
|
||||||
import org.apache.http.client.methods.AbortableHttpRequest;
|
import org.apache.http.client.methods.AbortableHttpRequest;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.params.HttpClientParams;
|
import org.apache.http.client.params.HttpClientParams;
|
||||||
import org.apache.http.conn.BasicManagedEntity;
|
import org.apache.http.conn.BasicManagedEntity;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
|
@ -57,6 +63,8 @@ import org.apache.http.conn.ConnectionPoolTimeoutException;
|
||||||
import org.apache.http.conn.HttpRoute;
|
import org.apache.http.conn.HttpRoute;
|
||||||
import org.apache.http.conn.ManagedClientConnection;
|
import org.apache.http.conn.ManagedClientConnection;
|
||||||
import org.apache.http.conn.RouteDirector;
|
import org.apache.http.conn.RouteDirector;
|
||||||
|
import org.apache.http.conn.Scheme;
|
||||||
|
import org.apache.http.conn.SchemeRegistry;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.params.HttpConnectionParams;
|
import org.apache.http.params.HttpConnectionParams;
|
||||||
import org.apache.http.params.HttpParams;
|
import org.apache.http.params.HttpParams;
|
||||||
|
@ -98,6 +106,9 @@ public class DefaultClientRequestDirector
|
||||||
/** The request retry handler. */
|
/** The request retry handler. */
|
||||||
protected final HttpRequestRetryHandler retryHandler;
|
protected final HttpRequestRetryHandler retryHandler;
|
||||||
|
|
||||||
|
/** The redirect handler. */
|
||||||
|
protected final RedirectHandler redirectHandler;
|
||||||
|
|
||||||
/** The HTTP parameters. */
|
/** The HTTP parameters. */
|
||||||
protected final HttpParams params;
|
protected final HttpParams params;
|
||||||
|
|
||||||
|
@ -110,6 +121,7 @@ public class DefaultClientRequestDirector
|
||||||
final ConnectionReuseStrategy reustrat,
|
final ConnectionReuseStrategy reustrat,
|
||||||
final HttpProcessor httpProcessor,
|
final HttpProcessor httpProcessor,
|
||||||
final HttpRequestRetryHandler retryHandler,
|
final HttpRequestRetryHandler retryHandler,
|
||||||
|
final RedirectHandler redirectHandler,
|
||||||
final HttpParams params) {
|
final HttpParams params) {
|
||||||
|
|
||||||
if (conman == null) {
|
if (conman == null) {
|
||||||
|
@ -124,6 +136,9 @@ public class DefaultClientRequestDirector
|
||||||
if (retryHandler == null) {
|
if (retryHandler == null) {
|
||||||
throw new IllegalArgumentException("HTTP request retry handler may not be null");
|
throw new IllegalArgumentException("HTTP request retry handler may not be null");
|
||||||
}
|
}
|
||||||
|
if (redirectHandler == null) {
|
||||||
|
throw new IllegalArgumentException("Redirect handler may not be null");
|
||||||
|
}
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
throw new IllegalArgumentException("HTTP parameters may not be null");
|
throw new IllegalArgumentException("HTTP parameters may not be null");
|
||||||
}
|
}
|
||||||
|
@ -131,6 +146,7 @@ public class DefaultClientRequestDirector
|
||||||
this.reuseStrategy = reustrat;
|
this.reuseStrategy = reustrat;
|
||||||
this.httpProcessor = httpProcessor;
|
this.httpProcessor = httpProcessor;
|
||||||
this.retryHandler = retryHandler;
|
this.retryHandler = retryHandler;
|
||||||
|
this.redirectHandler = redirectHandler;
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this.requestExec = new HttpRequestExecutor(params);
|
this.requestExec = new HttpRequestExecutor(params);
|
||||||
|
|
||||||
|
@ -206,20 +222,35 @@ public class DefaultClientRequestDirector
|
||||||
public HttpResponse execute(RoutedRequest roureq, HttpContext context)
|
public HttpResponse execute(RoutedRequest roureq, HttpContext context)
|
||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
RequestWrapper request = wrapRequest(roureq.getRequest());
|
HttpRequest orig = roureq.getRequest();
|
||||||
|
|
||||||
|
// Link parameter collections to form a hierarchy:
|
||||||
|
// request -> client
|
||||||
|
orig.getParams().setDefaults(this.params);
|
||||||
|
|
||||||
|
// Add default headers
|
||||||
|
Collection defHeaders = (Collection) orig.getParams().getParameter(
|
||||||
|
HttpClientParams.DEFAULT_HEADERS);
|
||||||
|
if (defHeaders != null) {
|
||||||
|
for (Iterator it = defHeaders.iterator(); it.hasNext(); ) {
|
||||||
|
orig.addHeader((Header) it.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int execCount = 0;
|
||||||
|
|
||||||
HttpResponse response = null;
|
HttpResponse response = null;
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int execCount = 0;
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
|
|
||||||
|
RequestWrapper request = wrapRequest(roureq.getRequest());
|
||||||
HttpRoute route = roureq.getRoute();
|
HttpRoute route = roureq.getRoute();
|
||||||
|
|
||||||
// Re-write request URI if needed
|
// Re-write request URI if needed
|
||||||
rewriteRequestURI(request, route);
|
rewriteRequestURI(request, route);
|
||||||
|
|
||||||
if (managedConn == null) {
|
if (managedConn == null || !managedConn.isOpen()) {
|
||||||
managedConn = allocateConnection(route);
|
managedConn = allocateConnection(route);
|
||||||
}
|
}
|
||||||
establishRoute(route, context);
|
establishRoute(route, context);
|
||||||
|
@ -465,9 +496,9 @@ public class DefaultClientRequestDirector
|
||||||
* Analyzes a response to check need for a followup.
|
* Analyzes a response to check need for a followup.
|
||||||
*
|
*
|
||||||
* @param roureq the request and route. This is the same object as
|
* @param roureq the request and route. This is the same object as
|
||||||
* was passed to {@link #prepareRequest prepareRequest}.
|
* was passed to {@link #wrapRequest(HttpRequest)}.
|
||||||
* @param request the request that was actually sent. This is the object
|
* @param request the request that was actually sent. This is the object
|
||||||
* returned by {@link #prepareRequest prepareRequest}.
|
* returned by {@link #wrapRequest(HttpRequest)}.
|
||||||
* @param response the response to analayze
|
* @param response the response to analayze
|
||||||
* @param context the context used for the current request execution
|
* @param context the context used for the current request execution
|
||||||
*
|
*
|
||||||
|
@ -483,15 +514,50 @@ public class DefaultClientRequestDirector
|
||||||
HttpContext context)
|
HttpContext context)
|
||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
//@@@ if there is a followup, check connection keep-alive and
|
HttpParams params = request.getParams();
|
||||||
//@@@ consume response body if necessary or close otherwise
|
if (params.getBooleanParameter(HttpClientParams.HANDLE_REDIRECTS, true) &&
|
||||||
|
this.redirectHandler.isRedirectNeeded(response)) {
|
||||||
//@@@ if the request needs to be re-sent with authentication,
|
|
||||||
//@@@ how to revert the modifications applied by the interceptors?
|
|
||||||
//@@@ use a wrapper when sending?
|
|
||||||
|
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = this.redirectHandler.getLocationURI(response, context);
|
||||||
|
} catch (ProtocolException ex) {
|
||||||
|
if (LOG.isWarnEnabled()) {
|
||||||
|
LOG.warn(ex.getMessage());
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRoute oldRoute = roureq.getRoute();
|
||||||
|
|
||||||
|
HttpHost newTarget = new HttpHost(
|
||||||
|
uri.getHost(),
|
||||||
|
uri.getPort(),
|
||||||
|
uri.getScheme());
|
||||||
|
|
||||||
|
SchemeRegistry schemeRegistry = this.connManager.getSchemeRegistry();
|
||||||
|
Scheme schm = schemeRegistry.getScheme(newTarget.getSchemeName());
|
||||||
|
|
||||||
|
InetAddress localAddress = oldRoute.getLocalAddress();
|
||||||
|
HttpHost proxy = oldRoute.getProxyHost();
|
||||||
|
|
||||||
|
HttpRoute newRoute = new HttpRoute(
|
||||||
|
newTarget,
|
||||||
|
localAddress,
|
||||||
|
proxy,
|
||||||
|
schm.isLayered(),
|
||||||
|
(proxy != null),
|
||||||
|
(proxy != null));
|
||||||
|
|
||||||
|
HttpGet redirect = new HttpGet(uri);
|
||||||
|
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("Redirecting to '" + uri + "' via " + newRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RoutedRequest.Impl(redirect, newRoute);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
} // handleResponse
|
} // handleResponse
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.auth.AuthSchemeRegistry;
|
import org.apache.http.auth.AuthSchemeRegistry;
|
||||||
import org.apache.http.client.HttpRequestRetryHandler;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
||||||
import org.apache.http.client.HttpState;
|
import org.apache.http.client.HttpState;
|
||||||
|
import org.apache.http.client.RedirectHandler;
|
||||||
import org.apache.http.client.RoutedRequest;
|
import org.apache.http.client.RoutedRequest;
|
||||||
import org.apache.http.client.params.AuthPolicy;
|
import org.apache.http.client.params.AuthPolicy;
|
||||||
import org.apache.http.client.params.CookiePolicy;
|
import org.apache.http.client.params.CookiePolicy;
|
||||||
|
@ -211,6 +212,11 @@ public class DefaultHttpClient extends AbstractHttpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected RedirectHandler createRedirectHandler() {
|
||||||
|
return new DefaultRedirectHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected HttpState createHttpState() {
|
protected HttpState createHttpState() {
|
||||||
return new HttpState();
|
return new HttpState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* $HeadURL$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.http.impl.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
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.HttpStatus;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
|
import org.apache.http.client.RedirectHandler;
|
||||||
|
import org.apache.http.client.params.HttpClientParams;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
import org.apache.http.protocol.HttpExecutionContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of a redirect handler.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
|
||||||
|
*
|
||||||
|
* <!-- empty lines to avoid svn diff problems -->
|
||||||
|
* @version $Revision$
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class DefaultRedirectHandler implements RedirectHandler {
|
||||||
|
|
||||||
|
private static final Log LOG = LogFactory.getLog(DefaultRedirectHandler.class);
|
||||||
|
|
||||||
|
public boolean isRedirectNeeded(final HttpResponse response) {
|
||||||
|
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_SEE_OTHER:
|
||||||
|
case HttpStatus.SC_TEMPORARY_REDIRECT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
} //end of switch
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getLocationURI(
|
||||||
|
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 (LOG.isDebugEnabled()) {
|
||||||
|
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(HttpClientParams.REJECT_RELATIVE_REDIRECT)) {
|
||||||
|
throw new ProtocolException("Relative redirect location '"
|
||||||
|
+ uri + "' not allowed");
|
||||||
|
}
|
||||||
|
// Adjust location URI
|
||||||
|
HttpHost target = (HttpHost) context.getAttribute(
|
||||||
|
HttpExecutionContext.HTTP_TARGET_HOST);
|
||||||
|
if (target == null) {
|
||||||
|
throw new IllegalStateException("Target host not available " +
|
||||||
|
"in the HTTP context");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
uri = new URI(
|
||||||
|
target.getSchemeName(),
|
||||||
|
null,
|
||||||
|
target.getHostName(),
|
||||||
|
target.getPort(),
|
||||||
|
uri.getPath(),
|
||||||
|
uri.getQuery(),
|
||||||
|
uri.getFragment());
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
throw new ProtocolException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -130,8 +130,8 @@ class RequestWrapper extends AbstractHttpMessage implements HttpUriRequest {
|
||||||
return new BasicRequestLine(method, uritext, ver);
|
return new BasicRequestLine(method, uritext, ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetHeaders() {
|
public HttpRequest getOriginal() {
|
||||||
setHeaders(this.original.getAllHeaders());
|
return this.original;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue