2015-09-19 2 views
6

Я использую OkHttp с доработкой, чтобы выполнить сетевые запросы моего приложения. Я также использую Interceptors для аутентификации и, если необходимо, повторно запрашиваю запросы.Возврат ошибки из перехватчика OKHttp (с использованием модификации)

Сервер иногда имеет временные проблемы и возвращает пустое тело, хотя статус ответа 200 OK. Это приводит к сбою моего приложения, потому что вызывается блок успеха обратного вызова Retrofit, возвращенный пользовательский объект (и анализируется с помощью GSON) равен нулю, а обратный вызов с успешным кодом предполагает, что объект возвращается.

Я уже сообщал об этом команде сервера, но я также хочу исправить ее, не сворачивая весь код обратного вызова во всем приложении с нулевыми проверками.

CurrentY Я склонен к двум вариантам, хотя любые другие идеи наиболее приветствуются: 1) Не возвращаясь из перехватчика (это вообще возможно) и просто отображать сообщение об ошибке диалоговое 2) Возвращение то, что сделает Дооснащение? вызовите часть отказа в обратном вызове.

Мой код ниже. Как вы можете видеть, я повторяю запрос максимум в 3 раза, когда будет получено пустое тело.

@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??? 
    } 
} 

Большое спасибо.

+8

Почему бы не исключить исключение из перехватчика? – mastov

+3

Большое спасибо. Это было просто. Если вы опубликуете его в качестве ответа, я соглашусь с ним. :) –

+0

@mastov Если вы там указали ошибку, ваше приложение не исчезнет? Как вы обрабатываете ошибку/распространяете ее на обратный вызов? – Singed

ответ

0

Просто был такой же сценарий, и это сообщение помогло мне реализовать решение. Спасибо @mastov, чтобы указать на правильное направление.

Работа с back-end api, который всегда возвращает HTTP 200, даже если произошла ошибка. Это был мой образец ответа об ошибке

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

Вот простая реализация, дополняющая этот ответ.

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; 
    }