当前位置:  开发笔记 > 编程语言 > 正文

HttpClient 4 - 如何捕获上次重定向URL

如何解决《HttpClient4-如何捕获上次重定向URL》经验,为你挑选了5个好方法。

我有一个相当简单的HttpClient 4代码,它调用HttpGet来获取HTML输出.HTML返回脚本和图像位置全部设置为本地(例如)所以我需要调用URL使这些成为绝对()现在出现问题 - 在调用期间可能有一个或两个302重定向,因此原始URL不再反映了HTML的位置.

给定我可能(或可能没有)的所有重定向,如何获取返回内容的最新URL?

我看着HttpGet#getAllHeaders()HttpResponse#getAllHeaders()-找不到任何东西.

编辑:HttpGet#getURI()返回原始呼叫地址



1> ZZ Coder..:

这将是当前的URL,您可以通过调用获得

  HttpGet#getURI();

编辑:你没有提到你是如何进行重定向的.这对我们有用,因为我们自己处理302.

听起来像是在使用DefaultRedirectHandler.我们曾经这样做过.获取当前URL非常棘手.您需要使用自己的上下文.以下是相关的代码片段,

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

默认重定向对我们不起作用,所以我们改了但是我忘记了问题所在.


现在不推荐使用ExecutionContext,而是使用HttpCoreContext.

2> david_p..:

在HttpClient 4中,如果您正在使用LaxRedirectStrategy或者任何子类DefaultRedirectStrategy,这是推荐的方法(参见源代码DefaultRedirectStrategy):

HttpContext context = new BasicHttpContext();
HttpResult 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);
}

从HttpClient 4.3.x开始,上面的代码可以简化为:

HttpClientContext context = HttpClientContext.create();
HttpResult result = client.execute(request, handler, context);
URI finalUrl = request.getURI();
List locations = context.getRedirectLocations();
if (locations != null) {
    finalUrl = locations.get(locations.size() - 1);
}


你的答案应该收到勾选标记.这就是Apache实际上的意图!很好!

3> Atharva..:
    HttpGet httpGet = new HttpHead("");
    HttpClient httpClient = HttpClients.createDefault();
    HttpClientContext context = HttpClientContext.create();
    httpClient.execute(httpGet, context);
    List 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);
    }



4> Michael Poll..:

基于ZZ Coder解决方案的IMHO改进方法是使用ResponseInterceptor简单地跟踪最后的重定向位置.这样你就不会丢失信息,例如在标签之后.如果没有响应拦截器,则会丢失主题标签.示例: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";

像ZZ Coder的解决方案一样使用它:

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



5> AmirHossein..:

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

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有