Иногда Rx Java onError не улавливает исключение - PullRequest
0 голосов
/ 01 мая 2020

У меня есть список новостей. Когда пользователь нажимает одну из новостей, я показываю полную информацию о новостях. В тот момент я отправляю на бэкэнд запрос в шапке с псевдонимом этой новости. Иногда мое приложение вылетает. Но у этого запроса есть обработчик onError. Я не могу воспроизвести эту ошибку. Но я вижу эту ошибку на Crashlytics.

Я знаю, что есть символы не ASCII. Не могу показать весь заголовок. У меня много новостей, и одна из них может содержать символы не ASCII. Мне нужно убедиться, что эта ошибка будет обработана в onError, и приложение не обработает sh.

Вот ошибка журнала

Fatal Exception: java.lang.IllegalArgumentException: Unexpected char 0x430 at 12 in Params value: {"itemId":"акция"}
       at okhttp3.Headers$Companion.checkValue(Headers.java:434)
       at okhttp3.Headers$Companion.access$checkValue(Headers.java:346)
       at okhttp3.Headers$Builder.add(Headers.java:245)
       at okhttp3.Request$Builder.addHeader(Request.java:210)
       at com.example.NetworkModule.lambda$provideAuthOkHttpClient$1(NetworkModule.java:112)
       at com.example.-$$Lambda$NetworkModule$0kozbr2vzEMUs4EGFjGRxf09B6g.intercept(-.java)
       at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:112)
       at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:87)
       at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:219)
       at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:112)
       at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:87)
       at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:194)
       at okhttp3.RealCall$AsyncCall.run(RealCall.java:138)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
       at java.lang.Thread.run(Thread.java:762)

Вот пример кода.

mNetworkHelper.sendGrafanaMetrics()
                    .compose(RxUtil.applySchedulers())
                    .subscribe(response -> {
                    }, this::silentError);

Это часть класса NetworkModule. 112 строка - .addHeader (PARAMS_HEADER, params);

@Module
public class NetworkModule implements Constants {
    @Provides
    @Singleton
    @Named("authClient")
    OkHttpClient provideAuthOkHttpClient(Context context, PreferencesHelper preferencesHelper, VeonApi veonApi, UserAgent userAgent, SSLSocketFactory sslSocketFactory, TrustManager[] trustManager) {
        Cache cache = new Cache(context.getCacheDir(), cacheSize);

        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(message -> Log.d("myLogger", message))
                .setLevel(HttpLoggingInterceptor.Level.BODY);


        Interceptor authInterceptor = chain -> {
            Request original = chain.request();
            String params = userAgent.getJsonString();
            Request.Builder requestBuilder = original.newBuilder()
                    .addHeader(PARAMS_HEADER, params);
            String ticket = preferencesHelper.getTicket();

            if (addTicket && ticket != null) {
                Timber.v("--===adding ticket: %s", ticket);
                requestBuilder.addHeader(AUTHORIZATION_HEADER, ticket);
            } else {
                Timber.v("not adding ticket %s", ticket);
            }
            okhttp3.Response response = chain.proceed(requestBuilder.build());
            if (response.code() == 401) {
                Timber.v("Ticket Expired");
                if (preferencesHelper.rememberMe()) {
                    refreshTicket(veonApi, preferencesHelper);
                    ticket = preferencesHelper.getTicket();
                    if (ticket != null) {
                        requestBuilder.addHeader(AUTHORIZATION_HEADER, ticket);
                    }
                    response = chain.proceed(requestBuilder.build());
                } else {
                    return new okhttp3.Response.Builder()
                            .code(418)
                            .request(chain.request())
                            .protocol(response.protocol())
                            .message(context.getString(R.string.ticket_reload_required))
                            .body(ResponseBody.create(null,
                                    new Gson().toJson(new ResponseException(418, context.getString(R.string.ticket_reload_required)))))
                            .build();
                }
            }
            return response;
        };

        return new OkHttpClient.Builder()
                .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                .retryOnConnectionFailure(true)
                .addInterceptor(logInterceptor)
                .addInterceptor(authInterceptor)
                .cache(cache)
                .connectTimeout(TIMEOUT_SEC, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT_SEC, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT_SEC, TimeUnit.SECONDS)
                .hostnameVerifier((hostname, session) -> true)//todo should not be in prod
                .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManager[0])//todo should not be in prod
                .build();
    }
}

Сетевой запрос sendGrafanaMetrics имеет только данные заголовка. Этот запрос нужен для статистики c цели. Это часть запроса заголовка. {"itemId": "новые данные"}. Иногда в itemId я могу получить не ASCII символы

1 Ответ

0 голосов
/ 04 мая 2020

Заголовки не могут содержать символы не ASCII. Пожалуйста, обратитесь к https://github.com/square/okhttp/issues/2896. Вместо этого вы должны попытаться декодировать значение заголовка как base64.

...