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.
- ¿Cómo obtener un cuerpo de respuesta para la excepción de actualización?
- Confiando en todos los certificados con okHttp
- React Native & okhttp en Android - Establecer User-Agent
- OKhttp: SSLProtocolException: Protocolo de enlace SSL finalizado
- Retrofit 2 / OkHttp: Cancelar todas las solicitudes en ejecución
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.
- ¿Cómo acceder al contexto en un Interceptor?
- OkHttpClient cerrar la conexión
- Android cómo obtener la cadena de respuesta de Callback usando OkHttp?
- ¿Cómo usar Retrofit y SimpleXML juntos para descargar y analizar un archivo XML de un sitio?
- ¿Android usa OkHttp internamente?
- Set Cookie para Picasso
- Cómo resolver java.lang.AssertionError al crear OkHttpClient en mockito?
- OkHttp javax.net.ssl.SSLPeerUnverifiedException: Nombre de host domain.com no verificado
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; }
- Representación fuera de pantalla con PixelBuffer o FBO para guardar todos los gráficos en el mapa de bits (y luego en bmp / jpg) del tamaño deseado (> 4096) con OpenGL ES 2.0
- MediaCodec y PCM de 24 bits