You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit调用遇unexpected end of stream错误,Postman正常

排查Retrofit调用时的"unexpected end of stream"异常

我来帮你分析下这个问题——Postman能正常调用但Retrofit抛出java.io.IOException: unexpected end of stream,通常是因为两者的请求细节存在差异,服务器对这些差异的处理方式不同导致的。下面是几个常见的排查方向和解决方案:

  • 请求头不一致
    Postman会自动添加一些默认请求头(比如User-Agent、Accept-Encoding、Accept),而Retrofit如果没手动配置,可能缺失这些头或者格式不符合服务器预期。你可以尝试在Retrofit的OkHttpClient中添加拦截器,手动设置和Postman完全一致的请求头:

    val client = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val originalRequest = chain.request()
            val modifiedRequest = originalRequest.newBuilder()
                .header("User-Agent", "PostmanRuntime/7.32.3") // 替换成你Postman里的UA
                .header("Accept-Encoding", "gzip, deflate, br")
                .header("Accept", "*/*")
                .build()
            chain.proceed(modifiedRequest)
        }
        .build()
    
  • 请求体序列化问题
    你当前用JSONObject手动拼接参数,容易出现编码错误或者Content-Type设置不当的问题。Postman会自动处理JSON请求的Content-Type: application/json; charset=utf-8,而手动拼接可能没正确设置编码。建议改用Retrofit自带的JSON转换器(比如Gson)来序列化参数,避免手动拼接:

    // 先定义参数数据类
    data class RegisterDeviceParams(
        val deviceType: String,
        val deviceId: String,
        val deviceToken: String,
        val description: String
    )
    
    // 修改接口方法
    @POST("你的接口路径")
    fun registerDevice(@Body params: RegisterDeviceParams): Flowable<DefaultResponse>
    

    这样Retrofit会自动处理请求体的序列化和Content-Type的正确设置,比手动拼接更可靠。

  • 超时时间过短
    Retrofit的OkHttpClient默认超时时间可能比Postman短,如果服务器响应较慢,会导致连接提前断开。你可以调整超时参数:

    val client = OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()
    
  • 分块传输编码冲突
    部分服务器会使用分块传输(Transfer-Encoding: chunked),而OkHttpClient默认的处理逻辑可能和服务器不兼容。你可以尝试移除这个请求头:

    val client = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val request = chain.request().newBuilder()
                .removeHeader("Transfer-Encoding")
                .build()
            chain.proceed(request)
        }
        .build()
    
  • 对比请求细节找差异
    最直接的方法是添加日志拦截器,查看Retrofit发送的完整请求(包括头、请求体),和Postman的请求做对比,找出差异点。比如添加HttpLoggingInterceptor:

    val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY // 打印完整请求响应
    }
    val client = OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .build()
    

    运行后查看日志,和Postman的请求详情逐一对比,就能快速定位问题所在。

内容的提问来源于stack exchange,提问作者Harshad07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:23:24