Domanda

Ho piuttosto semplice codice HttpClient 4 che chiama HttpGet per ottenere l'output HTML. I rendimenti HTML con script e le posizioni di immagine tutti insieme per locali (ad es <img src="/images/foo.jpg"/>) quindi ho bisogno di chiamare URL per fare questi in assoluto (<img src="http://foo.com/images/foo.jpg"/>) Ora viene il problema - durante la chiamata ci possono essere uno o due 302 redirect così l'URL originale è non riflette la posizione di HTML.

Come faccio a ottenere l'ultimo URL del contenuto restituito dato tutti i reindirizzamenti che può (o non può) avere?

Ho guardato HttpGet#getAllHeaders() e HttpResponse#getAllHeaders() - non poteva trovare nulla

.

A cura: HttpGet#getURI() restituisce l'indirizzo di chiamata originale

È stato utile?

Soluzione

Questa sarebbe l'URL corrente, che si può ottenere chiamando

  HttpGet#getURI();

EDIT: Non hai parlato di come si sta facendo reindirizzamento. Che lavora per noi, perché gestiamo il 302 noi stessi.

Suona come si sta utilizzando DefaultRedirectHandler. Abbiamo usato per farlo. È un po 'difficile da ottenere l'URL corrente. È necessario utilizzare il proprio contesto. Qui ci sono i frammenti di codice rilevanti,

        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());

Il reindirizzamento di default non ha funzionato per noi, così abbiamo cambiato ma ho dimenticato quello che era il problema.

Altri suggerimenti

In HttpClient 4, se si utilizza LaxRedirectStrategy o qualsiasi sottoclasse di DefaultRedirectStrategy, questo è il modo consigliato (vedere il codice sorgente di 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);
}

Da HttpClient 4.3.x, il codice precedente può essere semplificata come:

HttpClientContext context = HttpClientContext.create();
HttpResult<T> result = client.execute(request, handler, context);
URI finalUrl = request.getURI();
List<URI> locations = context.getRedirectLocations();
if (locations != null) {
    finalUrl = locations.get(locations.size() - 1);
}
    HttpGet httpGet = new HttpHead("<put your URL here>");
    HttpClient httpClient = HttpClients.createDefault();
    HttpClientContext context = HttpClientContext.create();
    httpClient.execute(httpGet, context);
    List<URI> redirectURIs = context.getRedirectLocations();
    if (redirectURIs != null && !redirectURIs.isEmpty()) {
        for (URI redirectURI : redirectURIs) {
            System.out.println("Redirect URI: " + redirectURI);
        }
        URI finalURI = redirectURIs.get(redirectURIs.size() - 1);
    }

Un IMHO migliorato modo basato sulla soluzione di ZZ Coder è quello di utilizzare un ResponseInterceptor per monitorare semplicemente l'ultima posizione di reindirizzamento. In questo modo non si perde le informazioni per esempio dopo un hashtag. Senza l'intercettore risposta si perde l'hashtag. Esempio: 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";

usarla proprio come la soluzione di ZZ Coder:

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

Ho trovato questo su HttpComponents documentazione client

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
HttpGet httpget = new HttpGet("http://localhost:8080/");
CloseableHttpResponse response = httpclient.execute(httpget, context);
try {
    HttpHost target = context.getTargetHost();
    List<URI> redirectLocations = context.getRedirectLocations();
    URI location = URIUtils.resolve(httpget.getURI(), target, redirectLocations);
    System.out.println("Final HTTP location: " + location.toASCIIString());
    // Expected to be an absolute URI
} finally {
    response.close();
}

Credo modo più semplice per trovare ultimo URL è quello di utilizzare 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;
    }

}

Il codice per utilizzare questo gestore:

  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();
  }

Nella versione 2.3 di Android ancora non supportano seguente reindirizzamento (codice HTTP 302). Ho appena letto posizione di intestazione e scaricare di nuovo:

if (statusCode != HttpStatus.SC_OK) {
    Header[] headers = response.getHeaders("Location");

    if (headers != null && headers.length != 0) {
        String newUrl = headers[headers.length - 1].getValue();
        // call again the same downloading method with new URL
        return downloadBitmap(newUrl);
    } else {
        return null;
    }
}

No circolare reindirizza protezione qui quindi fate attenzione. Altro su dal blog Seguire 302 reindirizzamenti con AndroidHttpClient

Questo è come sono riuscito a ottenere l'URL di reindirizzamento:

Header[] arr = httpResponse.getHeaders("Location");
for (Header head : arr){
    String whatever = arr.getValue();
}

In alternativa, se si è certi che ci sia solo un luogo di reindirizzamento, fare questo:

httpResponse.getFirstHeader("Location").getValue();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top