我正试图按如下方式检索一个给定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();
如果有人发现上面的代码有什么不对的地方,欢迎评论。
更新
在返回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();
如果协议发生变化,比如http到https或者https到http,HttpURLConnection将不遵循重定向。在这种情况下,它将返回3xx代码,你应该能够得到Location头。你可能需要再次打开一个连接,以防那个新的url也重定向。所以基本上,使用一个循环,当你得到一个非重定向的响应代码时,就把它打断。另外,注意无限重定向循环,你可以设置一个迭代次数的限制,或者检查每个新的url是否已经被访问过。
如果你只是想要重定向的url,响应头应该会给你。
if (con.getResponseCode() == 301) {
String redirectUrl = con.getHeaderField("Location");
}
可能很容易有多个层次的重定向 - 想象一下,一个bit.ly指向一个youtu.be地址指向youtube.com。也许你需要循环,直到你得到你的200个OK或直到你打一个重定向周期。
我很难找到源码来检查,但我相信我说的是真的。参见例如 java urlconnection 获取最终的重定向URL。
你也可能需要处理协议重定向,例如HTTP -> HTTPS。URLConnection不遵循重定向
我想我现在明白你想要什么了。我现在认为,你是想检索最终地址,而不是最终地址的内容。如果我的假设是错误的,请纠正我。
要做到这一点(不是内容,而是地址),你需要一个不同的方法。你需要关闭follow-redirects,然后你需要自己处理迭代重定向-following,直到你找到一个非重定向的响应。请记住,你不能重复使用一个新的地址。URLConnection
.
寻找最终地址的方法和检索最终地址内容的另一种方法是如此不同,因为。URLConnection
是否 不 如果你开启了follow-redirects,就会显示follow-to的地址。
在你的代码中,你似乎希望 URLConnection.getURL()
来返回 followed-to 地址。这不是这个方法的行为。它返回原来的 URL
您用来创建 URLConnection
. 无论你是否开启了follow-redirects,它都会这样做。然而,如果你打开它,你将无法获得跟随到URL地址。这是因为 getHeaderField("Location")
,与follow-redirects一起使用,没有意义:它返回最终重定向的重定向目标,而这个目标不应该存在,因为它是最终地址。
有时它加载在requestURI的字段中。使用像这样的代码。
val declaredField = con.javaClass.getDeclaredField("requestURI")
declaredField.isAccessible=true
val loc = declaredField.get(con).toString()