HttpURLConnection.getResponseCode () zwraca -1 przy drugim wywołaniu
Wydaje mi się, że na Androidzie 1.5 napotkałem osobliwy problem, gdy używana przeze mnie biblioteka (signpost 1.1-SNAPSHOT) wykonuje dwa kolejne połączenia ze zdalnym serwerem. Drugie połączenie zawsze zawodzi z HttpURLConnection.getResponseCode()
z -1
Oto Test, który ujawnia problem:
// BROKEN
public void testDefaultOAuthConsumerAndroidBug() throws Exception {
for (int i = 0; i < 2; ++i) {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.tripit.com/oauth/request_token").openConnection();
final DefaultOAuthConsumer consumer = new DefaultOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
consumer.sign(c); // This line...
final InputStream is = 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);
}
}
Zasadniczo, jeśli podpiszę żądanie, a następnie pochłonie cały strumień wejściowy, następne żądanie zakończy się niepowodzeniem z kodem wyniku -1. Niepowodzenie nie wydaje się mieć miejsca, jeśli przeczytam tylko jedną postać ze strumienia wejściowego.
Zauważ, że nie dotyczy to żadnego adresu url - tylko konkretnych adresów URL, takich jak powyższy.
Również, jeśli przełączę się na HttpClient zamiast HttpURLConnection, wszystko działa dobrze:
// WORKS
public void testCommonsHttpOAuthConsumerAndroidBug() throws Exception {
for (int i = 0; i < 2; ++i) {
final HttpGet c = new HttpGet("https://api.tripit.com/oauth/request_token");
final CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
consumer.sign(c);
final HttpResponse response = new DefaultHttpClient().execute(c);
final InputStream is = response.getEntity().getContent();
while( is.read() >= 0 ) ;
assertTrue( response.getStatusLine().getStatusCode() == 200);
}
}
Znalazłem odniesienia do tego, co wydaje się być podobnym problemem gdzie indziej, ale na razie nie ma rozwiązań. Jeśli są one naprawdę ten sam problem, to prawdopodobnie problem nie jest z drogowskazem, ponieważ inne odniesienia nie odnoszą się do niego.
Any pomysły?
5 answers
Spróbuj ustawić tę właściwość, aby sprawdzić, czy to pomaga,
http.keepAlive=false
Widziałem podobne problemy, gdy odpowiedź serwera nie jest rozumiana przez UrlConnection i klient / serwer jest z synchronizacji.
Jeśli to rozwiąże twój problem, musisz uzyskać ślad HTTP, aby zobaczyć dokładnie, co jest specjalnego w odpowiedzi.
EDIT: ta zmiana tylko potwierdza moje podejrzenia. To nie rozwiąże Twojego problemu. To tylko ukrywa objaw.
Jeśli odpowiedź z pierwszego żądania wynosi 200, potrzebujemy namierzenia. I normalnie użyj Ethereal / Wireshark, aby uzyskać ślad TCP.
Jeśli twoja pierwsza odpowiedź nie jest 200, widzę problem w Twoim kodzie. W przypadku OAuth odpowiedź na Błąd (401) rzeczywiście zwraca dane, które zawierają ProblemAdvice, Signature Base String itp., aby pomóc w debugowaniu. Musisz przeczytać wszystko ze strumienia błędów. W przeciwnym razie, to będzie mylić następne połączenie i to jest przyczyną -1. Poniższy przykład pokazuje, jak poprawnie obsługiwać błędy,
public static String get(String url) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
URLConnection conn=null;
byte[] buf = new byte[4096];
try {
URL a = new URL(url);
conn = a.openConnection();
InputStream is = conn.getInputStream();
int ret = 0;
while ((ret = is.read(buf)) > 0) {
os.write(buf, 0, ret);
}
// close the inputstream
is.close();
return new String(os.toByteArray());
} catch (IOException e) {
try {
int respCode = ((HttpURLConnection)conn).getResponseCode();
InputStream es = ((HttpURLConnection)conn).getErrorStream();
int ret = 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 + ": " +
new String(os.toByteArray());
} catch(IOException ex) {
throw ex;
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 19:37:56
Napotkałem ten sam problem, gdy nie odczytałem wszystkich danych ze strumienia wejściowego przed zamknięciem go i otwarciem drugiego połączenia. Został również naprawiony albo za pomocą System.setProperty("http.keepAlive", "false");
, albo po prostu zapętlając, dopóki nie przeczytam reszty strumienia wejściowego.
Nie do końca związane z Twoim problemem, ale mam nadzieję, że pomoże to komukolwiek z podobnym problemem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-27 00:19:05
Google dostarczyło eleganckie obejście, ponieważ dzieje się to dopiero przed Froyo:
private void disableConnectionReuseIfNecessary() {
// HTTP connection reuse which was buggy pre-froyo
if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
System.setProperty("http.keepAlive", "false");
}
}
[[1]}por. http://android-developers.blogspot.ca/2011/09/androids-http-clients.html Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-27 17:32:26
Lub możesz ustawić nagłówek HTTP w połączeniu (HttpUrlConnection):
conn.setRequestProperty("Connection", "close");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-24 07:18:32
Czy możesz sprawdzić, czy połączenie nie zostanie zamknięte, zanim skończysz czytać odpowiedź? Może HttpClient przetwarza kod odpowiedzi od razu i zapisuje go dla przyszłych zapytań, jednak HttpURLConnection może zwracać -1 po zamknięciu połączenia?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-17 20:29:45