我们的大创项目在进行联调的时候发现ESP32发送http请求后无法收到来自服务端的响应, 经过了一整天的debug, 我们最终发现是Content-length
和Transfer-Encoding: chunked
这两个头的问题, 关于它们的介绍请见: https://www.cnblogs.com/xuehaoyue/p/6639029.html, 这里主要分析一下为什么会出问题以及解决方案.
后端(Spring Boot):
经过一番折腾, 我发现直接返回文本会带有正确的Content-length
头, 而返回对象序列化成的json则会带有Transfer-Encoding: chunked
这个头. 后来在百度一番搜索, 发现有大佬说是因为对象序列化成json的话Spring Boot不知道返回的数据有多大, 所以无法附加Content-length
头. 解决方案也很简单, 就是添加一个使用ContentCachingResponseWrapper
包装response
的Filter
,
这样的话ContentCachingResponseWrapper
会缓存所有返回的数据,并且顺便设置Content-Length
.
如果还有其他问题, 可以参考这位大佬写的文章: https://zhuanlan.zhihu.com/p/375170625
终端(ESP32, 使用ESP-IDF开发):
向后端发送请求用的是ESP-IDF自带的http client库, 问题在于esp_http_client_get_content_length()
是从Content-length
头中获取长度, 如果是分块传输则应该调用esp_http_client_is_chunked_response()
和esp_http_client_get_chunk_length()
获取长度.
这个问题可给我们坑惨了, 因为文档里除了API参考根本就没提到分块传输, GitHub上也只有寥寥数几的issues提到了它, 所以浪费了我们不少的时间才找到问题. 最后甚至还到GitHub上提了个issue, 希望能把两个获取长度的接口合并一下, 但是似乎被否决了, 链接在这里: https://github.com/espressif/esp-idf/issues/8258.
不愧是你, 乐鑫
如果想学习一下http client库的用法, 可以去大佬的博客看看: https://redlightasl.github.io/2022/01/24/ESP32-IDF学习9【HTTP客户端】/