HttpURLConnection.getResponseCode() выдает IOException, когда код известен

Как получилось, что HttpURLConnection.getResponseCode() выбрасывает IOException, даже если статус известен?

Caused by: java.io.IOException: Server returned HTTP response code: 412 for URL: <my url>

Это не проблема получения кода ответа, поскольку он написан в сообщении об исключении.

Я бы ожидал получить код статуса (даже если он не ~ 200), не получив исключения, поэтому я смогу решить в своем коде, что делать.

Полная трассировка стека:

Caused by: java.io.IOException: Server returned HTTP response code: 412 for URL: <my url>
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1625)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
... my code

UPDATE Я изменил реализацию на стороне сервера, чтобы вернуть другой код состояния (303), и теперь он работает (не бросая исключение IOException). Это означает, что это связано с 412.

Ответ 1

ВНИМАНИЕ: это может зависеть от версии JVM, которую вы используете!!!, поскольку тесты @SotiriosDelimanolis дали разные результаты

Ответ находится в исходном коде HttpURLConnection и связан со всеми ошибками с кодом ошибки > 400

Если код ошибки равен 404 или 410, значение FileNotFoundException выбрано иначе IOException как

    if (respCode >= 400) {
        if (respCode == 404 || respCode == 410) {
            throw new FileNotFoundException(url.toString());
        } else {
            throw new java.io.IOException("Server returned HTTP" +
              " response code: " + respCode + " for URL: " +
              url.toString());
        }
    }

sun.net.www.protocol.http.HttpURLConnection Исходный код в строке 1625:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/protocol/http/HttpURLConnection.java#HttpURLConnection

Мой тест на http://media.jarnbjo.de/412.php, используя:

Java (TM) SE Runtime Environment (сборка 1.7.0_21-b11) Java HotSpot (TM) 64-разрядная серверная VM (сборка 23.21-b01, смешанный режим)

в Windows 64 бит

enter image description here

Ответ 2

Я столкнулся с той же проблемой сегодня на работе - наш код вызывал HttpURLConnection.getResponseCode() и заканчивался Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL:... - и через некоторое время качества Окунувшись в исходный код JDK, я понял следующее:

  • getResponseCode() самом деле не вызывает исключение!
  • Исключение getResponseCode() изнутри getResponseCode(), но оно перехватывается.
    • До того, как он перехватил, в HttpURLConnection устанавливаются некоторые поля, которые позволяют getResponseCode() успешно, что и происходит.
    • Также до того, как оно было перехвачено, исключение сохраняется в поле в подклассе HttpURLConnection (в частности: sun.net.www.protocol.http.HttpURLConnection.rememberedException).
  • Впоследствии наш код вызвал getInputStream() напрямую, что в данном случае должно вызвать исключение. (getErrorStream() этого вы должны вызывать getErrorStream().)
  • getInputStream() генерирует исключение, которое оборачивает исходное выброшенное и перехваченное исключение.
  • Таким образом, в итоге мы получили трассировку стека с параметром Caused by который ссылался на нашу строку кода, где мы Caused by getResponseCode(), хотя наша настоящая проблема была позже, в нашей строке кода, где мы getInputStream() напрямую.
    • В трассировке стека также упоминается более поздняя строка кода, но сначала я этого не заметил.

Могу поспорить, что ваш случай был таким же.