Kotlin/Native使用libcurl发送POST请求遇JSON解析错误求助
Kotlin/Native + libcurl 长POST请求400错误排查方案
问题本质
Spring Boot返回400加字符160异常,说白了就是后端收到的请求体里混入了非法的不间断空格(ASCII 160),且仅长JSON触发,这肯定是Kotlin/Native与libcurl结合时的请求体处理出了边界问题——短字符串刚好避开了这个坑,长字符串就踩中了。
具体排查方向和解决办法
1. 请求体长度指定错误
libcurl发送POST请求时需要准确指定数据长度,如果长JSON的长度计算和实际字节数偏差,后端会收到不完整的JSON,甚至会把内存里的脏数据(比如ASCII 160)当成请求体的一部分,直接导致解析失败。
- 别手动计算长度,直接调用:
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, jsonString.length.toLong()),注意Kotlin/Native字符串默认是UTF-8编码,要和后端的解析编码保持一致。
2. 字符串内存被提前回收
Kotlin/Native的内存模型和JVM不同,长字符串如果在curl_easy_perform执行完成前被GC回收,libcurl拿到的就是乱码或脏数据,这就会出现莫名其妙的非法字符。
- 换用
CURLOPT_COPYPOSTFIELDS替代CURLOPT_POSTFIELDS,让libcurl主动拷贝请求体数据,避免原字符串内存引用失效:curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, jsonString)。 - 同时要确保JSON字符串在整个请求周期(从设置参数到请求结束)都处于有效作用域内,不要提前被销毁。
3. 字符串混入不间断空格
拼接长JSON时,可能会无意识引入ASCII 160(比如从复制的文本中带入),短字符串刚好没这个问题,长字符串就会触发报错。
- 生成JSON后做清洗处理:
val cleanJson = jsonString.replace("\u00A0", ""),移除所有不间断空格。 - 打印完整JSON字符串到日志,对比Postman或终端curl发送的内容,确认是否存在额外非法字符。
4. 分块传输配置错误
长JSON可能触发libcurl的分块传输,但如果请求头配置不当,后端可能无法解析分块数据导致报错。
- 显式设置请求头,必须包含
Content-Type: application/json,若使用分块传输则加上Transfer-Encoding: chunked。用curl_slist_append组装头信息后,通过CURLOPT_HTTPHEADER设置给libcurl。 - 若不确定分块问题,可临时关闭分块测试:
curl_easy_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L),这仅作为测试手段,不建议长期使用。
验证技巧
- 用Wireshark抓包,对比Kotlin/Native发送的长请求和终端curl的请求,查看请求体的内容、长度、编码是否一致。
- 在Spring Boot后端添加拦截器,打印接收到的原始请求体字节,确认是否真的存在ASCII 160,或是请求体被截断。
- 逐步缩短长JSON长度,找到触发错误的临界值,判断是否为固定边界的内存或长度计算问题。
内容的提问来源于stack exchange,提问作者Alopex
相关产品推荐
相关产品推荐

