【问题标题】:Java HttpURLConnection request throwing IOException with Invalid Http responseJava HttpURLConnection 请求抛出带有无效 Http 响应的 IOException
【发布时间】:2017-02-03 11:48:06
【问题描述】:

我正在使用 Java 8 发出 POST 请求,如下所示:

URL url = new URL("http://target.server.com/doIt");
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;

byte[] soapBytes = soapRequest.getBytes();
httpConn.setRequestProperty("Host", "target.host.com");
httpConn.setRequestProperty("Content-Length", soapBytes.length+"");
httpConn.setRequestProperty("Content-Type", "application/soap+xml; charset=utf-8");
httpConn.setRequestMethod("POST");
httpConn.setConnectTimeout(5000);
httpConn.setReadTimeout(35000);
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
OutputStream out = httpConn.getOutputStream();
out.write(soapBytes);
out.close();

int statusCode;
try {
    statusCode = httpConn.getResponseCode();
} catch (IOException e) {
    InputStream stream = httpConn.getErrorStream();
    if (stream == null) {
        throw e;
    } else {
        // this never happens
    }
}

我的 soap 请求包含一个文档 ID,并且目标服务器(托管我不拥有或无权访问的第三方服务)返回一个与提供的 ID 匹配的 PDF 文档。

大多数时候,服务器会返回一个 PDF 文档,有时当文档不可用时,状态码是 500。但是,有时对 getResponseCode() 的调用会引发 IOException,并显示“无效的 Http 响应”。

我认为无论发生什么情况,服务器总会返回一些响应代码。

  • 这是否意味着服务器正在返回完整的垃圾 匹配 HTTP 响应的预期格式?
  • 有没有办法获得有关实际响应的更多信息?
  • 有没有办法检索原始文本响应(如果有)?

【问题讨论】:

  • 来自doc of getResponseCodeIOException:如果连接到服务器时发生错误。所以我猜想连接存在一些问题。 PS:如果代码无法识别,将返回-1
  • 但是如果是这样的话,写soap请求时不会抛出异常吗,发生在调用获取响应码之前?
  • 这似乎是 javadoc 中的一个错误。如果您打开源代码,您会看到打开输入流时可能会发生这种情况(您可以使用调试器检查是否可以轻松重现)。然后你就能明白为什么(或至少是原因)

标签: java http httpurlconnection


【解决方案1】:

正如 AxelH 指出的那样,连接远程服务器时一定有问题,在这种情况下,您无法得到有效的响应。

如果您在测试环境中,您可以监控连接在 TCP 级别(不是在 HTTP 级别):在您的客户端和远程服务器之间放置一个监控器,监控所有交换的 TCP 流量两个同行之间。如果您使用的是 Eclipse,您可以创建一个 TCP 监视器

【讨论】:

  • 不幸的是,这对我来说很难重现。我会看看服务所有者是否可以了解情况。似乎连接被拒绝了,尽管我原以为来自 IOException 的错误消息会是“连接被拒绝”。
  • @RTF 实际上,当您尝试连接到不可用的服务器时,您应该得到“连接被拒绝”异常。但是,如果连接建立后,它被远程对等方异常中止,则会引发不同的错误消息。
  • 你知道我的代码 sn-p 中与远程服务器的连接到底是什么时候建立的吗?
  • @RTF 当然:就在您调用httpConn.getOutputStream() 时,连接已隐式建立。在URLConnection 中了解这个多步骤流程。