httppost example ejemplo java apache-httpclient-4.x

java - example - HttpClient 4-cómo capturar la última URL de redireccionamiento



httppost java (8)

Así es como logré obtener la URL de redireccionamiento:

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

O, si está seguro de que solo hay una ubicación de redireccionamiento, haga lo siguiente:

httpResponse.getFirstHeader("Location").getValue();

Tengo un código HttpClient 4 bastante simple que llama a HttpGet para obtener resultados HTML. El HTML regresa con los scripts y las ubicaciones de las imágenes, todas configuradas como locales (por ejemplo, <img src="/images/foo.jpg"/> ), así que necesito llamar a la URL para convertirlas en absolutas ( <img src="http://foo.com/images/foo.jpg"/> ) Ahora surge el problema: durante la llamada puede haber uno o dos redireccionamientos 302, por lo que la URL original ya no refleja la ubicación del HTML.

¿Cómo obtengo la última URL del contenido devuelto dado todos los redireccionamientos que puedo (o no puedo) tener?

Miré HttpGet#getAllHeaders() y HttpResponse#getAllHeaders() - no pude encontrar nada.

Editado: HttpGet#getURI() devuelve la dirección de llamada original


Creo que la forma más fácil de encontrar la última URL es usar 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; } }

Código para utilizar este controlador:

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


En HttpClient 4, si está utilizando LaxRedirectStrategy o cualquier subclase de DefaultRedirectStrategy , esta es la forma recomendada (consulte el código fuente de 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); }

Desde HttpClient 4.3.x, el código anterior se puede simplificar como:

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


En la versión 2.3, Android aún no admite la siguiente redirección (código HTTP 302). Acabo de leer el encabezado de la ubicación y descargar de nuevo:

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

Aquí no hay protecciones circulares, así que ten cuidado. Más información en el blog Siga 302 redirecciones con AndroidHttpClient


Encontré esto en la documentación del cliente HttpComponents

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


Esa sería la URL actual, que puede obtener llamando

HttpGet#getURI();

EDIT: No mencionaste cómo estás redirigiendo. Eso nos funciona porque nosotros nos encargamos del 302.

Parece que está utilizando DefaultRedirectHandler. Solíamos hacer eso. Es un poco difícil obtener la URL actual. Necesitas usar tu propio contexto. Aquí están los fragmentos de código relevantes,

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 redirección predeterminada no funcionó para nosotros, así que cambiamos, pero olvidé cuál era el problema.


Una forma mejorada IMHO basada en la solución de ZZ Coder es usar un ResponseInterceptor para simplemente rastrear la última ubicación de redireccionamiento. De esa manera no perderá información, por ejemplo, después de un hashtag. Sin el interceptor de respuesta pierdes el hashtag. Ejemplo: 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";

Úsalo como la solución de ZZ Coder:

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


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