Protocol Buffers
背景
Protocol Buffers是Google开发的语言中立、平台中立、可扩展的结构化数据序列化机制——类似XML,但更小、更快、更简单。您只需定义一次数据结构,之后就可以使用专门生成的源代码,轻松地以多种语言(如Java、C++或Python)在各种数据流中读写结构化数据。
Protocol Buffers序列化格式采用二进制编码,不易人工阅读。由于Protocol Buffers消息常通过HTTP交换,我们添加了以人类可读方式查看和编辑Protocol Buffers消息的完整支持。
Charles当前支持Protocol Buffers 2.4.1版本,该版本基本向后兼容早期版本。
概述
当HTTP请求或响应的Content-Type
头包含MIME类型application/x-protobuf
或application/x-google-protobuf
时,Charles会识别其中含有Protocol Buffers消息。此时会新增两个HTTP正文内容查看器:Protobuf文本查看器和Protobuf结构化查看器。
为使查看器能显示消息内容,需要访问HTTP正文中消息对应的protocol buffers描述符。Charles通过解析content-type中的desc
和messageType
参数来定位FileDescriptorSet(*.desc
文件)和完全限定的消息类型名,进而加载对应描述符。可通过protocol buffers编译器(protoc)使用-o
或--descriptor_set_out
选项从*.proto
文件生成FileDescriptorSet,例如:protoc -oModel.desc Model.proto
。
HTTP正文可能包含单个消息或采用标准protocol buffers长度分隔格式序列化的消息列表。通过检查content-type中可选的delimited
参数判断内容类型(需设为true
表示分隔消息列表)。分隔列表中的所有消息必须为同一类型。
完整的Content-Type
头示例如下:Content-Type: application/x-protobuf; desc="http://localhost/Model.desc"; messageType="com.xk72.sample.PurchaseOrder"; delimited=true
加载FileDescriptorSet
Charles通过Content-Type
头的desc
参数获取FileDescriptorSet的URL地址(支持file
或http
等协议)。每次选择Protobuf查看器时都会尝试获取FileDescriptorSet,这种按需加载机制对处理大量protocol buffers通信时至关重要。
FileDescriptorSet缓存
针对重复使用的消息类型,Charles基于HTTP 1.1标准缓存机制实现FileDescriptorSet缓存:HTTP URL采用标准缓存策略,本地文件通过最后修改时间戳判断。
可通过配置Web服务器的HTTP缓存/验证头(Last-Modified和ETag)优化加载性能,或通过no-cache头禁用缓存。
若无缓存头信息,Charles会启用启发式缓存(默认5分钟),该时长可在Preferences->Viewers中调整(设为0则禁用)。
注:此缓存仅作用于desc
URL解析,不影响Charles记录的HTTP事务行为。
Protobuf文本查看器
以protocol buffers标准文本格式显示消息(与Java的com.google.protobuf.TextFormat
、C++的google.protobuf.text_format.h
或Python的google.protobuf.text_format
模块格式一致)。
显示消息列表时,每条消息以分隔符间隔:>--------------------------------next message--------------------------------<
Protobuf结构化查看器
基础消息显示
以树形结构展示消息的完整层次,包含所有字段和子消息。
各列说明:
- 第一列:Protocol Buffer定义中的字段名
- 第二列:字段类型(标量类型显示
.proto
类型名;枚举类型显示完全限定名;消息类型显示完全限定名;重复字段标注Repeating
前缀) - 第三列:字段值(标量值显示文本;枚举值显示定义名;重复字段显示重复次数)
字符串字段显示C风格转义编码(如\n
表示换行)。双击字段可弹出详细值查看窗口。
未指定可选字段处理
Protocol Buffers中未显式包含的optional字段会采用默认值(定义中的默认值或类型默认值如0
/false
/空字符串)。默认隐藏这些字段(可在Preferences->Viewers中配置显示),显示时以斜体标注。
未知字段处理
当消息定义变更导致存在未知字段时,结构化查看器会显示Unknown Fields
节点,包含字段的数字标签、序列化线类型(Varint/32-bit/64-bit/Length-delimited)和原始值。详见编码文档。
未知消息处理
当无法获取描述符(如缺少desc
/messageType
参数或URL解析失败)时,所有字段将作为未知字段处理,并显示解析错误信息。
配置选项
通过Preferences->Viewers可配置:
- 隐藏未指定字段 - 控制是否显示optional默认字段
- 启用Protobuf描述符缓存 - 是否启用缓存
- 启发式缓存TTL - 无HTTP缓存头时的默认缓存时长(0表示禁用)
- 清除缓存 - 立即清空所有缓存描述符
消息对比
在结构视图或序列视图中选中两个事务时,可通过右键菜单Compare命令使用文本查看器或结构化查看器对比消息内容。
消息编辑
编辑HTTP请求时,若内容类型为application/x-protobuf
或application/x-google-protobuf
,可使用专用编辑器。
文本编辑器模式
直接编辑文本格式消息(底层通过标准库API转换)。需注意:原始消息中的未知字段在重新解析时会报错(*Message type XXX has no field named YYY*),需手动删除。
编辑消息列表时,使用>--------------------------------next message--------------------------------<
分隔各消息。
结构化编辑器模式
始终显示所有定义字段(未赋值的字段显示为斜体)。操作方式:
- 双击值列修改标量字段(右键选择Clear value清空)
- 右键消息类型字段选择Clear entire message清空
- 右键重复字段可添加/插入/删除条目