HttpURLConnection.getResponseCode() returns -1 on second invocation
HttpURLConnection.getResponseCode() возвращает -1 при втором вызове
Кажется, я сталкиваюсь со своеобразной проблемой на Android 1.5, когда библиотека, которую я использую (signpost 1.1-SNAPSHOT), выполняет два последовательных подключения к удаленному серверу. Второе подключение всегда завершается ошибкой с HttpURLConnection.getResponseCode() из -1
Вот тестовый пример, который раскрывает проблему:
// BROKEN publicvoidtestDefaultOAuthConsumerAndroidBug()throws Exception { for (inti=0; i < 2; ++i) { finalHttpURLConnectionc= (HttpURLConnection) newURL("https://api.tripit.com/oauth/request_token").openConnection(); finalDefaultOAuthConsumerconsumer=newDefaultOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1); consumer.sign(c); // This line... finalInputStreamis= c.getInputStream(); while( is.read() >= 0 ) ; // ... in combination with this line causes responseCode -1 for i==1 when using api.tripit.com but not mail.google.com assertTrue(c.getResponseCode() > 0); } }
В принципе, если я подпишу запрос, а затем использую весь входной поток, следующий запрос завершится ошибкой с результирующим кодом, равным -1. Похоже, что сбоя не произойдет, если я просто прочитаю один символ из входного потока.
Обратите внимание, что этого не происходит ни для какого URL-адреса - только для определенных URL-адресов, таких как приведенный выше.
Кроме того, если я переключусь на использование HttpClient вместо HttpURLConnection, все будет работать нормально:
Я нашел ссылки на то, что кажется похожей проблемой в другом месте, но пока нет решений. Если это действительно одна и та же проблема, то проблема, вероятно, не в signpost, поскольку другие ссылки на него не ссылаются.
Есть идеи?
Переведено автоматически
Ответ 1
Попробуйте установить это свойство, чтобы посмотреть, поможет ли оно,
http.keepAlive=false
Я видел похожие проблемы, когда URLConnection не понимал ответ сервера и клиент / сервер не синхронизировались.
Если это решит вашу проблему, вы должны получить HTTP-трассировку, чтобы точно увидеть, что особенного в ответе.
РЕДАКТИРОВАТЬ: Это изменение просто подтверждает мои подозрения. Это не решает вашу проблему. Оно просто скрывает симптом.
Если ответ от первого запроса равен 200, нам нужна трассировка. Обычно я использую Ethereal / Wireshark для получения трассировки TCP.
Если ваш первый ответ не равен 200, я действительно вижу проблему в вашем коде. С OAuth ответ об ошибке (401) фактически возвращает данные, которые включают ProblemAdvice, базовую строку подписи и т.д., Чтобы помочь вам в отладке. Вам нужно прочитать все из потока ошибок. В противном случае это приведет к путанице при следующем подключении, и это является причиной -1. Следующий пример показывает вам, как правильно обрабатывать ошибки,
try { URLa=newURL(url); conn = a.openConnection(); InputStreamis= conn.getInputStream(); intret=0; while ((ret = is.read(buf)) > 0) { os.write(buf, 0, ret); } // close the inputstream is.close(); returnnewString(os.toByteArray()); } catch (IOException e) { try { intrespCode= ((HttpURLConnection)conn).getResponseCode(); InputStreames= ((HttpURLConnection)conn).getErrorStream(); intret=0; // read the response body while ((ret = es.read(buf)) > 0) { os.write(buf, 0, ret); } // close the errorstream es.close(); return"Error response " + respCode + ": " + newString(os.toByteArray()); } catch(IOException ex) { throw ex; } } }
Ответ 2
Я столкнулся с той же проблемой, когда я не прочитал все данные из InputStream перед его закрытием и открытием второго подключения. Это также было исправлено либо с помощью System.setProperty("http.keepAlive", "false");, либо просто зацикливанием, пока я не прочитаю остальную часть входного потока.
Не полностью связано с вашей проблемой, но надеюсь, что это поможет кому-либо еще с подобной проблемой.
Ответ 3
Google предоставил элегантный обходной путь, поскольку это происходит только до Froyo:
privatevoiddisableConnectionReuseIfNecessary() { // HTTP connection reuse which was buggy pre-froyo if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }