HTTP失败:java.io.IOException:发出https请求时流意外结束异常 [英] HTTP FAILED: java.io.IOException: unexpected end of stream exception while making https request
问题描述
我们以前使用的是http api,现在我们已经迁移到https,使用相同的代码我们面临着HTTP FAILED异常:java.io.IOException:流的意外结束(这适用于某些设备和某些网络调用).我们正在使用OkHttp和来自Android应用程序的Retrofit.以下是我们的代码
We are previously using http apis and now we have migrated to https, with same code we are facing the exception HTTP FAILED: java.io.IOException: unexpected end of stream (this is for some device and for some network calls). We are using the
OkHttp and Retrofit from android app. Below is our code
@Provides
@ApplicationScope
OkHttpClient provideOkHttpClientV2(
HttpLoggingInterceptor logging,
Interceptor headerInterceptor) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//Removed custom timeout units
return builder.addInterceptor(headerInterceptor)
.addInterceptor(logging)
.retryOnConnectionFailure(true)
.readTimeout(100, TimeUnit.SECONDS)
.connectTimeout(100, TimeUnit.SECONDS)
.build();
}
@Provides
@ApplicationScope
Interceptor provideRetrofitHeaderV2(final SharedPreferencesUtil sharedPreferencesUtil) {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder();
builder.header("Content-Type", "application/json")
.method(original.method(), original.body());
if (sharedPreferencesUtil != null) {
if (sharedPreferencesUtil.isLogin()) {
String loginToken = sharedPreferencesUtil.getLoginToken();
builder.addHeader("Authorization", "Bearer " + loginToken);
}
}
builder.addHeader("Connection", "close");
Request request = builder.build();
return chain.proceed(request);
}
};
}
@Provides
@ApplicationScope
HttpLoggingInterceptor provideLoggingInterceptorV2() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
} else {
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return logging;
}
@Provides
@ApplicationScope
Retrofit provideRetrofitV2(OkHttpClient okHttpClient) {
return new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.build();
}```
我们已经尝试过的事情:
Things we have already tried:
- 使用
addHeader("Connection","close")
添加标头 - 添加连接池以限制理想的连接
- 增加超时时间
任何帮助将不胜感激,我们面对这个问题已有相当长的时间了.
Any help will be appreciated, we are facing this issue for quite some time now.
推荐答案
我刚遇到这种情况,并想出了一种解决方法.这是由于使用HttpLoggingInterceptor引起的.通过调试okhttp代码,我发现它引发了该错误,因为主体的长度与响应中的内容长度标头不匹配.如果接收到内容标头,则它将使用FixedLengthSource,并且在读取时将引发意外的流末尾"错误.您可以在源 https://github.com/square/okhttp/blob/okhttp_3.9.x/okhttp/src/main/java/okhttp3/internal/http1/Http1Codec.java openResponseBody方法
I just had this happen and figured out a workaround. This was caused by the use of the HttpLoggingInterceptor. Through debugging into the okhttp code I found that it was throwing that error because the length of the body did not match what the content length header in the response was. If it receives a content header it uses a FixedLengthSource and that will throw the "unexpected end of stream" error when it is read. You can see this in the source https://github.com/square/okhttp/blob/okhttp_3.9.x/okhttp/src/main/java/okhttp3/internal/http1/Http1Codec.java openResponseBody method
作为一种解决方法,我在构建器中添加了一个 response 解释器,该解释器去除了内容长度标头,从而导致其使用UnknownLengthSource.
As a workaround I added a response interpreter to my builder that strips out the content-length header which causes it to use an UnknownLengthSource.
private static final Interceptor REWRITE_CONTENT_LENGTH_INTERCEPTOR = new Interceptor() {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().removeHeader("Content-Length")
.build();
}
};
这篇关于HTTP失败:java.io.IOException:发出https请求时流意外结束异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!