原文地址:www.charlesproxy.com/documentati…
原文作者:
发布时间:
背景资料
引用协议缓冲器网站上的一句话:"协议缓冲器是谷歌的语言中立、平台中立、可扩展的结构化数据机制。
协议缓冲区是谷歌的语言中立、平台中立、可扩展的结构化数据序列化机制--想想XML,但更小、更快、更简单。你只需定义一次你想要的数据结构化方式,然后你就可以使用特殊生成的源码轻松地将你的结构化数据写入或从各种数据流中读取,并使用各种语言--Java、C++或Python。
Protocol Buffers序列化格式是一种二进制编码格式,不容易被人类读取。由于协议缓冲区消息通常通过HTTP进行交换,我们已经添加了完整的支持,以人类可读的方式查看和编辑协议缓冲区消息。
Charles目前支持2.4.1版本的Protocol Buffers,它在很大程度上向后兼容早期版本。
概述
当Content-Type头的MIME类型为application/x-protobuf或application/x-google-protobuf时,Charles识别出HTTP请求或响应包含协议缓冲区消息。在查看内容时,两个新的HTTP主体内容查看器变得可用,即Protobuf文本查看器和Protobuf结构化查看器。
为了让这些查看器能够显示消息内容,他们需要访问HTTP正文内容中包含的消息的协议缓冲描述符。Charles在content-type中寻找desc和messageType参数,以发现FileDescriptorSet(*.desc文件)的位置和完全限定的消息类型名称,然后它使用这些来检索和加载消息的适当描述符。协议缓冲区FileDescriptorSet可以由协议缓冲区编译器(protoc)通过使用-o或--descriptor_set_out选项,例如protoc -oModel.desc Model.proto,从一个*.proto文件中生成。
最后,HTTP body的内容可能包含一个单一的消息,也可能包含一个使用标准协议缓冲区长度分隔格式序列化的消息列表。为了确定HTTP主体是否包含一个单一的消息或一个定界的消息列表,在内容类型中需要寻找一个可选的定界参数。这个参数必须存在,并且其值为true,以表示已经发送了一个分隔的消息列表。当一个分隔的消息列表被发送后,所有的消息必须是相同的消息类型。
这意味着一个完整的Content-Type头将看起来像:Content-Type: application/x-protobuf; desc="http://localhost/Model.desc"; messageType="com.xk72.sample.PurchaseOrder"; delimited=true。
加载文件描述符集
Charles希望Content-Type头的desc参数包含一个有效的URL,指向协议缓冲区消息的FileDescriptorSet的位置。这可以是任何有效的URL,但通常是一个文件或http URL。Charles每次选择一个Protobuf查看器显示HTTP正文内容时,都会尝试检索FileDescriptorSet,这意味着直到需要时才会解析desc URL,这在Charles记录大量协议缓冲区事务时至关重要。
FileDescriptorSet缓存
通常情况下,你仍然会得到许多使用相同协议缓冲消息类型的事务,所以Charles确实基于http URL的标准HTTP 1.1缓存和文件URL的最后修改时间戳来实现FileDescriptorSets的缓存。
这意味着你可以通过确保服务于文件的Web服务器设置适当的HTTP 1.1缓存和/或验证(Last-Modified和ETag)头来确保FileDescriptorSet的加载性能。缓存也可以通过设置适当的HTTP 1.1 no-cache头文件来有效地禁止。
当FileDescriptorSet响应中不存在HTTP缓存或验证头文件时,Charles就会为缓存的FileDescriptorSets计算自己的启发式到期时间。Charles缓存这些资源的时间长度可以在Charles的Preferences->Viewers弹窗中配置,它的默认值是5分钟。可以将其设置为0以禁用启发式缓存。
请注意,该缓存仅用于解析desc URLs,它不会以任何方式改变Charles记录HTTP事务的行为。
Protobuf文本浏览器
Protobuf文本体内容查看器显示协议缓冲区消息的默认文本表示。这与Java API中的com.google.protobuf.TextFormat类、google.protobuf.text_format.h C++ API或thegoogle.protobuf.text_format Python模块实现的格式是一样的,这些都是协议缓冲区发行版中附带的。
当显示定界的消息列表时,每条消息都由文本定界符分隔:>--------------------------------next message--------------------------------<。
Protobuf浏览器
基本信息显示
Protobuf正文内容查看器显示协议缓冲区报文的树状结构视图,显示报文的完整层次结构,包括所有字段和子报文。
在结构化查看器中,第一列显示协议缓冲区消息定义的树形结构中每个字段的定义字段名。
第二列显示字段的类型。
- 标量字段被赋予了它们的.proto类型名称,如string, uint32, bool, sfixed64等。
- 枚举的标签是以Enum为前缀的枚举的完全限定类型名称。
- 消息类型的字段被赋予消息的完全限定类型名称。
- 任何重复的字段都以重复为前缀,例如:重复的字符串
第三列显示有关字段值的信息。
- 标量字段显示其值的文字表示。
- 枚举的值有定义的名称显示。
- 重复的字段显示该字段存在的重复次数。
消息类型和重复字段可以被扩展以显示它们所封装的单个字段或重复。请注意,对于字符串字段,显示的不是字符串的字面值,而是它的编码,以支持表示不可打印的字符。所使用的编码是C代码中字符串字面的格式,所以换行变成了\n,制表符变成了\t,等等。
任何字段都可以通过双击打开一个弹出的对话框,其中包含了该字段值的字符串表示。当字段内容太大,不容易显示在表格中时,这很有用。同样,当双击一个信息输入字段时,该字段中包含的整个信息内容,包括其所有子字段都会显示出来。
遗漏的可选字段的处理
对于协议缓冲消息,在消息定义中被定义为可选的字段不必包含在消息中。在这种情况下,当字段没有明确存在于消息中时,它仍然有一个隐含的值。如果在消息定义中为字段定义了一个默认值,那么这个值将是默认值,否则它将获得其类型的正常默认值,例如数字类型为0,布尔类型为false,字符串类型为空字符串。
通常这些未指定的字段会被隐藏起来,因为它被认为是没有什么意义的。这包括隐藏重复次数为0的重复字段。您可以在Charles的 "首选项->查看器 "对话框中配置查看器以显示这些未指定字段。
当未指定字段被显示时,它们的字段名、类型信息和隐含或默认值会以斜体显示在查看器中。
未知字段
对于协议缓冲区消息,有可能在消息内容中获得未知字段,这通常发生在消息定义已经改变,并且正在解析包含消息定义中不再存在的字段的旧消息时。
当发生这种情况时,结构化查看器会在消息层次结构中显示一个未知字段子节点,可以展开该子节点查看与未知字段相关的可用信息。因为通常在消息定义中为这些字段找到的元数据是不可用的,您能看到的只是字段的数字标签、序列化线类型和序列化值。可能的线型有
- Varint
- 32位
- 64位
- 长度限制
请参阅协议缓冲区编码文档,了解从.proto标量类型到这些线类型的映射以及如何解码序列化的值。
未知信息
在某些情况下,消息的协议缓冲描述符不可用。例如,这可能发生在Content-Type头中没有指定desc或messageType参数,或者在解析desc参数中提供的URL时出现错误。
当这种情况发生时,协议缓冲区消息会被解析为未知消息,实际上这意味着消息中的所有字段都变成了未知字段,并且只显示我们能从线格式中发现的最小信息。导致消息被解析为未知消息的错误也会显示在查看器中,希望能让您修复任何导致该问题的原因。
配置选项
协议缓冲区功能的某些方面是用户可配置的。这些选项在 "首选项 "对话框的 "查看器 "部分提供。首选项对话框可从 "编辑 "菜单(或Mac OS X上的Charles菜单)中激活。
- Hide Unspecified Fields(隐藏未指定的字段)--当选择该选项时,在结构化查看器中显示该消息时,将隐藏协议缓冲区消息中未指定的可选字段,当未选择该选项时,未指定的字段将以斜体显示,同时显示它们的默认值或隐含值。
- 缓存Protobuf描述符 - 启用缓存部分所述的协议缓冲区描述符的缓存,当未选择描述符时,描述符将不会被缓存。
- 启发式缓存TTL - 启用缓存时,这是缓存TTL或到期时间,用于从没有指定HTTP缓存头的HTTP URL中检索描述符,当没有明确的HTTP缓存头时,设置为0则永不缓存。
- 清理缓存资源--点击该按钮可立即清理所有缓存的协议缓冲描述符。
比较信息
当您在结构视图或序列视图中正好选择了两个事务时,您可以使用右键上下文菜单中的 Comparecommand 比较它们的内容。
当两个事务都包含协议缓冲区消息以及通常可用的标准比较查看器时,您可以选择使用Protobuf文本查看器或Protobuf结构化查看器来查看事务之间的比较。
编辑信息
当编辑一个HTTP请求的内容时,也可以使用Protobuf Text Viewer和Protobuf Structured Viewer。当您选择编辑一个HTTP请求时,如果它被识别为协议缓冲区请求(通过具有application/x-protobuf或application/x-google-protobuf的内容类型),那么两个protobuf特定的查看器将作为编辑请求内容的选项。
Protobuf文本查看器 - 编辑模式
在编辑模式下,Protobuf Text viewer简单地允许你编辑协议缓冲区消息的可读文本表示。这个文本既是生成的,又是使用标准的协议缓冲区库API(即Java API中的com.google.protobuf.TextFormat类,google.protobuf.text_format.h C++ API或thegoogle.protobuf.text_format Python模块)重新解析(编辑后)成一个序列化的协议缓冲区消息。
你可能需要注意的一个怪癖是,如果原始消息包含未知字段,这些字段会在协议缓冲区文本格式化器生成的文本中表示出来,但当文本试图被重新ars时,它们会引起一个错误(Message type XXX has no field named YYY)。这意味着在编辑时需要手动从文本中删除它们。
当编辑一个定界的消息列表时,编辑器希望在每条消息之间使用文本定界符>--------------------------------next message--------------------------------<。你可以添加或删除这个定界符的实例来添加或删除列表中的信息。
Protobuf Viewer - 编辑模式
编辑模式下的Protobuf查看器以Protobuf结构化视图中描述的相同结构化视图显示当前消息内容。一个关键的区别是,所有定义的字段总是被显示出来,不管它们当前是否被填充。为消息定义的但当前没有填充的字段会以斜体显示。这样就可以很容易地看到消息中存在哪些字段,并为这些字段设置值。
任何标量字段的值都可以通过简单地双击值列来设置(双击行上的其他地方会打开一个包含字段值的对话框,这个功能对于查看非常大的值非常有用)。标量字段可以通过右击字段并选择 "清除值 "来清除(变成一个不在消息中填充的字段)。
同样,也可以通过右键单击字段并选择清除整个消息来清除消息值字段。未填充的消息值字段的处理方式与标量字段非常相似,它们以斜体显示,并以其默认值或隐含值填充。一旦未填充消息的任何子字段被明确设置,那么该消息将成为一个具体的、明确定义的值。
重复的字段可以通过右键点击字段并选择添加重复,或者在右键点击现有重复时使用Insert before或Insert after命令来添加新的重复。也有删除重复选项。
通过www.DeepL.com/Translator(免费版)翻译