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

时间:2016-09-20 12:08:06

标签: servlets httpsurlconnection

我正在使用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);

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

提前致谢! :)

1 个答案:

答案 0 :(得分:0)

简短版本:OpenJDK和其他人有一个parseHttpHeader方法,它正好解析HTTP状态代码编号的三个字符,以及以字符串' 100'开头的任何内容。被视为HTTP继续。这个servlet对话的非持续性质使客户端感到困惑,因此它无法打开输出流并放弃。

WAAAAY长版:

这有点让我感到烦恼,因为只有100-599(ish,实际上比这个还少)的状态代码应该真正起作用。 RFC2616表示代码必须是三位数并且(释义)您只需要理解第一个数字的类(以允许扩展)。

OpenJDK 6'} HttpURLConnection实施是我检查的第一个(因为你没有指定),代码基本上是这样做的:

  • 抓住回复的第一行。
  • 寻找HTTP / 1。 (显然不关心0.9,忽略第二位)。
  • 因文字原因找到最后的一切。
  • 尝试解析中间的任何int。

GNU Classpath几乎完全相同。

值得注意的是,OpenJDK并没有特别审查RFC规则。你可以在那里投入十亿美元而且它或多或少都可以(至少就像getResponseCode()关心一样......无论如何......看起来getInputStream()将对任何代码进行barf> = 400 in sun.net.www.protocol中的具体实现......)。

无论如何,这并没有回答为什么你只看到这个奇怪的行为只有100倍。 OpenJDK看起来应该抛出表单的IOException"服务器返回HTTP 1234 ...

......左右我想。 HttpURLConnection是抽象的,因此具体实现必须至少覆盖抽象方法。好吧,concrete implementation of HttpURLConnection,抽象的getResponseCode()版本被排除了。均田。该实现调用sun.net.www.http.HttpClient的parseHTTP作为打开输入流的一部分,该输出流解析出HTTP / 1。然后恰好是代码中的三个字符(然后进行复杂的事情来按摩输入流,将所有那些东西追溯到一个叫做HttpCapture的东西。哎呀。)。如果这三个字符发生在come out to 100,那么客户端认为它必须继续对话以获得有效的InputStream。

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

我认为这个神秘的问题已经解决了。你可以把几乎任何东西都放在" 100"并获得相同的行为(即使" 100xyz"如果你的servlet API允许你)。

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

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

希望能回答你的问题!