HttpURLConnection.getResponseCode () devuelve -1 en segunda invocación
Parece que me encuentro con un problema peculiar en Android 1.5 cuando una biblioteca que estoy usando (signpost 1.1-SNAPSHOT), hace dos conexiones consecutivas a un servidor remoto. La segunda conexión siempre falla con un HttpURLConnection.getResponseCode()
de -1
He aquí un testcase que expone el problema:
- ¿Por qué no puedo crear varios ID de cliente de OAuth 2.0 para el mismo nombre de paquete?
- ¿Cómo implementar correctamente el inicio de sesión linkedIn?
- ¿Cómo verificar correctamente la integridad de un token de Google?
- Buscando un ejemplo de trabajo (proyecto completo) para OAuth 2.0 Acceso a gmail
- "Http: // {root_dir} / oauth / token" Archivo no encontrado en Magento para registrar la aplicación REST API
// 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); } }
Básicamente, si firmo la solicitud y después consume toda la secuencia de entrada, la siguiente solicitud fallará con un resultado de -1. El fallo no parece ocurrir si acabo de leer un carácter del flujo de entrada.
Tenga en cuenta que esto no sucede para cualquier url – sólo urls específicos como el de arriba.
Además, si cambio a usar HttpClient en lugar de HttpURLConnection, todo funciona bien:
// 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); } }
He encontrado referencias a lo que parece ser un problema similar en otros lugares, pero hasta ahora no hay soluciones. Si son verdaderamente el mismo problema, entonces el problema probablemente no está con la señal puesto que las otras referencias no hacen ninguna referencia a él.
¿Algunas ideas?
- RedDit oAuth 2 para Android aplicación "sin usuario" con Retrofit
- ¿Existe ya una biblioteca OAuth2 para Java / Android?
- Inicia sesión de Google en la aplicación de Android para consumir Cloud Endpoints backend
- Problema con OAuth, Twitter y Android: falla en la comunicación http con el servidor
- ¿Es OAuth en un teléfono móvil usando un servidor proxy demasiado problema?
- Android Oauth Exception con el transporte SMTP se conectan, con Android versión 2.3
- ¿Cómo uso OAuth 2.0 para enviar Gmail desde Indy?
- ¿Cuáles son los riesgos de exponer la clave no tan secreta? ¿Hay alguna solución?
Intente establecer esta propiedad para ver si ayuda,
http.keepAlive=false
Vi problemas similares cuando la respuesta del servidor no es entendida por UrlConnection y cliente / servidor se descompone.
Si esto soluciona su problema, tiene que obtener una traza HTTP para ver exactamente lo que es especial acerca de la respuesta.
EDIT: Este cambio confirma mi sospecha. No soluciona tu problema. Sólo esconde el síntoma.
Si la respuesta de la primera solicitud es 200, necesitamos un rastro. Normalmente uso Ethereal / Wireshark para obtener el rastreo TCP.
Si su primera respuesta no es 200, veo un problema en su código. Con OAuth, la respuesta de error (401) en realidad devuelve datos, que incluye ProblemAdvice, Signature Base String etc para ayudarle a depurar. Necesita leer todo desde la secuencia de errores. De lo contrario, va a confundir la siguiente conexión y esa es la causa de -1. El ejemplo siguiente le muestra cómo manejar errores correctamente,
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; } } }
He encontrado el mismo problema cuando no leí en todos los datos del InputStream antes de cerrarlo y de abrir una segunda conexión. También se corrigió con System.setProperty("http.keepAlive", "false");
O simplemente simplemente hacer bucle hasta que he leído el resto de la InputStream.
No está completamente relacionado con tu problema, pero espero que esto ayude a alguien con un problema similar.
Google proporcionó una solución elegante ya que sólo está ocurriendo antes de 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"); } }
Cf. http://android-developers.blogspot.ca/2011/09/androids-http-clients.html
O bien, puede establecer un encabezado HTTP en la conexión (HttpUrlConnection):
conn.setRequestProperty("Connection", "close");
¿Puede verificar que la conexión no se está cerrando antes de terminar de leer la respuesta? Tal vez HttpClient analiza el código de respuesta de inmediato, y lo guarda para consultas futuras, sin embargo HttpURLConnection podría estar regresando -1 una vez que la conexión se cierra?
- ¿Qué es authorizedEntity? No se puede encontrar gcm_defaultSenderId en la propia aplicación.
- Android Studio Gradle problema de actualización a la versión 0.5.0 – Gradle de la migración de 0,8 a 0,9 – También Android Studio actualización a 0,8.1