如何将二进制gRPC元数据反序列化为Rust结构体?
问题:gRPC二进制元数据反序列化为Rust结构体失败
尝试将客户端传来的二进制gRPC元数据反序列化为Rust结构体,按建议使用bincode处理后反序列化,但运行时触发错误。
结构体定义
#[derive(serde::Serialize, serde::Deserialize)] #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Metadata { /// login token #[prost(string, tag = "1")] pub access_key: ::prost::alloc::string::String, /// pack type #[prost(string, tag = "2")] pub mobi_app: ::prost::alloc::string::String, /// device #[prost(string, tag = "3")] pub device: ::prost::alloc::string::String, /// inner build id #[prost(int32, tag = "4")] pub build: i32, /// channel #[prost(string, tag = "5")] pub channel: ::prost::alloc::string::String, /// device buvid #[prost(string, tag = "6")] pub buvid: ::prost::alloc::string::String, /// app platform #[prost(string, tag = "7")] pub platform: ::prost::alloc::string::String, }
处理代码
//... let req_metadata_bin = request .metadata() .get_bin("x-auth-metadata-bin") .unwrap() .as_ref(); let req_metadata: Metadata = bincode::deserialize(req_metadata_bin).unwrap();
错误信息
thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: UnexpectedEof, error: "" })'
二进制数据示例
x-auth-metadata-bin: CiA4NGIxOTE5NTUxZWM1ZGE5M2M1MzI4MzY5ODc5ZjNjMhIHYW5kcm9pZCD0oLADKgZtYXN0ZXIyJVhVMEQwNTgwQTgwQzgyMjc2RDlERjMzQjREMjA2NjVDNDJFMzM6B2FuZHJvaWQ
解决方案
问题根源
- 客户端传来的元数据是Base64编码的Protobuf二进制数据,而非bincode格式,用bincode反序列化必然失败。
- gRPC的二进制元数据字段默认会做Base64编码传输,需要先解码得到原始Protobuf二进制。
修改后的代码
首先确保依赖中包含base64 crate:
# Cargo.toml [dependencies] prost = "0.12" base64 = "0.21"
处理逻辑调整为:
use base64::engine::{general_purpose, Engine as _}; // 获取Base64编码的元数据 let req_metadata_base64 = request.metadata().get_bin("x-auth-metadata-bin").unwrap().as_ref(); // 解码Base64得到原始Protobuf二进制 let req_metadata_bin = general_purpose::STANDARD.decode(req_metadata_base64).unwrap(); // 使用prost的Message::decode方法反序列化 let req_metadata = Metadata::decode(&*req_metadata_bin).unwrap();
额外优化
如果不需要同时支持serde序列化,可以去掉结构体上的serde::Serialize和serde::Deserialize derive,减少不必要的依赖:
#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Metadata { // ... 字段定义不变 }
内容的提问来源于stack exchange,提问作者cxw620
相关产品推荐
相关产品推荐

