Devolución de error de OKHttp interceptor (utilizando retrofit)

Estoy usando OkHttp con Retrofit para hacer las solicitudes de red de mi aplicación. También estoy usando interceptores para la autenticación y reintentar las solicitudes si es necesario.

El servidor a veces tiene problemas temporales y devuelve un cuerpo vacío aunque el estado de respuesta es 200 OK. Esto hace que mi aplicación se bloquee, porque se llama al bloque de éxito de Retrofit Callback, el objeto personalizado devuelto (y analizado con GSON) es nulo y el código en devolución de llamada de éxito asume que se devuelve un objeto.

Ya he informado esto al equipo del servidor, pero quiero arreglarlo también, sin tener que envolver todo el código de devolución de llamadas de éxito en toda la aplicación con comprobaciones nulas.

Currenty Estoy inclinado a dos opciones, aunque cualquier otra idea son bienvenidos: 1) No volver del interceptor (es esto posible?) Y sólo mostrar un diálogo de error 2) Devolver algo que hará retrofit llamar a la parte de falla de la llamar de vuelta.

Mi código está abajo. Como puede ver, vuelvo a intentar la solicitud por un máximo de 3 veces cuando se recibe un cuerpo vacío.

@Override public Response intercept(Chain chain) throws IOException { // First Request request = chain.request(); Response response = chain.proceed(request); .... .... .... // Retry empty body response requests for a maximum of 3 times Integer retryMaxCount = 3; MediaType contentType = response.body().contentType(); String bodyString = response.body().string(); while (bodyString.length() == 0 && retryMaxCount > 0) { //Empty body received!, Retrying... retryMaxCount--; response = chain.proceed(request); bodyString = response.body().string(); } if (bodyString.length() != 0) { // Create and return new response because it was consumed ResponseBody newResponseBody = ResponseBody.create(contentType, bodyString); return response.newBuilder().body(newResponseBody).build(); } else { // WHAT TO WRITE HERE??? } } 

Muchas gracias.

Sólo tenía el mismo escenario y este post me ayudó a implementar la solución. Gracias a @mastov para apuntar a la dirección correcta.

Trabajar con un api de back-end que siempre devuelve HTTP 200 incluso si hubo un error. Esta fue mi muestra de respuesta de un error

 {"status":403,"message":"Bad User credentials","time":1495597740061,"version":"1.0"} 

Esta es una implementación sencilla para complementar esta respuesta.

 public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); ResponseBody body = response.body(); // Only intercept JSON type responses and ignore the rest. if (body != null && body.contentType() != null && body.contentType().subtype() != null && body.contentType().subtype().toLowerCase().equals("json")) { String errorMessage = ""; int errorCode = 200; // Assume default OK try { BufferedSource source = body.source(); source.request(Long.MAX_VALUE); // Buffer the entire body. Buffer buffer = source.buffer(); Charset charset = body.contentType().charset(Charset.forName("UTF-8")); // Clone the existing buffer is they can only read once so we still want to pass the original one to the chain. String json = buffer.clone().readString(charset); JsonElement obj = new JsonParser().parse(json); // Capture error code an message. if (obj instanceof JsonObject && ((JsonObject) obj).has("status")) { errorCode = ((JsonObject) obj).get("status").getAsInt(); } if (obj instanceof JsonObject && ((JsonObject) obj).has("message")) { errorMessage= ((JsonObject) obj).get("message").getAsString(); } } catch (Exception e) { Log.e(TAG, "Error: " + e.getMessage()); } // Check if status has an error code then throw and exception so retrofit can trigger the onFailure callback method. // Anything above 400 is treated as a server error. if(errorCode > 399){ throw new Exception("Server error code: " + errorCode + " with error message: " + errorMessage); } } return response; } 
  • OkHttp cuerpo del poste del gzip
  • Cómo agregar matriz a okhttp cuerpo (POST)
  • Petición POST de Retrofit con la autenticación HTTP básica: "No se puede reintentar el cuerpo HTTP transmitido"
  • OkHTTP Actualiza la interfaz de usuario desde la devolución de llamada en cola
  • Retrofit 2.0 java.lang.IllegalStateException: Se esperaba BEGIN_ARRAY pero era STRING
  • Ninguna excepción de clase encontrada com.squareup.okhttp.logging.HttpLoggingInterceptor
  • Causado por: java.lang.NoClassDefFoundError: Clase no encontrada usando el cargador de clase de arranque; No hay rastro de la pila disponible
  • Cómo obtener el cuerpo de la respuesta en okhttp cuando el código es 401
  • NoSuchMethodError si estoy usando okhttp 2.0 y la última actualización?
  • Http sesión siempre se crea en la versión Android ModernHttpClient (okHttp1.5)
  • Android OkHttp cómo manejar ETag
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.