Android应用POST请求异常:服务器收头无体且Content-Length>0求助
关于Retrofit/OkHttp POST请求仅发送头无请求体的排查思路
我之前也碰到过类似的诡异问题,结合自己的排查经验和对HTTP协议、OkHttp的了解,给你梳理几个可能的方向和排查建议:
一、HTTP协议与网络层面的可能性
- TCP连接中断导致请求体丢失:HTTP请求的头和体通过TCP包传输,虽然客户端在请求头里设置了正确的
Content-Length,但如果请求体传输过程中TCP连接意外断开(比如网络波动、运营商节点故障),服务器就只会收到已到达的请求头,请求体永远传不过来。这种偶发性的网络抖动很难在测试环境复现,尤其是生产环境的复杂网络链路更容易出现。 - 特殊传输场景的异常:虽然你提到
Content-Length>0(说明用的是固定长度传输而非分块编码),但还是要确认请求头里有没有同时出现Content-Length和Transfer-Encoding: chunked(规范不允许,但某些旧系统可能存在异常),这可能导致服务器解析混乱。
二、OkHttp/Retrofit客户端的潜在问题
- RequestBody写出异常:如果用了自定义
RequestBody,或者Converter(比如GsonConverter)序列化时抛出未捕获的异常,OkHttp可能已经发送了请求头,但写请求体时失败导致连接中断。建议添加一个OkHttp拦截器,在请求发送前完整打印请求体,确认序列化过程没问题:new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (request.body() != null) { Buffer buffer = new Buffer(); request.body().writeTo(buffer); String body = buffer.readUtf8(); Log.d("REQUEST_BODY", body); } return chain.proceed(request); } } - 旧版本OkHttp的bug:你用的OkHttp 3.6是2017年的老版本,虽然排查了重试拦截器,但后续版本修复了不少网络相关的bug(比如连接复用、请求体发送的异常处理)。建议尝试升级到OkHttp 3.12.x(兼容API 16),看是否能解决问题。
- API 16的系统兼容性:在API<24的设备上,OkHttp默认使用系统的
HttpURLConnection实现,旧版本Android的网络栈可能存在偶发性bug,比如请求体未正确写入输出流就断开连接。可以尝试强制OkHttp使用自身的HTTP引擎:OkHttpClient client = new OkHttpClient.Builder() .connectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS)) .build();
三、PHP服务器及中间件的配置问题
- 请求超时设置过短:如果服务器(或前端Nginx等代理)的
client_body_timeout、max_input_time设置得太短,即使请求体很小,网络拥堵时也可能触发服务器提前断开连接,导致PHP只接收到请求头。 - PHP参数限制异常:虽然你的小请求体不会超过
post_max_size,但如果服务器上的post_max_size设置得异常小(比如1KB以下),或者upload_max_filesize影响了multipart请求,也可能导致PHP丢弃请求体。可以检查php.ini中的这两个配置项。 - 反向代理的拦截:如果生产环境有Nginx、CDN等中间件,这些服务可能因为缓存、限流策略截断请求体。建议在服务器上用
tcpdump抓包,确认请求体是否真的到达了服务器,还是被中间件拦截了。
四、其他偶发性场景
- 系统级网络拦截:某些安卓设备上的省电软件、VPN、系统防火墙可能在后台拦截网络请求,导致请求体未被发送。这种情况很难复现,只能通过收集生产环境的设备信息来排查。
- 隐蔽的请求取消场景:除了用户关闭应用,Activity/Fragment销毁时未正确取消请求、RxJava订阅提前取消(如果用了RxJava配合Retrofit)等场景,也可能导致请求体未发送。可以在请求取消时添加日志,确认是否存在这类情况。
排查建议总结
- 客户端添加拦截器,确认请求体确实被正确序列化并准备发送;
- 服务器端抓包,验证请求体是否真的到达了服务器;
- 检查服务器和中间件的超时、大小限制配置;
- 升级OkHttp到较新的稳定版本,排除旧版本bug;
- 收集生产环境的错误日志和设备信息,缩小偶发问题的范围。
内容的提问来源于stack exchange,提问作者Amit Barjatya
相关产品推荐
相关产品推荐

