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

时间:2013-12-27 19:27:59

标签: java httpurlconnection url-redirection

我正在尝试检索给定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?

更新

好的,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();
    

5 个答案:

答案 0 :(得分:3)

如果协议发生更改,HttpURLConnection将不会遵循重定向,例如http到https或https到http。在这种情况下,它将返回3xx代码,您应该能够获得Location标头。如果新网址也重定向,您可能需要再次打开连接。所以基本上,当你得到一个非重定向响应代码时,使用一个循环并打破它。另外,请注意无限重定向循环,您可以设置迭代次数的限制或检查是否已经访问过每个新的URL。

答案 1 :(得分:1)

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

我无法找到要检查的源代码,但我相信我说的是真的。参见例如java urlconnection get the final redirected URL

您还可能需要处理协议重定向,例如HTTP - > HTTPS:URLConnection Doesn't Follow Redirect

答案 2 :(得分:0)

如果您只想要重定向网址,则响应标头应该为您提供:

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

答案 3 :(得分:0)

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

为了做到这一点(不是内容,而是地址),你需要一个不同的方法。您需要关闭跟随重定向,然后您需要自己处理迭代重定向跟踪,直到找到非重定向响应。请记住,您无法重复使用URLConnection

查找最终地址的方法和检索最终地址内容的其他方法是如此不同,因为如果您切换,URLConnection 会显示后续地址关于跟随重定向。

在您的代码中,您似乎希望URLConnection.getURL()返回后续地址。这不是此方法的行为。它会返回您用于创建URL的原始URLConnection。无论你是否打开跟随重定向,它都会这样做 但是,如果将其打开,则无法获取后续URL地址。这是因为具有跟随重定向的getHeaderField("Location")没有意义:它返回最终重定向的重定向目标,该重定向不应该存在,因为它是最终地址。

答案 4 :(得分:0)

有时它正在请求URL的字段中加载。像这样的代码使用:

val declaredField = con.javaClass.getDeclaredField("requestURI")
declaredField.isAccessible=true
val loc = declaredField.get(con).toString()