跳过导航 →

Protocol Buffers

背景

引用自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-protobufapplication/x-google-protobuf时,Charles会识别其中含有Protocol Buffers消息。此时会新增两个HTTP正文内容查看器:Protobuf文本查看器Protobuf结构化查看器

为使查看器能显示消息内容,需要访问HTTP正文中消息对应的protocol buffers描述符。Charles通过解析content-type中的descmessageType参数来定位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地址(支持filehttp等协议)。每次选择Protobuf查看器时都会尝试获取FileDescriptorSet,这种按需加载机制对处理大量protocol buffers通信时至关重要。

FileDescriptorSet缓存

针对重复使用的消息类型,Charles基于HTTP 1.1标准缓存机制实现FileDescriptorSet缓存:HTTP URL采用标准缓存策略,本地文件通过最后修改时间戳判断。

可通过配置Web服务器的HTTP缓存/验证头(Last-Modified和ETag)优化加载性能,或通过no-cache头禁用缓存。

若无缓存头信息,Charles会启用启发式缓存(默认5分钟),该时长可在Preferences->Viewers中调整(设为0则禁用)。

注:此缓存仅作用于descURL解析,不影响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-protobufapplication/x-google-protobuf,可使用专用编辑器。

文本编辑器模式

直接编辑文本格式消息(底层通过标准库API转换)。需注意:原始消息中的未知字段在重新解析时会报错(*Message type XXX has no field named YYY*),需手动删除。

编辑消息列表时,使用>--------------------------------next message--------------------------------<分隔各消息。

结构化编辑器模式

始终显示所有定义字段(未赋值的字段显示为斜体)。操作方式:

  • 双击值列修改标量字段(右键选择Clear value清空)
  • 右键消息类型字段选择Clear entire message清空
  • 右键重复字段可添加/插入/删除条目