51 votes

HttpClient 4 - comment capturer la dernière URL de redirection

J'ai plutôt simple HttpClient 4 du code qui appelle HttpGet pour obtenir la sortie HTML. Le HTML retourne avec des scripts et de l'image emplacements de tous locales (par exemple, <img src="/images/foo.jpg"/>) donc j'ai besoin d'appeler une URL à faire dans l'absolu (<img src="http://foo.com/images/foo.jpg"/>), vient Maintenant le problème lors de l'appel, il peut y avoir un ou deux 302 redirige donc l'URL d'origine est ne reflète plus l'emplacement de HTML.

Comment puis-je obtenir la dernière adresse URL du contenu retourné, compte tenu de toutes les redirections je peut (ou peut ne pas) avoir?

J'ai regardé HttpGet#getAllHeaders() et HttpResponse#getAllHeaders() - ne pouvait pas trouver quoi que ce soit.

Modifié: HttpGet#getURI() retours d'origine appel à l'adresse

64voto

ZZ Coder Points 36990

Que serait l'URL courante, que vous pouvez obtenir en appelant

  HttpGet#getURI();

EDIT: Vous n'avez pas mentionné la façon dont vous faites de redirection. Qui fonctionne pour nous car nous nous occupons de l'302 nous-mêmes.

On dirait que vous utilisez DefaultRedirectHandler. Nous avons l'habitude de le faire. C'est un peu difficile à obtenir l'URL actuelle. Vous devez utiliser votre propre contexte. Voici les extraits de code,

        HttpGet httpget = new HttpGet(url);
        HttpContext context = new BasicHttpContext(); 
        HttpResponse response = httpClient.execute(httpget, context); 
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            throw new IOException(response.getStatusLine().toString());
        HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute( 
                ExecutionContext.HTTP_REQUEST);
        HttpHost currentHost = (HttpHost)  context.getAttribute( 
                ExecutionContext.HTTP_TARGET_HOST);
        String currentUrl = (currentReq.getURI().isAbsolute()) ? currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());

La redirection par défaut n'a pas de travail pour nous afin que nous changé, mais j'ai oublié quel était le problème.

42voto

david_p Points 483

Dans HttpClient 4, si vous utilisez LaxRedirectStrategy ou d'une sous-classe de DefaultRedirectStrategy, c'est la manière recommandée (voir le code source d' DefaultRedirectStrategy) :

HttpContext context = new BasicHttpContext();
HttpResult<T> result = client.execute(request, handler, context);
URI finalUrl = request.getURI();
RedirectLocations locations = (RedirectLocations) context.getAttribute(DefaultRedirectStrategy.REDIRECT_LOCATIONS);
if (locations != null) {
    finalUrl = locations.getAll().get(locations.getAll().size() - 1);
}

13voto

Atharva Points 624
    HttpHead httpHead = new HttpHead("<put your URL here>");
    HttpClient httpClient = HttpClients.createDefault();
    HttpClientContext context = HttpClientContext.create();
    httpClient.execute(httpHead, context);
    List<URI> redirectURIs = context.getRedirectLocations();
    if (redirectURIs != null && !redirectURIs.isEmpty()) {
        for (URI redirectURI : redirectURIs) {
            System.out.println("Redirect URI: " + redirectURI);
        }
    }

6voto

Michael Pollmeier Points 402

Mon humble avis une manière améliorée basée sur ZZ Coder la solution est d'utiliser un ResponseInterceptor pour simplement suivre la dernière rediriger emplacement. De cette façon, vous ne perdez plus d'informations, par exemple, après un hashtag. Sans l'intervention de l'intercepteur vous perdez le hashtag. Exemple: http://j.mp/OxbI23

private static HttpClient createHttpClient() throws NoSuchAlgorithmException, KeyManagementException {
    SSLContext sslContext = SSLContext.getInstance("SSL");
    TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllTrustManager() };
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

    SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("https", 443, sslSocketFactory));
    schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory()));

    HttpParams params = new BasicHttpParams();
    ClientConnectionManager cm = new org.apache.http.impl.conn.SingleClientConnManager(schemeRegistry);

    // some pages require a user agent
    AbstractHttpClient httpClient = new DefaultHttpClient(cm, params);
    HttpProtocolParams.setUserAgent(httpClient.getParams(), "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1");

    httpClient.setRedirectStrategy(new RedirectStrategy());

    httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
        @Override
        public void process(HttpResponse response, HttpContext context)
                throws HttpException, IOException {
            if (response.containsHeader("Location")) {
                Header[] locations = response.getHeaders("Location");
                if (locations.length > 0)
                    context.setAttribute(LAST_REDIRECT_URL, locations[0].getValue());
            }
        }
    });

    return httpClient;
}

private String getUrlAfterRedirects(HttpContext context) {
    String lastRedirectUrl = (String) context.getAttribute(LAST_REDIRECT_URL);
    if (lastRedirectUrl != null)
        return lastRedirectUrl;
    else {
        HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
        HttpHost currentHost = (HttpHost)  context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
        String currentUrl = (currentReq.getURI().isAbsolute()) ? currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());
        return currentUrl;
    }
}

public static final String LAST_REDIRECT_URL = "last_redirect_url";

l'utiliser comme ZZ Coder la solution:

HttpResponse response = httpClient.execute(httpGet, context);
String url = getUrlAfterRedirects(context);

4voto

ydanila Points 76

Je pense que de moyen plus facile de trouver de la dernière URL est d'utiliser DefaultRedirectHandler.

package ru.test.test;

import java.net.URI;

import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.impl.client.DefaultRedirectHandler;
import org.apache.http.protocol.HttpContext;

public class MyRedirectHandler extends DefaultRedirectHandler {

    public URI lastRedirectedUri;

    @Override
    public boolean isRedirectRequested(HttpResponse response, HttpContext context) {

        return super.isRedirectRequested(response, context);
    }

    @Override
    public URI getLocationURI(HttpResponse response, HttpContext context)
            throws ProtocolException {

        lastRedirectedUri = super.getLocationURI(response, context);

        return lastRedirectedUri;
    }

}

Code pour utiliser cette fonction:

  DefaultHttpClient httpclient = new DefaultHttpClient();
  MyRedirectHandler handler = new MyRedirectHandler();
  httpclient.setRedirectHandler(handler);

  HttpGet get = new HttpGet(url);

  HttpResponse response = httpclient.execute(get);

  HttpEntity entity = response.getEntity();
  lastUrl = url;
  if(handler.lastRedirectedUri != null){
      lastUrl = handler.lastRedirectedUri.toString();
  }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X