2016-09-20 12 views
1

Я использую вызов HttpsURLConnection, чтобы получить ответ от HTTP-сервлета с сообщением и кодом ошибки. Ниже некоторые фрагмент кода из моего кода: -HttpsURLConnection.getResponseCode() возвращает -1 вместо 1001 или 1002 или 1003

 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 стороны, я ставлю StatusCode и описание: -

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

Все выше код существующий код и он работает отлично, за исключением. Он должен вернуть код состояния в качестве кода ответа. Но несколько кодов не работают как 1001 1002 или 1003. Если я установил response.setStatus (1001), он возвращает -1 в качестве responseCode() на стороне клиента с помощью «java.io.IOException: Invalid Http response». Для любого другого целочисленного значения, такого как 1101,1102, 1232 и т. Д., Он отлично работает. Я отлаживал код и обнаружил, что сервлет устанавливает правильные значения, но клиент не может разобрать ответ. И когда вы меняете код состояния с некоторым другим числовым значением, он начинает работать правильно! Я получаю такое же поведение как в HTTP, так и в HTTPS. Кажется, что эти неработающие коды являются предопределенными кодами с определенной целью и не могут использоваться в качестве кода состояния, но я ничего не нашел в Интернете. Кто-нибудь испытал то же самое и что могло быть причиной.

Заранее благодарен! :)

ответ

0

Краткая версия: OpenJDK и другие имеют метод parseHttpHeader, который анализирует ровно три символа номера кода состояния HTTP, и все, начиная с строки «100», рассматривается как продолжение HTTP. Непрерывный характер этой беседы с сервлетом путал клиента, поэтому он не мог открыть выходной поток и сдался.

WAAAAY длинная версия:

Это один своего рода прослушивают меня, потому что только 100-599 (МОГ, на самом деле меньше, чем это) коды состояния должны реально работать. RFC2616 говорит, что коды должны быть три цифры и (перефразирование), вам обязательно нужно понять только класс первой цифры (чтобы разрешить расширения). HttpURLConnection реализация

OpenJDK 6 был первым я проверил (так как вы не указали) и код в основном делает:

  • захватить первую линию ответа.
  • искать HTTP/1. (Не волнует, по-видимому, 0,9 и игнорирует вторую цифру).
  • Ищите все в конце по причине текста.
  • попытайтесь разобрать все, что находится в середине.

GNU Classpath делает практически то же самое.

Примечательно, что OpenJDK особо не проверяет это против правил RFC. Вы могли бы добавить туда миллиард, и это было бы более или менее нормально с этим (по крайней мере, насколько это касается getResponseCode(), в любом случае ... похоже, что getInputStream() будет barf на любом коде> = 400 в конкретная реализация в sun.net.www.protocol ...).

В любом случае, это не ответило на то, почему вы видели это странное поведение всего за 100 раз. OpenJDK выглядит так, как будто он должен был выбрасывать IOException формы «Сервер вернулся HTTP 1234 ...

... или так я думал. HttpURLConnection является абстрактным, поэтому конкретная реализация должна переопределять, по крайней мере, абстрактные методы.Ну, concrete implementation of HttpURLConnection, абстрактная версия getResponseCode() проигнорирована sorta. Вроде. Эта реализация вызывает parseHTTP sun.net.www.http.HttpClient как часть открытия входного потока, который анализирует HTTP/1. а затем ровно три символа кода (а затем запутанные вещи, чтобы массировать входной поток, чтобы все эти вещи ретроактивно отбрасывались обратно во что-то, называемое HttpCapture. Yuck.). И если эти три символа происходят с come out to 100, тогда клиент считает, что он должен продолжить разговор, чтобы получить рабочий InputStream.

Поскольку ваш сервлет фактически выполнен с транзакцией уже и не продолжается, клиент смущается о WTF, который делает ваш сервлет, и поэтому возвращает ошибку (как это должно быть в RFC).

Так что тайна решена, я думаю. Вы можете добавить почти все, начиная с «100» и получить такое же поведение (даже «100xyz», если ваш API сервлета позволит вам).

(Android, кстати, и делает это три-обугленный разобрана.)

Это все технически нарушает RFC (хотя, если честно, это своего рода глупых ошибок). Строго говоря, только коды 2xx должны рассматриваться как полностью ОК, чтобы пройти без проблем, но, вероятно, вы могли бы использовать статус «000» и пройти «ОК» (опять же, если ваш API позволяет вам помещать в него произвольную строку).

Надеюсь, что ответит на ваш вопрос!

+0

спасибо @BJ Черный. Это отвечает на мой вопрос. Я должен был проанализировать больше. –

+0

Я бы не стал слишком сильно потеть. Я был программистом на Java очень долго, и это ни в коем случае не было очевидным. –