2. Defining New Structured Fields (定义新的结构化字段)
要将HTTP字段指定为结构化字段,其作者需要:
必需步骤
1. 规范性引用本规范
字段的接收者和生成者需要知道本文档的要求有效。
示例引用文本:
"本字段是一个结构化字段 [RFC8941]。"
2. 标识字段类型
确定该字段是:
- 结构化头部 (Structured Header): 只能用于头部区段(常见情况)
- 结构化尾部 (Structured Trailer): 只能用于尾部区段
- 结构化字段 (Structured Field): 两者皆可
3. 指定顶级数据类型
选择以下类型之一:
- List (列表) - 第3.1节
- Dictionary (字典) - 第3.2节
- Item (项目) - 第3.3节
4. 定义字段值的语义
说明字段的含义和用途。
5. 指定额外约束
定义字段值的约束条件,以及违反这些约束时的后果。
定义模式
通常,字段定义会指定顶级类型(List、Dictionary或Item),然后定义其允许的类型和约束。
示例约束
List类型字段:
- 所有成员都是Integer
- 或者混合类型
Item类型字段:
- 仅允许String
- 并且仅允许以字母"Q"开头的字符串
- 或者仅允许小写字符串
特别注意: 内部列表 (Inner Lists, 第3.1.1节) 仅在字段定义明确允许时才有效。
错误处理
当解析失败时,整个字段被忽略(参见第4.2节);在大多数情况下,违反字段特定约束应该产生相同的效果。
默认行为
场景: 字段定义为Item且必须是Integer,但接收到String
默认行为: 忽略该字段
如果需要不同的错误处理,必须明确指定。
可扩展性
Parameters (参数) - 扩展机制
Item和Inner List都允许参数作为可扩展性机制;这意味着将来可以扩展值以容纳更多信息。
为了保持向前兼容性: 字段规范不鼓励 (discouraged) 将未识别参数的存在定义为错误条件。
"Grease" Parameters (润滑参数)
为了进一步确保未来的可扩展性,并鼓励消费者使用完整的解析器实现,字段定义可以指定发送者添加"grease"参数。
示例策略:
---------
规范可以规定所有符合定义模式的参数都保留用于此用途,
然后鼓励在部分请求中发送它们。
目的:
----
这有助于阻止接收者编写不考虑参数的解析器。
Dictionary的向前兼容性
使用Dictionary的规范也可以通过要求忽略未知成员的存在及其关联的值和类型来实现向前兼容。后续规范可以添加其他成员,并适当指定对它们的约束。
然后,结构化字段的扩展可以要求:如果理解该扩展的接收者发现其定义的值不满足约束,则忽略整个字段值。
约束规则
不能放松要求
字段定义不能 (cannot) 放松本规范的要求,因为这样做会妨碍通用软件的处理;它们只能添加额外的约束。
可以添加的约束示例:
- Integer和Decimal的数值范围
- String和Token的格式
- Dictionary值中允许的类型
- List中Item的数量
全字段适用
字段定义只能将本规范用于整个字段值,而不是其中的一部分。
实现限制
最小值
本规范为实现支持的各种结构的长度或数量定义了最小值。
最大值
在大多数情况下,它不指定最大大小,但作者应该意识到HTTP实现确实对以下方面施加了各种限制:
- 单个字段的大小
- 字段总数
- 整个头部或尾部区段的大小
命名约定
规范可以将字段名称称为:
- "结构化头部名称 (structured header name)"
- "结构化尾部名称 (structured trailer name)"
- "结构化字段名称 (structured field name)"
字段值可以称为:
- "结构化头部值 (structured header value)"
- "结构化尾部值 (structured trailer value)"
- "结构化字段值 (structured field value)"
ABNF使用
字段定义鼓励 (encouraged) 使用本规范中以"sf-"开头的ABNF规则;本规范中的其他规则不打算用于字段定义。
完整示例: Foo-Example头部
42. Foo-Example Header
The Foo-Example HTTP header field conveys information about how
much Foo the message has.
Foo-Example is an Item Structured Header [RFC8941]. Its value
MUST be an Integer (Section 3.3.1 of [RFC8941]). Its ABNF is:
Foo-Example = sf-integer
Its value indicates the amount of Foo in the message, and it MUST
be between 0 and 10, inclusive; other values MUST cause the entire
header field to be ignored.
The following parameter is defined:
* A parameter whose key is "foourl", and whose value is a String
(Section 3.3.3 of [RFC8941]), conveying the Foo URL for the
message. See below for processing requirements.
"foourl" contains a URI-reference (Section 4.1 of [RFC3986]). If
its value is not a valid URI-reference, the entire header field
MUST be ignored. If its value is a relative reference
(Section 4.2 of [RFC3986]), it MUST be resolved (Section 5 of
[RFC3986]) before being used.
For example:
Foo-Example: 2; foourl="https://foo.example.com/"
示例分析
Foo-Example: 2; foourl="https://foo.example.com/"
解析:
- 类型: Item (Integer)
- 值:
2 - 参数:
foourl="https://foo.example.com/"
验证:
- 值是Integer ✓
- 值在0-10范围内 ✓
- foourl参数存在 ✓
- foourl是有效的URI ✓
如果值为15:
Foo-Example: 15; foourl="https://foo.example.com/"
结果: 整个字段被忽略(违反0-10范围约束)
定义清单 (Checklist)
定义新的结构化字段时,确保:
- 规范性引用RFC 8941
- 明确字段是Header/Trailer/Field
- 指定顶级类型 (List/Dictionary/Item)
- 定义字段语义
- 指定类型约束
- 定义值范围约束(如果适用)
- 说明参数(如果有)
- 定义错误处理(如果不同于默认)
- 考虑向前兼容性
- 提供示例
关键要点 (Key Takeaways)
- 五个必需步骤: 引用、类型、数据类型、语义、约束
- 严格的默认: 解析失败 = 忽略字段
- 可扩展性优先: 鼓励使用参数和忽略未知成员
- 只能添加约束: 不能放松RFC 8941的要求
- 完整字段: 规范适用于整个字段值
- 实现限制: 注意HTTP实现的大小限制