HttpsURLConnection.getResponseCode() 返回 -1 而不是 1001 或 1002 或 1003

HttpsURLConnection.getResponseCode() returning -1 instead 1001 or 1002 or 1003

我正在使用 HttpsURLConnection 调用从 HTTP servlet 获取带有消息和错误代码的响应。以下是我的代码中的一些代码片段:-

        connection = (HttpsURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            // Headers
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-type", "text/xml");
            connection.setRequestProperty("Accept", "text/plain");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Authorization", authorization);

            connection.connect();

从 HTTPServlet 端,我正在设置状态码和描述:-

response.setStatus(code);
    response.getWriter().write(returnDescription);

以上所有代码都是现有代码,并且工作正常,除了。它应该 return 状态代码作为响应代码。但是很少有代码不能像 1001,1002 或 1003 那样工作。即如果我设置 response.setStatus(1001) 它 returns -1 作为客户端的 responseCode() "java.io.IOException: Invalid Http response"。对于任何其他整数值,如 1101、1102、1232 等,它都可以正常工作。我调试了代码,发现 servlet 设置了正确的值,但客户端无法解析响应。当您用其他数值更改状态代码时,它会开始正常工作!我在 HTTP 和 HTTPS 中得到相同的行为。 这些非工作代码似乎是具有特定 objective 的预定义代码,不能用作状态代码,但我没有在网上找到任何东西。有没有人有同样的经历,可能是什么原因。

提前致谢! :)

简短版本:OpenJDK 和其他人有一个 parseHttpHeader 方法,可以准确解析 HTTP 状态代码编号的三个字符,任何以字符串“100”开头的内容都被视为 HTTP 继续。此 servlet 会话的非连续性使客户端感到困惑,因此无法打开输出流并放弃。

WAAAAY 长版:

这有点让我烦恼,因为只有 100-599(大概,实际上少于这个)状态码才真正有效。 RFC2616 说代码必须是三位数字,并且(换句话说)您只需要了解第一位数字的 class(以允许扩展)。

OpenJDK 6 的 HttpURLConnection 实现是我检查的第一个(因为你没有指定)并且代码基本上是:

  • 抓取响应的第一行。
  • 寻找HTTP/1。 (显然不关心 0.9,并忽略第二个数字)。
  • 由于文本原因,请查找末尾的所有内容。
  • 尝试解析中间的任何 int。

GNU 类路径的作用几乎相同。

值得注意的是,OpenJDK 并未特别针对 RFC 规则进行审查。你可以把十亿放在那里,它或多或少都可以(至少就 getResponseCode() 关心而言,无论如何……看起来 getInputStream() 会在任何 >=400 的代码上呕吐具体实现在sun.net.www.protocol...).

无论如何,这并没有回答为什么您只看到 100 倍的这种古怪行为。 OpenJDK 看起来应该抛出形式为“服务器返回 HTTP 1234...

的 IOException

……我是这么想的。 HttpURLConnection 是抽象的,因此具体的实现必须至少覆盖抽象方法。好吧,concrete implementation of HttpURLConnection, the abstract's version of getResponseCode() is sorta ignored. Kinda. This implementation calls sun.net.www.http.HttpClient's parseHTTP as part of opening the input stream, which parses out the HTTP/1. and then exactly THREE characters of the code (and then does convoluted things to massage the input stream to having all that stuff retroactively shoved back in in something called an HttpCapture. Yuck.). And if that three chars happens to come out to 100,然后客户端认为它必须继续对话才能获得有效的 InputStream。

由于您的 servlet 实际上已经完成了事务并且没有继续,客户端对您的 servlet 正在执行的 WTF 感到困惑,因此返回错误(根据 RFC 应该如此)。

我想谜团已经解开了。您几乎可以放置任何以“100”开头的内容并获得相同的行为(如果您的 servlet API 允许,甚至是“100xyz”)。

(Android, 顺便说一句,也做这个三字符解析。)

这在技术上都违反了 RFC(尽管老实说,这是一个愚蠢的错误)。严格来说,只有 2xx 代码应该被视为完全可以不受干扰地通过,但您可能可以使用“000”状态并通过 OK(同样,假设您的 API 允许您在其中放置任意字符串)。

希望这能回答您的问题!