我有新闻清单。当用户单击新闻之一时,我将显示完整的新闻信息。在那一刻,我在标头中将此消息的别名发送到后端请求。有时我的应用程序崩溃。但是此请求具有onError处理程序。我无法重现此错误。但我在Crashlytics上看到此错误。
我知道有非ASCII符号。无法显示所有标题。我有很多新闻,其中之一可以有非ASCII符号。我需要确保此错误将在onError中处理,并且应用不会崩溃。
这里是日志错误
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();
}
}
标题不能包含非ASCII字符。请参考https://github.com/square/okhttp/issues/2896。而不是您应该尝试将标头值解码为base64。