Получить объект ошибки вместо HTTP 400 на Android - PullRequest
0 голосов
/ 18 марта 2020

Я использую клиент apollo на Android для использования сервисов graphql с Авторизацией.

Когда срок действия данного токена аутентификации истек, появляется ошибка: HTTP 400 вместо действительного ошибка сервера:

{
  "errors": [
    {
      "message": "Invalid token.",
      ...
    }
  ]
}

С технической точки зрения это должно выполняться onSuccess, но hasErrors вместо onFailure.

override fun onFailure(e: ApolloException) {
    //I receive the error here. 
}

override fun onResponse(response: Response<T>) {
    if (!response.hasErrors()) {
        //Success
    } else {
        //I should receive the error here...
    }
}

Это связано с customType?

Ответы [ 3 ]

0 голосов
/ 28 марта 2020

На самом деле Apollo очень похож на Retrofit, где оба используют OkHttp для обработки Response. То, как Apollo обрабатывает HTTP-ответы, следует правилам и поведению OkHttp. Согласно OkHttp Docs , функция isSuccess, которая определяет успешный обратный вызов:

Возвращает true, если код находится в [200..300], что означает, что запрос был успешно принят, понят и принят.

В Аполлоне это означает, что если код состояния НЕ находится между 200-300, он будет всегда вводить onFailure обратный вызов (в в вашем случае вы получили его из-за HTTP 400).

Единственный способ заставить код ввести обратный вызов onSuccess - перехватить исключение на стороне сервера и отправить HTTP 200 вместе с сообщением об ошибке, вместо HTTP 400. Моя команда сделала это, и это работает.

0 голосов
/ 30 марта 2020

Предисловие

Система делает то, что должна. HTTP 400 является ошибкой. Поэтому прохождение через обратные вызовы с ошибками вполне в пределах разумного.

Лучшим решением было бы устранить ошибку .

Возможно, автоматически попытаться получить новый токен доступа с вашим рефре sh токеном. Если это не удается, попросите пользователя снова войти в систему с помощью единого входа.

Потенциальное решение

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

Я не проверял следующее, но он должен делать то, что вы хотите.

Перехватчик выполняет вызов. Проверяет код результата звонка. Если этот вызов равен 400, то мы генерируем новый ответ на основе предыдущего ответа. Этот новый ответ изменяется для отправки успешного кода результата.

val okHttpClient = OkHttpClient.Builder()
        .addInterceptor {
            val response = it.call().execute()

            val updatedResponse = if (response.code() == 400) {
                response.newBuilder()
                        .code(200)
                        .build()
            } else {
                response
            }

            updatedResponse
        }
        ...
        .build()

val apollo = ApolloClient.builder()
        .okHttpClient(okHttpClient)
        ...
        .build()
0 голосов
/ 26 марта 2020

, если вы используете Retrofit, пожалуйста, проверьте ниже код

protected void onApiError(Throwable throwable) {
        setIsLoading(false);
        Timber.e(throwable);
        if (throwable instanceof HttpException) {
            Response errorResponse = ((HttpException) throwable).response();
            if (errorResponse != null) {
                ResponseBody errorResponseBody = errorResponse.errorBody();
                if (errorResponseBody != null) {
                    ApiError response = new Gson().fromJson(errorResponseBody.charStream(), ApiError.class);
                    if (response != null) {
                        showToast(TextUtils.isEmpty(response.statusMessage) ? response.description : response.statusMessage);
                    } else {
                        showToast(R.string.something_went_wrong);
                    }
                } else {
                    showToast(R.string.something_went_wrong);
                }
            } else {
                showToast(R.string.something_went_wrong);
            }
        } else {
            showToast(R.string.something_went_wrong);
    }
}

ApiError. java

@Parcel
public class ApiError {

    @SerializedName("statusCode")
    public int statusCode;

    @SerializedName("statusMessage")
    public String statusMessage;

    @SerializedName("error")
    public String error;

    @SerializedName("error_description")
    public String description;

    public ApiError() {
    }
}
...