跳到主要内容

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​

本规范定义了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节中强调的关于一致性和错误处理的要求适用于本文档.


在本规范中,链接是两个资源之间的类型化连接,由以下部分组成:

  • 链接上下文 (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"链接关系.

在最简单的情况下,链接关系类型标识链接的语义.例如,具有关系类型"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)以不区分大小写的方式进行比较.


Link实体头字段提供了一种在HTTP头中序列化一个或多个链接的方法.它在语义上等同于HTML的<link>元素.

Link头字段语法​

Link       = #link-value
link-value = "`&lt;" URI-Reference ">`" *( OWS ";" OWS link-param )
link-param = token BWS [ "=" BWS ( token / quoted-string ) ]

每个link-value传达一个链接.链接目标由尖括号(&lt; 和 >)内的URI-Reference表示.

默认情况下,链接的上下文是表示它出现的消息的有效请求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)影响其在特定应用程序中的使用.

例如:

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: `&lt;/terms>`; rel="copyright"; anchor="#foo"

指示标识符为"foo"的资源的版权资源可以在/terms找到.

多个链接可以在单个Link头字段中传达:

Link: `&lt;/TheBook/chapter2>`; rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
`&lt;/TheBook/chapter4>`; rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel

这里,两个链接都使用国际化的title参数.

也可以使用多个Link头字段:

Link: `&lt;/TheBook/chapter2>`; rel="previous"
Link: `&lt;/TheBook/chapter4>`; rel="next"

4. IANA Considerations​

本规范更新了"Message Headers"注册表中"Link"头字段的定义.

头字段名称: Link

适用协议: http

状态: 标准

作者/变更控制者: IETF

规范文档: 本规范(第3节)

本规范建立了"Link Relation Types"注册表,位于 ````https://www.iana.org/assignments/link-relations/\````.

注册请求应包括:

  • 关系名称: 关系类型的名称
  • 描述: 类型语义的简短英文描述
  • 参考: 指定链接关系类型的文档的参考

本规范建立了"Link Relation Application Data"注册表.


Appendices​

HTML [W3C.REC-html5-20141028]定义了<link>元素用于传达链接.例如:

`<link rel="stylesheet" href="/style.css" type="text/css">`

HTML链接与本规范中定义的链接模型之间的对应关系如下:

  • 链接上下文是包含链接元素的文档的URI
  • 链接关系类型由"rel"属性的值标识
  • 链接目标由"href"属性的值标识
  • 目标属性由其他属性(如"type","media"等)表示

Atom [RFC4287]定义了一个链接元素,可以出现在feed和entry中.例如:

<link rel="alternate" type="text/html" 
href="http://example.org/"/>

Atom链接与本规范中定义的链接模型之间的对应关系如下:

  • 链接上下文是包含链接元素的feed或entry的URI
  • 链接关系类型由"rel"属性的值标识
  • 链接目标由"href"属性的值标识
  • 目标属性由其他属性(如"type","hreflang"等)表示

本附录定义了解析Link头字段的算法.这些算法是规范性的.

给定一组HTTP头字段headers:

  1. 让links为空列表
  2. 对于headers中的每个字段field,其字段名为"Link"(不区分大小写):
    • 让field_value为field的字段值
    • 让field_links为解析field_value的结果(使用B.2节中的算法)
    • 将field_links中的每个链接添加到links
  3. 返回links

该算法从一个 Link 头字段值中解析零个或多个以逗号分隔的 link-value. 给定 ASCII 字符串 field_value, 返回 link object 列表:

  1. 令 links 为空列表.
  2. 当 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.
  3. 返回 links.

B.3. Parsing Parameters (解析参数)​

该算法从头字段值中解析参数. 给定 ASCII 字符串 input, 返回其中包含的 (parameter_name, parameter_value) 元组列表, 并从 input 中移除已经解析的字符:

  1. 令 parameters 为空列表.
  2. 当 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 中移除已解析字符:

  1. 令 output 为空字符串.
  2. 如果 input 的第一个字符不是 DQUOTE, 返回 output.
  3. 丢弃第一个字符.
  4. 当 input 仍有内容时:
    • 如果第一个字符是反斜杠 \, 丢弃该字符. 如果没有更多输入, 返回 output; 否则消耗第一个字符并追加到 output.
    • 否则, 如果第一个字符是 DQUOTE, 丢弃该字符并返回 output.
    • 否则, 消耗第一个字符并追加到 output.
  5. 返回 output.

Appendix C. Changes from RFC 5988 (与RFC 5988的变化)​

本规范与RFC 5988相比的主要变化包括:

  • 澄清了链接上下文和链接目标的定义
  • 更新了注册程序以使用RFC 8126
  • 添加了解析算法(附录B)
  • 澄清了扩展关系类型的使用
  • 更新了对其他规范的引用
  • 改进了示例和说明文本