【问题标题】:HTTP FAILED: java.io.IOException: unexpected end of stream exception while making https requestHTTP FAILED: java.io.IOException: 在发出 https 请求时意外结束流异常
【发布时间】:2019-04-02 11:19:41
【问题描述】:

我们以前使用 http apis,现在我们已经迁移到 https,使用相同的代码,我们面临异常 HTTP FAILED: java.io.IOException: unexpected end of stream (这适用于某些设备和某些网络调用) .我们正在使用 来自 Android 应用的 OkHttp 和 Retrofit。下面是我们的代码

@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();
}```

我们已经尝试过的事情:

  • addHeader("Connection", "close")添加标题
  • 添加连接池限制理想连接
  • 增加超时时间

我们将不胜感激任何帮助,我们已经面临这个问题很长一段时间了。

【问题讨论】:

  • 似乎是 OkHttp 问题 github.com/square/okhttp/issues/2738
  • 已经检查过大多数答案都不适用于我们的案例。
  • @Asheesh 我用真机运行,一切都会好起来的。

标签: android retrofit okhttp okhttp3


【解决方案1】:

我刚刚发生了这种情况并想出了一个解决方法。这是由使用 HttpLoggingInterceptor 引起的。通过调试 okhttp 代码,我发现它抛出了该错误,因为正文的长度与响应中的内容长度标头不匹配。如果它接收到内容标头,它将使用 FixedLengthSource 并且在读取它时会抛出“意外的流结束”错误。这个可以在源码https://github.com/square/okhttp/blob/okhttp_3.9.x/okhttp/src/main/java/okhttp3/internal/http1/Http1Codec.javaopenResponseBody 方法中看到

作为一种解决方法,我向我的构建器添加了一个 response 解释器,该解释器去除了导致它使用 UnknownLengthSource 的 content-length 标头。

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

【讨论】:

    猜你喜欢
    • 2018-09-01
    • 2022-08-24
    • 1970-01-01
    • 2018-03-11
    • 1970-01-01
    • 2018-06-13
    • 2019-03-14
    • 1970-01-01
    相关资源
    最近更新 更多