如何从reqwest::Request获取请求体?流式场景处理及None原因排查
关于reqwest 0.12.9中Multipart请求体获取的问题
问题背景
使用reqwest 0.12.9版本(启用json、multipart特性)构建Multipart请求,需要提取请求体字节用于签名,但通过req.body_mut().map(|b| b.as_bytes())获取时始终返回None。相关代码如下:
let payload = serde_json::to_string(&document.metadata).unwrap(); let mut metadata_headers = HeaderMap::new(); metadata_headers.insert( CONTENT_TYPE, HeaderValue::from_str("application/json").unwrap(), ); let metadata_part = Part::text(json!(payload).to_string()) .headers(metadata_headers) .file_name("metadata"); let mut file_headers = HeaderMap::new(); file_headers.insert( CONTENT_TYPE, HeaderValue::from_str("application/octet-stream").unwrap(), ); let byte_array = document.content.to_vec(); let file_form_part = Part::bytes(byte_array.clone()) .headers(file_headers) .file_name(document.metadata.id_doc_type); let form = Form::new() .part("metadata", metadata_part) .part("content", file_form_part); let request_builder = RequestBuilder::from_parts(Client::new(), Request::new(Method::POST, url.clone())) .multipart(form) .headers(new_headers); let (client, request) = request_builder.build_split(); let body_bytes = match request { Ok(req) => req.body_mut().map(|b| b.as_bytes()).unwrap_or_default(), Err(_) => None, };
提出两个问题:
- 若当前为流式场景,该如何获取请求体?
- 若不是流式场景,为何body会是
None?
问题解答
1. 为什么body返回None?
你的场景本质就是流式处理:reqwest的Multipart请求默认采用流式生成请求体,即使你上传的内容是内存中的字节,MultipartBody也会分块组装multipart格式数据,不会提前将完整请求体缓存到内存中。因此as_bytes()方法会返回None——它只对预存在内存中的非流式Body有效。
2. 流式场景下如何获取完整请求体?
需要手动将Multipart Form序列化为完整的字节数组,而不是依赖Request的body对象获取。具体实现分两种场景:
同步场景(使用reqwest同步Client)
利用std::io::Read trait读取Body的所有字节:
// 构建好你的form之后 let mut body = reqwest::Body::from(form); let mut body_bytes = Vec::new(); // 读取所有字节到body_bytes中 std::io::Read::read_to_end(&mut body, &mut body_bytes).unwrap();
异步场景(使用reqwest异步Client)
使用Body的into_bytes()方法(需await):
use futures_util::StreamExt; // 构建好你的form之后 let body = reqwest::Body::from(form); let body_bytes = body.into_bytes().await.unwrap();
拿到body_bytes后,你就可以用它来生成签名,再将签名插入最终请求的请求头中。
内容的提问来源于stack exchange,提问作者kaning
相关产品推荐
相关产品推荐

