【问题标题】:Retrieve redirected URL with Java / HttpURLConnection使用 Java / HttpURLConnection 检索重定向的 URL
【发布时间】:2014-01-15 08:22:06
【问题描述】:

给定一个 URL(字符串引用),我正在尝试检索重定向的 URL,如下所示:

        HttpURLConnection con = (HttpURLConnection)new URL(ref).openConnection();
        con.setInstanceFollowRedirects(false);
        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();

我有几个(概念和技术)问题:

概念问题:

  • 它在大多数情况下都有效,但我不太明白如何。
  • “con”实例的所有方法都在连接打开后调用(当“con”实例化时)。
  • 那么它们对实际结果有何影响?
  • 为什么调用'setInstanceFollowRedirects'会影响'getHeaderField'的返回值?
  • 在返回值不是 1xx 之前一遍又一遍地调用“getResponseCode”有什么意义吗?
  • 归根结底,我的一般问题是:每次调用这些方法之一时,是否还会通过连接发送另一个请求/响应?

技术问题:

  • 有时响应代码是 3xx,但“getHeaderField”不返回“最终”网址。
  • 我尝试使用返回值“getHeaderField”调用我的代码,直到响应代码为 2xx。
  • 但在大多数其他响应代码为 3xx 的情况下,“getHeaderField”确实会返回“最终”URL,如果我使用此 URL 调用我的代码,则会得到一个空字符串。

您能否建议如何解决上述两个问题,以便获得用于检索“最终”网址的“100% 证明”代码?

请忽略响应代码​​为 4xx 或 5xx(或除 1xx / 2xx / 3xx 之外的任何其他内容)的情况。

谢谢

【问题讨论】:

  • 您的异常处理是什么样的?也许代码悄悄地忽略了一个异常,它可以告诉你更多关于问题的可能原因。也请发布 try..catch 或 throws 部分。
  • 上面提到的都是指没有抛出异常的情况。整个代码用 try/catch 正确封装,任何异常都返回 ""。但我对解决这个问题范围内的异常不感兴趣,因为(正如我所说)所描述的问题发生在“正常执行路径”下。

标签: java httpurlconnection http-redirect url-redirection


【解决方案1】:

概念问题

0.) 一个URLConnectionHttpURLConnection 对象可以重复使用吗?

不,您不能重复使用这样的对象。您可以使用它只获取一个 URL 的内容一次。您不能使用它来检索另一个 URL,也不能两次获取内容(在网络级别上)。

如果要获取另一个 URL 或再次获取该 URL,则必须再次调用 URL 类的 openConnection() 方法以实例化新的连接对象。

1.) URLConnection 何时真正连接?

方法名称openConnection() 具有误导性。它仅实例化连接对象。它不会在网络级别做任何事情。

网络层面的交互从这一行开始,隐式连接连接(=打开底层的TCP套接字,发送和接收数据):

int responseType = con.getResponseCode()/100;

.

或者,您可以使用HttpURLConnection.connect() 显式连接连接。

2.) setInstanceFollowRedirects 是如何工作的?

setInstanceFollowRedirects(true) 导致 URL 被一次又一次地“在后台”获取,直到出现非重定向响应。非重定向响应的响应代码由您调用 getResponseCode() 返回。

更新
是的,如果您不想自己为重定向而烦恼,这允许编写简单的代码。您可以简单地打开以跟踪重定向,然后您可以读取您被重定向到的位置的最终响应,就好像没有发生重定向一样。

【讨论】:

  • 所以你真正想说的是,我应该做与我正在做的完全相反的事情?调用 setInstanceFollowRedirects(true),然后调用 getResponseCode(),它会返回除了 3xx 之外的任何东西,然后,假设 response-code 是 2xx,简单地返回 con.getURL().toString()?
  • @barakmanos,我已经编辑了我的答案以更具体地解决您的评论。
  • 谢谢 Daniel S。因此,只要响应代码不是 1xx(假设那时它必须是 2xx),我就会返回 con.getURL().toString()。但是我仍然有返回值不是最终位置的情况。有没有机会我需要继续轮询响应代码直到它是 2xx(而不是轮询它直到它不是 1xx)?换句话说,有没有可能在一段时间内返回 3xx?
  • @barakmanos 顺便说一句,您是否收到过 1xx 响应代码?我从未见过它被使用。这是一些ajax的东西吗?你在那里写什么样的东西?如果它不是特别花哨的东西,你可能根本不需要关心 1xx 代码。
  • 我从未收到过 1xx,但我在 HTTP 标准中读到过它,最初我认为这是我的问题,所以我添加了它。我在服务器端工作,所以没有(客户端)AJAX。只是试图在网络上找到广告的着陆页。我现在正在轮询响应代码,只要它是 1 或 3。你认为它会帮助我在 100% 的情况下检索着陆页吗?
【解决方案2】:

在评估响应代码时我会更加小心。并非每个 3xx 代码都会自动成为一种重定向。例如,代码 304 仅代表“未修改”。

查看原始定义here

【讨论】:

  • 这是一个很好的观点,但我会将此作为评论,因为它确实解决了任何 OP 的问题,至少不是很清楚。
  • 我检查了 3xx 问题,只是不想用繁琐的细节“超载”我的问题。无论如何,它始终是 301 或 302,所以问题肯定出在其他地方。
  • 好吧,有时我的回答太短了。对此感到抱歉。我同意,评论形式会更合适。我的贡献特别针对这个问题:'有时响应代码是 3xx,但 'getHeaderField' 不返回“最终” URL。'
猜你喜欢
  • 2014-01-16
  • 1970-01-01
  • 2016-08-24
  • 2013-02-10
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 2018-03-28
相关资源
最近更新 更多