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

我试图检索给定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(); 

如果有人看到上面的代码有任何问题,请欣赏评论。

UPDATE

  • 删除了代码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(); 

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

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

我无法找到要检查的源代码,但我相信我说的是真的。 请参阅例如java urlconnection获取最终重定向的URL

您还可能需要处理协议重定向,例如HTTP – > HTTPS: URLConnection不遵循重定向

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

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

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

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

查找最终地址的方法和检索最终地址内容的另一种方法是如此不同,因为如果您打开后续重定向, URLConnection不会显示后续地址。

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