在Java中检索一个给定URL的最终位置。

问题描述 投票:5回答:5

我正试图按如下方式检索一个给定URL(String ref)的最终位置。

        HttpURLConnection con = (HttpURLConnection)new URL(ref).openConnection();
        con.setInstanceFollowRedirects(true);
        con.setRequestProperty("User-Agent","");
        int responseCode = con.getResponseCode();
        return con.getURL().toString();

它在大多数情况下都能工作,但很少返回一个包含另一个重定向的URL。

我在这里做错了什么?

为什么在调用setInstanceFollowRedirects(true)之后,我仍然得到responseCode = 3xx?

UPDATE:

OK, responseCode有时会是3xx.

如果发生这种情况,那么我将返回con.getHeaderField("Location")代替。

现在的代码是。

        HttpURLConnection con = (HttpURLConnection)new URL(ref).openConnection();
        con.setInstanceFollowRedirects(true);
        con.setRequestProperty("User-Agent","");
        int responseType = con.getResponseCode()/100;
        while (responseType == 1)
        {
            Thread.sleep(10);
            responseType = con.getResponseCode()/100;
        }
        if (responseType == 3)
            return con.getHeaderField("Location");
        return con.getURL().toString();

如果有人发现上面的代码有什么不对的地方,欢迎评论。

更新

  • 删除了对代码1xx的处理,因为根据大多数评论者的意见,它是不必要的。
  • 在返回Location头之前测试它是否存在,以便处理代码304。

        HttpURLConnection con = (HttpURLConnection)new URL(ref).openConnection();
        con.setInstanceFollowRedirects(true);
        con.setRequestProperty("User-Agent","");
        if (con.getResponseCode()/100 == 3)
        {
            String target = con.getHeaderField("Location");
            if (target != null)
                return target;
        }
        return con.getURL().toString();
    
java httpurlconnection url-redirection
5个回答
3
投票

如果协议发生变化,比如http到https或者https到http,HttpURLConnection将不遵循重定向。在这种情况下,它将返回3xx代码,你应该能够得到Location头。你可能需要再次打开一个连接,以防那个新的url也重定向。所以基本上,使用一个循环,当你得到一个非重定向的响应代码时,就把它打断。另外,注意无限重定向循环,你可以设置一个迭代次数的限制,或者检查每个新的url是否已经被访问过。


1
投票

如果你只是想要重定向的url,响应头应该会给你。

if (con.getResponseCode() == 301) {
    String redirectUrl = con.getHeaderField("Location");
}

1
投票

可能很容易有多个层次的重定向 - 想象一下,一个bit.ly指向一个youtu.be地址指向youtube.com。也许你需要循环,直到你得到你的200个OK或直到你打一个重定向周期。

我很难找到源码来检查,但我相信我说的是真的。参见例如 java urlconnection 获取最终的重定向URL。

你也可能需要处理协议重定向,例如HTTP -> HTTPS。URLConnection不遵循重定向


0
投票

我想我现在明白你想要什么了。我现在认为,你是想检索最终地址,而不是最终地址的内容。如果我的假设是错误的,请纠正我。

要做到这一点(不是内容,而是地址),你需要一个不同的方法。你需要关闭follow-redirects,然后你需要自己处理迭代重定向-following,直到你找到一个非重定向的响应。请记住,你不能重复使用一个新的地址。URLConnection.

寻找最终地址的方法和检索最终地址内容的另一种方法是如此不同,因为。URLConnection 是否 如果你开启了follow-redirects,就会显示follow-to的地址。

在你的代码中,你似乎希望 URLConnection.getURL() 来返回 followed-to 地址。这不是这个方法的行为。它返回原来的 URL 您用来创建 URLConnection. 无论你是否开启了follow-redirects,它都会这样做。然而,如果你打开它,你将无法获得跟随到URL地址。这是因为 getHeaderField("Location"),与follow-redirects一起使用,没有意义:它返回最终重定向的重定向目标,而这个目标不应该存在,因为它是最终地址。


0
投票

有时它加载在requestURI的字段中。使用像这样的代码。

val declaredField = con.javaClass.getDeclaredField("requestURI")
declaredField.isAccessible=true
val loc = declaredField.get(con).toString()
© www.soinside.com 2019 - 2024. All rights reserved.