RFC 8288 - Web 链接 (Web Linking)
- 状态 (Status): Proposed Standard (拟议标准)
- 发布日期 (Published): 2017 年 10 月
- 文档流 (Stream): IETF
- 废弃了: RFC5988
- 勘误: 无勘误
摘要 (Abstract)
本规范定义了 Web 上资源之间关系的模型 ("链接 (links)"), 以及这些关系的类型 ("链接关系类型 (link relation types)").
本规范还定义了如何使用 Link 头字段 (Link header field), 在 HTTP 头部中序列化这类链接.
目录 (Contents)
- 1. 引言 (Introduction)
- 1.1. 记号约定 (Notational Conventions)
- 1.2. 一致性和错误处理 (Conformance and Error Handling)
- 2. 链接 (Links)
- 2.1. 链接关系类型 (Link Relation Types)
- 2.1.1. 已注册关系类型 (Registered Relation Types)
- 2.1.2. 扩展关系类型 (Extension Relation Types)
- 2.2. 目标属性 (Target Attributes)
- 2.1. 链接关系类型 (Link Relation Types)
- 3. HTTP 头部中的链接序列化 (Link Serialisation in HTTP Headers)
- 3.1. 链接目标 (Link Target)
- 3.2. 链接上下文 (Link Context)
- 3.3. 关系类型 (Relation Type)
- 3.4. 目标属性 (Target Attributes)
- 3.5. Link 头字段示例 (Link Header Field Examples)
- 4. IANA 事项 (IANA Considerations)
- 5. 安全考虑 (Security Considerations)
- 6. 国际化考虑 (Internationalisation Considerations)
- 7. 参考文献 (References)
- 附录 (Appendices)
相关资源 (Related Resources)
- 官方文本 (Official Text): RFC 8288 (TXT)
- 官方页面 (Official Page): RFC 8288 DataTracker
- 勘误 (Errata): RFC Editor Errata
1. Introduction
本规范定义了Web上资源之间关系的模型("链接",links)以及这些关系的类型("链接关系类型",link relation types).
HTML [W3C.REC-html5-20141028]和Atom [RFC4287]都有明确定义的链接概念;第2节将其概括为一个框架,涵盖这些格式中的链接以及(可能的)其他地方的链接.
此外,第3节定义了用于传达此类链接的HTTP头字段.
1.1. Notational Conventions (符号约定)
本文档中的关键词"MUST","MUST NOT","REQUIRED","SHALL","SHALL NOT","SHOULD","SHOULD NOT","RECOMMENDED","NOT RECOMMENDED","MAY"和"OPTIONAL"应按照BCP 14 [RFC2119] [RFC8174]中的描述进行解释,当且仅当它们以全大写形式出现时,如此处所示.
本文档使用[RFC7230]的增强巴科斯-瑙尔范式(Augmented Backus-Naur Form, ABNF) [RFC5234]符号,包括#规则,并明确包含以下规则: quoted-string, token, SP (空格), BWS (不良空白), OWS (可选空白), RWS (必需空白), LOALPHA, DIGIT.
此外,还包括以下规则:
- URI和URI-Reference来自[RFC3986]
- type-name和subtype-name来自[RFC6838]
- media-query-list来自[W3C.REC-css3-mediaqueries-20120619]
- Language-Tag来自[RFC5646]
1.2. Conformance and Error Handling (一致性和错误处理)
[RFC7230]第2.5节中强调的关于一致性和错误处理的要求适用于本文档.
2. Links
在本规范中,链接是两个资源之间的类型化连接,由以下部分组成:
- 链接上下文 (link context)
- 链接关系类型 (link relation type) (第2.1节)
- 链接目标 (link target)
- 可选的目标属性 (target attributes) (第2.2节)
链接可以被视为以下形式的陈述: "链接上下文在链接目标处具有链接关系类型资源,该资源具有目标属性".
例如,"https://www.example.com/"在"https://example.com"处具有"canonical"资源,该资源具有"text/html"的"type".
链接上下文和链接目标都是国际化资源标识符(Internationalized Resource Identifiers, IRIs) [RFC3987].然而,在常见情况下,链接上下文也将是URI [RFC3986],因为许多协议(如HTTP)不支持解引用IRI.同样,链接目标有时会在不支持IRI的序列化中(例如第3节中定义的Link头字段)转换为URI(参见[RFC3987]第3.1节).
本规范不对链接的基数施加限制;可以有多个指向特定目标和来自特定目标的链接,以及给定上下文和目标之间相同或不同类型的多个链接.同样,在任何特定序列化中或序列化之间(例如,Link头字段和内容中的链接)链接的相对顺序在本规范中未指定或不重要;希望考虑顺序重要的应用程序可以这样做.
链接在链接序列化中传达;它们是"线上的字节",可以以各种形式出现.例如,Atom [RFC4287]和HTML [W3C.REC-html5-20141028]都定义了将链接序列化到各自格式中的方式,第3节定义了如何在HTTP头字段中序列化链接.
本规范没有定义跨不同序列化的链接的通用语法,也没有强制要求任何给定链接的特定上下文;预期链接的序列化将指定这两个方面.
最后,链接由链接应用程序使用.通常,应用程序将定义它使用的链接关系类型,以及它们可能出现的序列化.例如,应用程序"Web浏览"在HTML链接序列化中(以及可选地在Link头字段中)查找"stylesheet"链接关系类型,而应用程序"AtomPub"在Atom序列化中使用"edit"和"edit-media"链接关系.
2.1. Link Relation Types (链接关系类型)
在最简单的情况下,链接关系类型标识链接的语义.例如,具有关系类型"copyright"的链接表示当前链接上下文在链接目标处具有版权资源.
链接关系类型还可用于指示目标资源具有特定属性或表现出特定行为;例如,"service"链接意味着链接目标可以用作定义协议的一部分(在这种情况下,是服务描述).
关系类型不应与媒体类型[RFC2046]混淆;它们不标识解引用链接时产生的表示的格式.相反,它们仅描述当前上下文如何与另一个资源相关.
关系类型不应该(SHOULD NOT)基于另一个链接关系类型的存在或不存在或其自身的出现基数来推断任何额外的语义.一个例外是"alternate"和"stylesheet"注册关系类型的组合,由于历史原因,它在HTML中具有特殊含义.
有两种关系类型: 注册的和扩展的.
2.1.1. Registered Relation Types (注册的关系类型)
明确定义的关系类型可以注册为标记,以方便和/或促进其他应用程序的重用,使用第2.1.1.1节中的程序.
注册的关系类型名称必须(MUST)符合reg-rel-type规则(参见第3.3节),并且必须(MUST)以不区分大小写的方式逐字符比较.它们应该(SHOULD)适合关系类型的特定性;也就是说,如果语义对特定应用程序高度特定,名称应该反映这一点,以便更通用的名称可用于不太特定的用途.
注册的关系类型禁止(MUST NOT)约束链接上下文的媒体类型,并且禁止(MUST NOT)约束链接目标的可用表示媒体类型.但是,它们可以指定目标资源的行为和属性(例如,允许的HTTP方法,以及需要支持的请求和响应媒体类型).
2.1.2. Extension Relation Types (扩展关系类型)
不希望注册关系类型的应用程序可以使用扩展关系类型,这是唯一标识关系类型的URI [RFC3986].尽管URI可以指向包含关系类型语义定义的资源,但客户端不应该(SHOULD NOT)自动访问该资源以避免使其服务器负担过重.
用于扩展关系类型的URI应该(SHOULD)在定义它的人或方的控制之下或被委托给他们.
当比较扩展关系类型时,它们必须(MUST)作为字符串(如果以不同格式序列化,则在转换为URI后)以不区分大小写的方式逐字符比较.因此,应该(SHOULD)为扩展关系使用全小写URI.
请注意,虽然扩展关系类型需要是URI,但链接的序列化可以指定它们以另一种形式表示,只要它们可以转换为URI即可.
2.2. Target Attributes (目标属性)
目标属性是描述链接或其目标的键/值对列表;例如,媒体类型提示.
它们可以由各个链接关系类型和链接序列化定义.
本规范不尝试协调目标属性的名称,其基数或使用.创建和维护序列化的人应该(SHOULD)协调其目标属性以避免语义或语法冲突,并可以(MAY)定义自己的目标属性注册表.
目标属性的名称应该(SHOULD)符合token规则,但SHOULD NOT被限制为ASCII;它们应该(SHOULD)以不区分大小写的方式进行比较.
3. Link Serialisation in HTTP Headers
Link实体头字段提供了一种在HTTP头中序列化一个或多个链接的方法.它在语义上等同于HTML的<link>元素.
Link头字段语法
Link = #link-value
link-value = "`<" URI-Reference ">`" *( OWS ";" OWS link-param )
link-param = token BWS [ "=" BWS ( token / quoted-string ) ]
3.1. Link Target (链接目标)
每个link-value传达一个链接.链接目标由尖括号(< 和 >)内的URI-Reference表示.
3.2. Link Context (链接上下文)
默认情况下,链接的上下文是表示它出现的消息的有效请求URI(Effective Request URI),如[RFC7230]第5.5节中定义的.
当存在时,上下文由Target IRI确定.请注意,任何IRI都必须根据第2节转换为URI才能在Link头字段中表示.
3.3. Relation Type (关系类型)
链接关系类型由"rel"参数的值标识,其值必须(MUST)包含以下之一:
- 注册的关系类型名称(参见第2.1.1节),或
- 扩展关系类型(参见第2.1.2节)
注册的关系类型名称和扩展关系类型可以在同一个"rel"参数值中使用,由一个或多个空格字符分隔.
relation-type = reg-rel-type / ext-rel-type
reg-rel-type = LOALPHA *( LOALPHA / DIGIT / "." / "-" )
ext-rel-type = URI
请注意,扩展关系类型被编码为URI;这意味着任何保留字符都需要根据[RFC3986]第2节进行百分号编码.
3.4. Target Attributes (目标属性)
链接的目标属性在link-value中表示为link-param.
3.4.1. Serialisation-Defined Attributes (序列化定义的属性)
"rel"参数必须(MUST)存在,但不能(MUST NOT)出现多次;如果它不存在或出现多次,则整个link-value无效.
同样,"anchor"参数(如果存在)必须(MUST)仅出现一次;如果它出现多次,则整个link-value无效.
其他常见的目标属性包括:
- hreflang: 指示目标资源的语言.值必须(MUST)符合[RFC5646].
- media: 指示目标资源的预期显示媒体.值必须(MUST)符合[W3C.REC-css3-mediaqueries-20120619].
- title: 用于标记目标资源的人类可读标识符.
- title*: 使用[RFC8187]中定义的编码的国际化版本的"title"参数.
- type: 提供关于目标资源的媒体类型的提示.
3.4.2. Extension Attributes (扩展属性)
其他link-param值是扩展目标属性,可以由链接关系类型或链接的应用程序定义和使用.
扩展目标属性的出现或不存在不应该(SHOULD NOT)使link-value无效,但可能(MAY)影响其在特定应用程序中的使用.
3.5. Link Header Field Examples (Link头字段示例)
例如:
Link: `\`http://example.com/TheBook/chapter2\``; rel="previous";
title="previous chapter"
指示"previous chapter"可以在http://example.com/TheBook/chapter2找到.
Link: `</>`; rel="http://example.net/foo"
指示根资源("/")与自定义扩展关系类型"http://example.net/foo"相关.
Link: `</terms>`; rel="copyright"; anchor="#foo"
指示标识符为"foo"的资源的版权资源可以在/terms找到.
多个链接可以在单个Link头字段中传达:
Link: `</TheBook/chapter2>`; rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
`</TheBook/chapter4>`; rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
这里,两个链接都使用国际化的title参数.
也可以使用多个Link头字段:
Link: `</TheBook/chapter2>`; rel="previous"
Link: `</TheBook/chapter4>`; rel="next"
4. IANA Considerations
4.1. Link HTTP Header Field Registration (Link HTTP头字段注册)
本规范更新了"Message Headers"注册表中"Link"头字段的定义.
头字段名称: Link
适用协议: http
状态: 标准
作者/变更控制者: IETF
规范文档: 本规范(第3节)
4.2. Link Relation Type Registry (链接关系类型注册表)
本规范建立了"Link Relation Types"注册表,位于 ````https://www.iana.org/assignments/link-relations/\````.
注册请求应包括:
- 关系名称: 关系类型的名称
- 描述: 类型语义的简短英文描述
- 参考: 指定链接关系类型的文档的参考
4.3. Link Relation Application Data Registry (链接关系应用数据注册表)
本规范建立了"Link Relation Application Data"注册表.
Appendices
A.1. Link Serialisation in HTML (HTML中的链接序列化)
HTML [W3C.REC-html5-20141028]定义了<link>元素用于传达链接.例如:
`<link rel="stylesheet" href="/style.css" type="text/css">`
HTML链接与本规范中定义的链接模型之间的对应关系如下:
- 链接上下文是包含链接元素的文档的URI
- 链接关系类型由"rel"属性的值标识
- 链接目标由"href"属性的值标识
- 目标属性由其他属性(如"type","media"等)表示
A.2. Link Serialisation in Atom (Atom中的链接序列化)
Atom [RFC4287]定义了一个链接元素,可以出现在feed和entry中.例如:
<link rel="alternate" type="text/html"
href="http://example.org/"/>
Atom链接与本规范中定义的链接模型之间的对应关系如下:
- 链接上下文是包含链接元素的feed或entry的URI
- 链接关系类型由"rel"属性的值标识
- 链接目标由"href"属性的值标识
- 目标属性由其他属性(如"type","hreflang"等)表示
Appendix B. Algorithms for Parsing Link Header Fields (解析Link头字段的算法)
本附录定义了解析Link头字段的算法.这些算法是规范性的.
B.1. Parsing a Header Set for Links (解析头集合以获取链接)
给定一组HTTP头字段headers:
- 让links为空列表
- 对于headers中的每个字段field,其字段名为"Link"(不区分大小写):
- 让field_value为field的字段值
- 让field_links为解析field_value的结果(使用B.2节中的算法)
- 将field_links中的每个链接添加到links
- 返回links
B.2. Parsing a Link Field Value (解析Link字段值)
该算法从一个 Link 头字段值中解析零个或多个以逗号分隔的 link-value. 给定 ASCII 字符串 field_value, 返回 link object 列表:
- 令
links为空列表. - 当
field_value仍有内容时:- 消耗任何前导 OWS.
- 如果第一个字符不是
<, 返回links. - 丢弃
<. - 消耗直到第一个
>之前或输入结束的内容, 并令结果为target_string. - 如果下一个字符不是
>, 返回links. - 丢弃
>. - 令
link_parameters为对剩余field_value执行 B.3 节参数解析的结果. - 按 [RFC3986] 第 5.2 节相对解析
target_string, 得到target_uri. 注意, 负载正文中的任何 base URI 都不使用. - 从
link_parameters中取第一个名称匹配rel的元组的第二项作为relations_string; 如果不存在, 则使用空字符串. - 按 RWS 分割
relations_string, 得到relation_types列表. - 从
link_parameters中取第一个名称匹配anchor的元组的第二项作为context_string; 如果不存在, 则使用承载 Link 头字段的表示的 URL, 并序列化为 URI. 如果该 URL 是 anonymous, 则context_string为 null. - 除非
context_string为 null, 否则按 [RFC3986] 第 5.2 节相对解析context_string, 得到context_uri. 负载正文中的 base URI 同样不使用. - 令
target_attributes为空列表. - 对
link_parameters中每个(param_name, param_value):- 如果
param_name匹配rel或anchor, 跳过该元组. - 如果
param_name匹配media,title,title*或type, 且target_attributes已有同名元组, 跳过该元组. - 否则将
(param_name, param_value)添加到target_attributes.
- 如果
- 找出所有以星号
*结尾的参数名, 形成star_param_names. - 对每个
star_param_name:- 令
base_param_name为去掉末尾*后的名称. - 如果实现不支持该参数的国际化形式, 从
link_parameters中移除所有名称为star_param_name的元组, 并处理下一个星号参数. - 从
link_parameters中移除所有名称为base_param_name的元组. - 将所有名称为
star_param_name的元组名称改为base_param_name.
- 令
- 对每个
relation_type:- 将
relation_type规范化为小写. - 向
links添加一个 link object, 其 target 为target_uri, relation type 为relation_type, context 为context_uri, target attributes 为target_attributes.
- 将
- 返回
links.
B.3. Parsing Parameters (解析参数)
该算法从头字段值中解析参数. 给定 ASCII 字符串 input, 返回其中包含的 (parameter_name, parameter_value) 元组列表, 并从 input 中移除已经解析的字符:
- 令
parameters为空列表. - 当
input仍有内容时:- 消耗任何前导 OWS.
- 如果第一个字符不是
;, 返回parameters. - 丢弃前导
;. - 消耗任何前导 OWS.
- 消耗直到第一个 BWS、
=、;、,或输入结束之前的内容, 并令结果为parameter_name. - 消耗任何前导 BWS.
- 如果下一个字符是
=:- 丢弃
=. - 消耗任何前导 BWS.
- 如果下一个字符是 DQUOTE, 令
parameter_value为按 B.4 节解析 quoted string 的结果. - 否则, 消耗直到第一个
;、,或输入结束之前的内容, 并令结果为parameter_value. - 如果
parameter_name的最后一个字符是*, 按 [RFC8187] 解码parameter_value. 如果遇到不可恢复错误, 继续处理后续输入.
- 丢弃
- 否则, 令
parameter_value为空字符串. - 将
parameter_name规范化为小写. - 将
(parameter_name, parameter_value)添加到parameters. - 消耗任何前导 OWS.
- 如果下一个字符是
,或输入已经结束, 停止处理并返回parameters.
B.4. Parsing a Quoted String (解析带引号的字符串)
该算法按 [RFC7230] 第 3.2.6 节解析 quoted string. 给定 ASCII 字符串 input, 返回去引号后的字符串, 并从 input 中移除已解析字符:
- 令
output为空字符串. - 如果
input的第一个字符不是 DQUOTE, 返回output. - 丢弃第一个字符.
- 当
input仍有内容时:- 如果第一个字符是反斜杠
\, 丢弃该字符. 如果没有更多输入, 返回output; 否则消耗第一个字符并追加到output. - 否则, 如果第一个字符是 DQUOTE, 丢弃该字符并返回
output. - 否则, 消耗第一个字符并追加到
output.
- 如果第一个字符是反斜杠
- 返回
output.
Appendix C. Changes from RFC 5988 (与RFC 5988的变化)
本规范与RFC 5988相比的主要变化包括:
- 澄清了链接上下文和链接目标的定义
- 更新了注册程序以使用RFC 8126
- 添加了解析算法(附录B)
- 澄清了扩展关系类型的使用
- 更新了对其他规范的引用
- 改进了示例和说明文本