OkHttp3请求仅返回响应头无响应体、unexpected end of stream报错求助
解决方案
1. 调整OkHttp配置,解决连接复用兼容问题
你遇到的java.net.ProtocolException: unexpected end of stream异常,核心原因是本地Flask默认的Werkzeug开发服务器的长连接(keep-alive)逻辑和OkHttp默认的连接复用机制不兼容,响应体偏大时服务端会提前断开连接,导致客户端读不到完整响应体。修改OkHttpClient构建代码即可解决:
import okhttp3.ConnectionPool import java.util.concurrent.TimeUnit // 省略其他原有代码 val client = OkHttpClient.Builder() .addInterceptor(interceptor) // 禁用连接池,避免复用已经被服务端断开的连接 .connectionPool(ConnectionPool(0, 1, TimeUnit.NANOSECONDS)) // 开启连接失败自动重试 .retryOnConnectionFailure(true) // 适当调高超时阈值,适配大响应体传输 .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS) .build()
2. 服务端侧适配方案
Werkzeug是专门用于开发调试的服务器,HTTP处理逻辑的兼容性较差,你可以选择以下任意一种方式修改服务端:
- 开发阶段可以给所有响应头添加
Connection: keep-alive字段,匹配OkHttp的长连接逻辑 - 直接用Gunicorn、uWSGI等生产级服务器部署Flask服务,部署完成后该问题会直接消失
3. 临时验证方案
如果需要快速验证问题根源,可以强制所有请求关闭长连接,每次请求完成后直接断开连接:
添加统一拦截器给所有请求加头:
val closeConnectionInterceptor = Interceptor { chain -> val request = chain.request().newBuilder() .header("Connection", "close") .build() chain.proceed(request) } // 把拦截器添加到OkHttpClient的拦截器列表 val client = OkHttpClient.Builder() .addInterceptor(interceptor) .addInterceptor(closeConnectionInterceptor) .build()
可选排查步骤
如果以上方案都未生效,可以先把接口返回类型临时改成Response<String>,先获取原始的响应字符串确认响应本身是完整的,再排查Utilisateur实体类的字段是否和服务端返回完全匹配,避免Gson反序列化异常被误判为流中断问题。
内容的提问来源于stack exchange,提问作者Enima Ben
相关产品推荐
相关产品推荐

