RFC 8288

Web Linking

πŸ“… published October 2017, from ietf

RFC 8288: Web Linking πŸŽ€

Okay bestie, let's get into it. This is RFC 8288, and the vibe is "how do resources on the Web relate to each other" πŸ¦‹

  • Request for Comments: 8288 πŸ’…
  • Author: M. Nottingham ✍️
  • Date: October 2017 πŸ“…
  • Category: Standards Track πŸ‘‘
  • Obsoletes: 5988 (so this one replaces RFC 5988, which is literally the whole point πŸ™ˆ)
  • ISSN: 2070-1721
  • Published by: Internet Engineering Task Force (IETF) 🌈

Abstract πŸ’–

Okay so this spec defines a model for how resources on the Web are related to each other (those are called "links") and what kind of relationship it is (those are called "link relation types") ✨

It also defines how these links get written into HTTP headers, using the Link header field πŸŽ€

Status of This Memo 🌸

This is an Internet Standards Track document. It's an official IETF product, which means it represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG) πŸ‘‘ If you want more info on what Internet Standards are, check out Section 2 of RFC 7841 πŸ’…

For the current status, any errata, and how to send feedback, head to https://www.rfc-editor.org/info/rfc8288 πŸ”—

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ’œ

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info), as in effect on the date this document was published. Please read these carefully, because they spell out your rights and restrictions for this document. Code Components pulled out of this document must include the Simplified BSD License text described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes 🫢

This document might contain material from IETF Documents or IETF Contributions that were published or made publicly available before November 10, 2008. The people controlling the copyright in some of that material might not have given the IETF Trust permission to allow modifications outside the IETF Standards Process. So unless you get an adequate license from whoever controls the copyright in those materials, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process. The exceptions are formatting it for publication as an RFC or translating it into languages other than English 🌷


Table of Contents πŸ“š

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
     1.1.  Notational Conventions  . . . . . . . . . . . . . . . . .   4
     1.2.  Conformance and Error Handling  . . . . . . . . . . . . .   4
   2.  Links . . . . . . . . . . . . . . . . . . . . . . . . . . . .   6
     2.1.  Link Relation Types . . . . . . . . . . . . . . . . . . .   6
       2.1.1.  Registered Relation Types . . . . . . . . . . . . . .   6
       2.1.2.  Extension Relation Types  . . . . . . . . . . . . . .   8
     2.2.  Target Attributes . . . . . . . . . . . . . . . . . . . .   9
   3.  Link Serialisation in HTTP Headers  . . . . . . . . . . . . .   9
     3.1.  Link Target . . . . . . . . . . . . . . . . . . . . . . .  10
     3.2.  Link Context  . . . . . . . . . . . . . . . . . . . . . .  10
     3.3.  Relation Type . . . . . . . . . . . . . . . . . . . . . .  11
     3.4.  Target Attributes . . . . . . . . . . . . . . . . . . . .  11
       3.4.1.  Serialisation-Defined Attributes  . . . . . . . . . .  11
       3.4.2.  Extension Attributes  . . . . . . . . . . . . . . . .  13
     3.5.  Link Header Field Examples  . . . . . . . . . . . . . . .  13
   4.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  14
     4.1.  Link HTTP Header Field Registration . . . . . . . . . . .  14
     4.2.  Link Relation Type Registry . . . . . . . . . . . . . . .  14
     4.3.  Link Relation Application Data Registry . . . . . . . . .  15
   5.  Security Considerations . . . . . . . . . . . . . . . . . . .  15
   6.  Internationalisation Considerations . . . . . . . . . . . . .  16
   7.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  16
     7.1.  Normative References  . . . . . . . . . . . . . . . . . .  16
     7.2.  Informative References  . . . . . . . . . . . . . . . . .  17
   Appendix A.  Notes on Other Link Serialisations . . . . . . . . .  19
     A.1.  Link Serialisation in HTML  . . . . . . . . . . . . . . .  19
     A.2.  Link Serialisation in Atom  . . . . . . . . . . . . . . .  19
   Appendix B.  Algorithms for Parsing Link Header Fields  . . . . .  20
     B.1.  Parsing a Header Set for Links  . . . . . . . . . . . . .  20
     B.2.  Parsing a Link Field Value  . . . . . . . . . . . . . . .  21
     B.3.  Parsing Parameters  . . . . . . . . . . . . . . . . . . .  22
     B.4.  Parsing a Quoted String . . . . . . . . . . . . . . . . .  23
   Appendix C.  Changes from RFC 5988  . . . . . . . . . . . . . . .  24
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  24

1. Introduction 🌸

Same energy as the abstract, just with more detail: this spec defines a model for the relationships between resources on the Web ("links") and the type of those relationships ("link relation types") πŸ’–

HTML [W3C.REC-html5-20141028] and Atom [RFC4287] both already have well-defined ideas about linking. Section 2 takes those ideas and turns them into one framework that covers linking in those formats and (potentially) other places too πŸ¦‹

Then Section 3 defines an HTTP header field for passing these links around πŸŽ€

1.1. Notational Conventions ✨

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, just like they do here πŸ’…

This document uses the Augmented Backus-Naur Form (ABNF) [RFC5234] notation from [RFC7230], including the #rule construct. It explicitly pulls in these rules from that spec: quoted-string, token, SP (space), BWS (bad whitespace), OWS (optional whitespace), RWS (required whitespace), LOALPHA, and DIGIT 🫢

It also includes these rules:

  • URI and URI-Reference from [RFC3986],
  • type-name and subtype-name from [RFC6838],
  • media-query-list from [W3C.REC-css3-mediaqueries-20120619], and
  • Language-Tag from [RFC5646].

1.2. Conformance and Error Handling 🧚

The conformance and error handling requirements that are highlighted in [RFC7230], Section 2.5 apply to this document too 🌈

Here's the core idea. In this spec, a link is a typed connection between two resources, and it's made up of:

  • a link context,
  • a link relation type (Section 2.1),
  • a link target, and
  • optionally, target attributes (Section 2.2).

You can read a link as a statement like "link context has a link relation type resource at link target, which has target attributes" πŸ’œ

For example, https://www.example.com/ has a "canonical" resource at https://example.com, which has a "type" of "text/html" πŸ“

Link contexts and link targets are both Internationalized Resource Identifiers (IRIs) [RFC3987]. However, in the common case the link context is also a URI [RFC3986], because lots of protocols (HTTP included) can't dereference IRIs. Likewise, the link target sometimes gets converted to a URI (see [RFC3987], Section 3.1) for serialisations that don't support IRIs, like the Link header field defined in Section 3 ✨

This spec doesn't put any limits on how many links there can be. There can be multiple links to and from a particular target, and multiple links of the same or different types between a given context and target. The relative ordering of links in a particular serialisation, or across serialisations (for example, the Link header field versus in-content links), isn't specified or significant in this spec. Applications that want ordering to matter are free to make it matter 🌷

Links live inside link serialisations. Those are the "bytes on the wire," and they can show up in all sorts of forms. For example, Atom [RFC4287] and HTML [W3C.REC-html5-20141028] both defined serializations of links for their own formats, and Section 3 defines how to serialise links in HTTP header fields πŸŽ€

This spec doesn't define one general syntax for links across every serialisation, and it doesn't require any particular context for a given link. Instead, serialisations of links are expected to specify both of those aspects πŸ’…

Last but not least, links get used by link applications. Usually an application defines the link relation type(s) it uses, plus the serialisation(s) those links might appear in. For example, the "Web browsing" application looks for the "stylesheet" link relation type in the HTML link serialisation (and optionally in the Link header field). Meanwhile, the "AtomPub" application uses the "edit" and "edit-media" link relations in the Atom serialisation πŸ‘‘

In the simplest case, a link relation type tells you the semantics of a link. For example, a link with the relation type "copyright" means the current link context has a copyright resource at the link target 🌸

Relation types can also say that the target resource has particular attributes or exhibits particular behaviours. For example, a "service" link implies the link target can be used as part of a defined protocol (in this case, a service description) πŸ¦‹

Relation types aren't the same thing as media types [RFC2046]. They don't tell you the format of the representation you get when you dereference the link. They only describe how the current context is related to another resource 🧚

Relation types SHOULD NOT infer any additional semantics based on whether another link relation type is present or absent, or based on its own cardinality of occurrence. The one exception is the combination of the "alternate" and "stylesheet" registered relation types, which has special meaning in HTML for historical reasons πŸ™ˆ

There are two kinds of relation types: registered and extension ✨

2.1.1. Registered Relation Types πŸŽ€

Well-defined relation types can be registered as tokens, for convenience and/or to encourage reuse by other applications. You do that using the procedure in Section 2.1.1.1 🫢

Registered relation type names MUST conform to the reg-rel-type rule (see Section 3.3), and MUST be compared character by character in a case-insensitive way. They SHOULD be appropriate to how specific the relation type is. In other words, if the semantics are really specific to one application, the name should reflect that, so the more general names stay available for less-specific use πŸ’…

Registered relation types MUST NOT constrain the media type of the link context, and MUST NOT constrain the available representation media types of the link target. They can, however, specify the behaviours and properties of the target resource (for example, allowable HTTP methods, and request and response media types that are required be supported) 🌈

Historically, registered relation types have been identified with a URI [RFC3986] by putting an application-defined base URI in front of their names (for example, see Appendix A.2). This practice is NOT RECOMMENDED, because the resulting strings won't be considered equivalent to the registered relation types by other applications. Applications that do use such URIs internally MUST NOT use them in link serialisations that don't explicitly accommodate them 😭

okay so, here's how you actually get a relation type into the registry πŸ“‹βœ¨ The "Link Relations" registry lives at <https://www.iana.org/assignments/link-relations/>. You can request a registration by following the instructions there, or by emailing the <link-relations@ietf.org> mailing list πŸ’Œ.

Every registration request has to include at least this info πŸ“:

  • Relation Name: The name of the relation type
  • Description: A short English description of what the type means. It SHOULD be explained in terms of the relationship between the link context and the link target πŸ”₯
  • Reference: A reference to the document that specifies the relation type, ideally with a URI where people can grab a copy of it πŸ“„. Pointing to the relevant section(s) is also a nice touch, but it's not required.

The expert(s) can add extra fields to the registry if they want 🧚.

The general rules for registered relation types are in Section 2.1.1, so go check those out πŸ’œ.

Registrations MUST reference a freely available, stable specification. No vibes-only registrations, bestie 🚫.

Also, relation types can be registered by third parties (including the expert(s)) if the expert(s) decide that an unregistered relation type is already widely deployed and probably won't get registered in a timely manner otherwise 🌈. These registrations still have to follow all the requirements, including referencing a specification.

2.1.1.2. Registration Request Processing

Relation types get registered under the Specification Required policy (see Section 4.6 of [RFC8126]), which means a designated expert has to review and approve them πŸ‘‘.

The whole point of the registry is to reflect how links are actually used on the Internet 🌸. So the expert(s) should be strongly biased toward approving registrations, unless they're abusive, frivolous, not likely to be used on the Internet, or actively harmful to the Internet and/or the Web. Being aesthetically displeasing or architecturally dubious doesn't count as harmful, so don't come for people over that πŸ™ˆ. As Section 2.1.1 says, the expert(s) can also refuse names that are too general for the proposed application πŸ™…β€β™€οΈ.

The expert(s) will clearly call out any issues that lead to a refusal πŸ“. They can give advice about the semantics of a proposed relation type, but if that advice doesn't block registration, it should be explicitly stated as much 🫢.

When a request gets approved, the expert(s) will tell IANA, and then the registration gets processed ✨. The IESG is the final arbiter of any objection, so that's the last word πŸ‘‘.

2.1.2. Extension Relation Types

Applications that don't want to register a relation type can use an extension relation type instead πŸ¦‹. This is a URI [RFC3986] that uniquely identifies the relation type. The URI can point to a resource that defines what the relation type means, but clients SHOULD NOT automatically access that resource, so they don't overburden its server 😭.

The URI used for an extension relation type SHOULD be under the control of the person or party defining it, or be delegated to them πŸ’….

When extension relation types are compared, they MUST be compared as strings (after converting them to URIs if they're serialised in a different format), case-insensitively, character by character πŸ”. Because of that, all-lowercase URIs SHOULD be used for extension relations πŸ“.

Also, even though extension relation types have to be URIs, a serialisation of links can say they're expressed in another form, as long as they can be converted to URIs 🧚.

2.2. Target Attributes

Target attributes are a list of key/value pairs that describe the link or its target, like a media type hint πŸŽ€.

They can be defined by individual link relation types and by link serialisations, both πŸ’œ.

This specification doesn't try to coordinate the names of target attributes, their cardinality, or how they're used πŸ€·β€β™€οΈ. People creating and maintaining serialisations SHOULD coordinate their target attributes so they don't clash in semantics or syntax, and they MAY define their own registries of target attributes 🌈.

The names of target attributes SHOULD conform to the token rule, but SHOULD NOT include any of the characters "%", "'", or "*", so they stay portable across serialisations πŸ¦‹. They MUST be compared case-insensitively too ✨.

Target attribute definitions SHOULD specify:

  • How their values are serialised into Unicode (or a subset of it), to maximise their chances of being portable across link serialisations 🫢.
  • The semantics and error handling when a target attribute shows up more than once on a given link πŸ™ˆ.

This specification does define target attributes for use in the Link HTTP header field, which you'll find in Section 3.4 πŸ‘‘.

The Link header field is how you serialise one or more links into HTTP headers πŸ’Œ.

The ABNF for the field value is:

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

Here's the tea β˜•: any link-param can be generated with its value in either token or quoted-string form, so recipients MUST be able to parse both forms πŸ’–. In other words, these parameters are equivalent:

x=y
x="y"

Earlier definitions of the Link header didn't explicitly equate the token and quoted-string forms. The title parameter was always quoted, and the hreflang parameter was always a token 🧚. Senders who want to maximize interoperability should send them in those forms 🌸.

Individual link-params specify their syntax in terms of the value after any necessary unquoting (as per [RFC7230], Section 3.2.6) πŸ”₯.

This specification establishes the link-params "rel", "anchor", and "rev" (which are part of the general link model), plus "hreflang", "media", "title", "title*", and "type" (which are target attributes defined by the serialisation) πŸ’….

Each link-value conveys one target IRI as a URI-Reference (after conversion to one, if necessary; see [RFC3987], Section 3.1), wrapped in angle brackets ("<>") πŸ¦‹. If the URI-Reference is relative, parsers MUST resolve it as per [RFC3986], Section 5. Also, any base IRI appearing in the message's content is not applied πŸ™…β€β™€οΈ.

By default, the context of a link conveyed in the Link header field is the URL of the representation it's associated with, as defined in [RFC7231], Section 3.1.4.1, and it's serialised as a URI πŸ“.

When it's present, the anchor parameter overrides this with another URI, like a fragment of this resource or a third resource (i.e., when the anchor value is an absolute URI) 🧚. If the anchor parameter's value is a relative URI, parsers MUST resolve it as per [RFC3986], Section 5. Any base URI from the body's content is not applied either πŸ’œ.

The ABNF for the "anchor" parameter's value is:

URI-Reference ; Section 4.1 of [RFC3986]

Link applications can choose to ignore links with an anchor parameter πŸ€·β€β™€οΈ. For example, the application might not allow the link context to be assigned to a different resource. In cases like that, the entire link is to be ignored, so link applications MUST NOT process the link without applying the anchor 🚫.

Also, depending on the HTTP status code and response headers, the link context might be "anonymous" (i.e., no link context is available). For example, that's the case on a 404 response to a GET request 😭.

3.3. Relation Type

The relation type of a link conveyed in the Link header field is carried in the "rel" parameter's value πŸŽ€. The rel parameter MUST be present, but it MUST NOT appear more than once in a given link-value. Occurrences after the first MUST be ignored by parsers πŸ’….

The rel parameter can, however, contain multiple link relation types 🌈. When it does, it establishes multiple links that share the same context, target, and target attributes ✨.

The "rev" parameter used to indicate that the relationship's semantics went in the reverse direction. So a link from A to B with REL="X" expresses the same relationship as a link from B to A with REV="X" πŸ”„. The rev parameter is deprecated by this specification, because it often confuses authors and readers. In most cases, a separate relation type is the better move πŸ™ˆ.

The ABNF for the rel and rev parameters' values is:

relation-type *( 1*SP relation-type )

where:

relation-type  = reg-rel-type / ext-rel-type
reg-rel-type   = LOALPHA *( LOALPHA / DIGIT / "." / "-" )
ext-rel-type   = URI ; Section 3 of [RFC3986]

Extension relation types are REQUIRED to be absolute URIs in Link header fields πŸ’–. They MUST be quoted when they contain characters that aren't allowed in tokens, like a semicolon (";") or comma (","), because those characters are delimiters in the header field itself 🚨.

3.4. Target Attributes

The Link header field defines several target attributes specific to this serialisation, and it also allows extension target attributes 🌸. Target attributes are serialised in the Link header field as parameters. For their syntax, see [RFC7231], Section 3.1.1.1 🧚.

3.4.1. Serialisation-Defined Attributes

okay so five link-params, hreflang, media, title, title*, and type, can be translated into serialisation-defined target attributes for the link πŸ’…

The hreflang attribute is a hint about what language the result of dereferencing the link should be 🌸 It's only a hint, though, ngl. For example, it doesn't override the Content-Language header field of an HTTP response you get by actually following the link. If there are multiple hreflang attributes on one link-value, that means the resource has multiple languages available 🌈

The ABNF for the hreflang parameter's value is:

Language-Tag

The media attribute tells you the intended destination medium (or media) for style information (see [W3C.REC-html5-20141028], Section 4.2.4) πŸŽ€ Its value MUST be quoted if it contains a semicolon (";") or comma (","). There MUST NOT be more than one media attribute in a link-value. Any occurrences after the first MUST be ignored by parsers πŸ™ˆ

The ABNF for the media parameter's value is:

media-query-list

The title attribute labels the destination so it can work as a human-readable identifier, like a menu entry, in the language given by the Content-Language header field (if it's there) πŸ’– The title attribute MUST NOT appear more than once in a given link. Occurrences after the first MUST be ignored by parsers.

The title* link-param lets you encode this attribute in a different character set and/or include language information, as per [RFC8187] πŸ¦‹ The title* link-param MUST NOT appear more than once in a given link-value. Occurrences after the first MUST be ignored by parsers. If the attribute doesn't contain language information, its language comes from the Content-Language header field (when it's present).

If both the title and title* link-params show up in a link, applications SHOULD use the value of title* for the title attribute ✨

The type attribute is a hint about what the media type of the result of dereferencing the link should be. Same energy as hreflang: it's only a hint, and it doesn't override the Content-Type header field of an HTTP response you get by actually following the link πŸ’œ The type attribute MUST NOT appear more than once in a given link-value. Occurrences after the first MUST be ignored by parsers.

The ABNF for the type parameter's value is:

type-name "/" subtype-name ; see Section 4.2 of [RFC6838]

3.4.2. Extension Attributes

Any other link-params are link-extensions, and they count as target attributes 🧚

Target attributes like these MAY be defined to use the encoding in [RFC8187], for example "example" and "example*" πŸ“ When both forms are present, they SHOULD be considered the same target attribute. Applications SHOULD use the value of the name ending in * (after [RFC8187] decoding), but they MAY fall back to the other value if there's an error decoding it, or if they don't support decoding at all πŸ’…


Okay, time for the fun part, bestie πŸŽ€ Here's a basic one:

Link: <http://example.com/TheBook/chapter2>; rel="previous";
      title="previous chapter"

This means "chapter2" is the previous page in a logical navigation path πŸ“–

Similarly, this one:

Link: </>; rel="http://example.net/foo"

says the root resource ("/") is related to this resource through the extension relation type "http://example.net/foo" 🌸

This link:

Link: </terms>; rel="copyright"; anchor="#foo"

tells you the linked copyright terms only apply to the part of the document marked by the (media type-specific) fragment identifier "foo" πŸ”₯

Next up is a Link header field with multiple links, plus the [RFC8187] encoding for non-ASCII characters and language info 🌈

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

Both titles are UTF-8 encoded, both are in German ("de"), and the second link has the Unicode code point U+00E4 ("LATIN SMALL LETTER A WITH DIAERESIS") in it. Iconic πŸ‡©πŸ‡ͺ✨

Note that link-values can carry multiple links between the same link target and link context. For example:

Link: <http://example.org/>;
      rel="start http://example.net/relation/other"

Here, the link to "http://example.org/" has the registered relation type "start" and the extension relation type "http://example.net/relation/other" πŸ‘‘

And finally, this header field:

Link: <https://example.org/>; rel="start",
      <https://example.org/index>; rel="index"

is equivalent to these two:

Link: <https://example.org/>; rel="start"
Link: <https://example.org/index>; rel="index"

Two links, one header, or two headers, all the same thing πŸ¦‹


4. IANA Considerations 🌷

This specification updates the "Message Headers" registry entry for "Link" in HTTP [RFC3864] so it points to this document πŸ’Œ

Header Field Name: Link
Protocol: http
Status: standard
Reference: RFC 8288

This specification updates the registration procedures for the "Link Relation Types" registry (see Section 2.1.1.1). Also, every reference to RFC 5988 in that registry has been swapped out for a reference to this document πŸ”„

IANA will send any incoming requests about the registry to this document and, if they're defined, to the processes set up by the expert(s). Typically that just means pointing people to the registry Web page 🧁

Note that the expert(s) is allowed (as per Section 2.1.1.1) to define additional fields to be collected in the registry πŸ’…

Per this specification, IANA has removed the "Link Relation Application Data" registry. It hasn't been used, and future use isn't expected, so bye bye πŸ‘‹


5. Security Considerations

🚨 Okay bestie, this section is SERIOUS, so read it carefully. Dramatic? Yes. Necessary? Also yes 😭

The content of the Link header field is not secure, private, or integrity-guaranteed. Right now, the only end-to-end way to get those properties is Transport Layer Security (TLS) with HTTP [RFC2818] πŸ”

Link applications ought to think hard about the attack vectors that open up when they automatically follow, trust, or otherwise use links pulled from HTTP header fields πŸ’€

For example, Link header fields that use the "anchor" parameter to tie a link's context to another resource can't be trusted. They're basically third-party assertions that could be wrong or malicious πŸ™ˆ Applications can reduce this risk by saying that such links should be discarded unless some relationship between the resources is established (e.g., they share the same authority) πŸ›‘οΈ

Dereferencing links has a bunch of risks, depending on the app. For instance, the Referer header [RFC7231] can leak information about the application's state (including private info) in its value 😱 Cookies [RFC6265] are another mechanism that can become an attack vector if they're used. Applications can handle these risks by carefully specifying how such mechanisms should operate πŸͺ

The Link header field makes heavy use of IRIs and URIs. See [RFC3987], Section 8 for security considerations about IRIs. See [RFC3986], Section 7 for security considerations about URIs. And see [RFC7230], Section 9 for security considerations about HTTP header fields πŸ’œ


6. Internationalisation Considerations

Link targets may need to be converted to URIs so they can be expressed in serialisations that don't support IRIs. The Link HTTP header field is one of those 🌍

The anchor parameter of the Link header field doesn't support IRIs either, so IRIs must be converted to URIs before they go in there πŸ”

Relation types are defined as URIs, not IRIs, which makes them easier to compare 🧐 They aren't expected to be shown to end users, so no need to make them pretty πŸ’…

Note that registered Relation Names are required to be lowercase ASCII letters πŸ”€


7. References

7.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC3864]  Klyne, G., Nottingham, M., and J. Mogul, "Registration
           Procedures for Message Header Fields", BCP 90, RFC 3864,
           DOI 10.17487/RFC3864, September 2004,
           <https://www.rfc-editor.org/info/rfc3864>.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, DOI 10.17487/RFC3986, January 2005,
           <https://www.rfc-editor.org/info/rfc3986>.

[RFC3987]  Duerst, M. and M. Suignard, "Internationalized Resource
           Identifiers (IRIs)", RFC 3987, DOI 10.17487/RFC3987,
           January 2005, <https://www.rfc-editor.org/info/rfc3987>.

[RFC5234]  Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
           Specifications: ABNF", STD 68, RFC 5234,
           DOI 10.17487/RFC5234, January 2008,
           <https://www.rfc-editor.org/info/rfc5234>.

[RFC5646]  Phillips, A., Ed. and M. Davis, Ed., "Tags for Identifying
           Languages", BCP 47, RFC 5646, DOI 10.17487/RFC5646,
           September 2009, <https://www.rfc-editor.org/info/rfc5646>.

[RFC6838]  Freed, N., Klensin, J., and T. Hansen, "Media Type
           Specifications and Registration Procedures", BCP 13,
           RFC 6838, DOI 10.17487/RFC6838, January 2013,
           <https://www.rfc-editor.org/info/rfc6838>.

[RFC7230]  Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
           Protocol (HTTP/1.1): Message Syntax and Routing",
           RFC 7230, DOI 10.17487/RFC7230, June 2014,
           <https://www.rfc-editor.org/info/rfc7230>.

[RFC7231]  Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
           Protocol (HTTP/1.1): Semantics and Content", RFC 7231,
           DOI 10.17487/RFC7231, June 2014,
           <https://www.rfc-editor.org/info/rfc7231>.

[RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
           Writing an IANA Considerations Section in RFCs", BCP 26,
           RFC 8126, DOI 10.17487/RFC8126, June 2017,
           <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8187]  Reschke, J., "Indicating Character Encoding and Language
           for HTTP Header Field Parameters", RFC 8187,
           DOI 10.17487/RFC8187, September 2017,
           <https://www.rfc-editor.org/info/rfc8187>.

[W3C.REC-css3-mediaqueries-20120619]
           Rivoal, F., "Media Queries", W3C Recommendation
           REC-css3-mediaqueries-20120619, June 2012,
           <http://www.w3.org/TR/2012/
           REC-css3-mediaqueries-20120619>.

7.2. Informative References πŸ“šβœ¨

[RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046, November 1996, <https://www.rfc-editor.org/info/rfc2046>.

[RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, DOI 10.17487/RFC2818, May 2000, <https://www.rfc-editor.org/info/rfc2818>.

[RFC4287] Nottingham, M., Ed. and R. Sayre, Ed., "The Atom Syndication Format", RFC 4287, DOI 10.17487/RFC4287, December 2005, <https://www.rfc-editor.org/info/rfc4287>.

[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[W3C.REC-html5-20141028] Hickson, I., Berjon, R., Faulkner, S., Leithead, T., Navara, E., O'Connor, T., and S. Pfeiffer, "HTML5", W3C Recommendation REC-html5-20141028, October 2014, <http://www.w3.org/TR/2014/REC-html5-20141028>.


Okay so header fields (Section 3) are only one way to serialise links 🧚. Other specs have come up with their own serialisations too, and they're honestly kind of iconic.

HTML is literally the OG that inspired the syntax of the Link header field πŸ‘‘, so a lot of the design decisions in this document are all about staying compatible with it 🫢.

In HTML, the link element can be mapped to links the way this spec describes, using href for the target URI and rel to convey the relation type, just like the Link header field πŸŽ€. The context of the link is the URI associated with the entire HTML document. HTML also defines a bunch of attributes on links that you can see as target attributes, including media, hreflang, type, and sizes πŸ’œ.

Section 4.8 of HTML5 [W3C.REC-html5-20141028] defines modern HTML links. That document links to the Microformats Wiki as a registry; over time, the IANA registry ought to mirror its contents and, ideally, eventually replace it (although that depends on the HTML community) πŸ“.

Surveys of existing HTML content have shown that unregistered link relation types that are not URIs are (perhaps inevitably) common πŸ’€. Consuming HTML implementations ought not consider such unregistered short links to be errors, but rather relation types with a local scope (i.e., their meaning is specific and perhaps private to that document) ✨.

Finally, the HTML specification gives a special meaning when the alternate relation types coincide with other relation types in the same link πŸ”₯. Such links ought to be serialised in the Link header field using a single list of relation-types (e.g., rel="alternate stylesheet") to preserve this relationship πŸ¦‹.

Atom [RFC4287] is a link serialisation that conveys links in the atom:link element, with the href attribute indicating the link target and the rel attribute containing the relation type 🌈. The context of the link is either a feed locator or an entry ID, depending on where it appears. Generally, feed-level links are obvious candidates for transmission as a Link header field 🫢.

When serialising an atom:link into a Link header field, it is necessary to convert link targets (if used) to URIs πŸ”₯.

Atom defines extension relation types in terms of IRIs. This specification redefines them as URIs, to simplify and reduce errors in their comparison 🧚.

Atom allows registered link relation types to be serialised as absolute URIs using a prefix, http://www.iana.org/assignments/relation/. This prefix is specific to the Atom serialisation πŸ’–.

Furthermore, link relation types are always compared in a case-sensitive fashion. Therefore, registered link relation types SHOULD be converted to their registered form (usually, lowercase) when serialised in an Atom document 😭.

Note also that while the Link header field allows multiple relations to be serialised in a single link, atom:link does not πŸ™ˆ. In this case, a single link-value may map to several atom:link elements.

As with HTML, atom:link defines some attributes that are not explicitly mirrored in the Link header field syntax, but they can also be used as link-extensions to maintain fidelity πŸ’œ.


This appendix outlines a set of non-normative algorithms: for parsing the Link header(s) out of a header set, for parsing a Link header field value, and algorithms for parsing generic parts of the field value πŸ’….

These algorithms are more permissive than the ABNF defining the syntax might suggest. The error handling embodied in them is a reasonable approach, but not one that is required. As such they are advisory only, and in cases where there is disagreement, the correct behaviour is defined by the body of this specification 🫢.

This algorithm can be used to parse the Link header fields that a HTTP header set contains. Given a header_set of (string field_name, string field_value) pairs, assuming ASCII encoding, it returns a list of link objects πŸŽ€.

  1. Let field_values be a list containing the members of header_set whose field_name is a case-insensitive match for "link".
  2. Let links be an empty list.
  3. For each field_value in field_values:
    1. Let value_links be the result of Parsing a Link Field Value (Appendix B.2) from field_value.
    2. Append each member of value_links to links.
  4. Return links.

This algorithm parses zero or more comma-separated link-values from a Link header field. Given a string field_value, assuming ASCII encoding, it returns a list of link objects πŸ“.

  1. Let links be an empty list.
  2. While field_value has content:
    1. Consume any leading OWS.
    2. If the first character is not "<", return links.
    3. Discard the first character ("<").
    4. Consume up to but not including the first ">" character or end of field_value and let the result be target_string.
    5. If the next character is not ">", return links.
    6. Discard the leading ">" character.
    7. Let link_parameters be the result of Parsing Parameters (Appendix B.3) from field_value (consuming zero or more characters of it).
    8. Let target_uri be the result of relatively resolving (as per [RFC3986], Section 5.2) target_string. Note that any base URI carried in the payload body is NOT used. πŸ™ˆ
    9. Let relations_string be the second item of the first tuple of link_parameters whose first item matches the string "rel" or the empty string ("") if it is not present.
    10. Split relations_string on RWS (removing it in the process) into a list of string relation_types.
    11. Let context_string be the second item of the first tuple of link_parameters whose first item matches the string "anchor". If it is not present, context_string is the URL of the representation carrying the Link header [RFC7231], Section 3.1.4.1, serialised as a URI. Where the URL is anonymous, context_string is null.
    12. Let context_uri be the result of relatively resolving (as per [RFC3986], Section 5.2) context_string, unless context_string is null, in which case context is null. Note that any base URI carried in the payload body is NOT used. πŸ’…
    13. Let target_attributes be an empty list.
    14. For each tuple (param_name, param_value) of link_parameters:
      1. If param_name matches "rel" or "anchor", skip this tuple.
      2. If param_name matches "media", "title", "title*", or "type" and target_attributes already contains a tuple whose first element matches the value of param_name, skip this tuple.
      3. Append (param_name, param_value) to target_attributes.
    15. Let star_param_names be the set of param_names in the (param_name, param_value) tuples of link_parameters where the last character of param_name is an asterisk ("*").
    16. For each star_param_name in star_param_names:
      1. Let base_param_name be star_param_name with the last character removed.
      2. If the implementation does not choose to support an internationalised form of a parameter named base_param_name for any reason (including, but not limited to, it being prohibited by the parameter's specification), remove all tuples from link_parameters whose first member is star_param_name, and skip to the next star_param_name.
      3. Remove all tuples from link_parameters whose first member is base_param_name.
      4. Change the first member of all tuples in link_parameters whose first member is star_param_name to base_param_name.
    17. For each relation_type in relation_types:
      1. Case-normalise relation_type to lowercase.
      2. Append a link object to links with the target target_uri, relation type of relation_type, context of context_uri, and target attributes target_attributes.
  3. Return links.

B.3. Parsing Parameters πŸ¦‹

This algorithm parses the parameters from a header field value. Given input, an ASCII string, it returns a list of (string parameter_name, string parameter_value) tuples that it contains. input is modified to remove the parsed parameters ✨.

  1. Let parameters be an empty list.
  2. While input has content:
    1. Consume any leading OWS.
    2. If the first character is not ";", return parameters.
    3. Discard the leading ";" character.
    4. Consume any leading OWS.
    5. Consume up to but not including the first BWS, "=", ";", or "," character, or up to the end of input, and let the result be parameter_name.
    6. Consume any leading BWS.
    7. If the next character is "=":
      1. Discard the leading "=" character.
      2. Consume any leading BWS.
      3. If the next character is DQUOTE, let parameter_value be the result of Parsing a Quoted String (Appendix B.4) from input (consuming zero or more characters of it).
      4. Else, consume the contents up to but not including the first ";" or "," character, or up to the end of input, and let the results be parameter_value.
      5. If the last character of parameter_name is an asterisk ("*"), decode parameter_value according to [RFC8187]. Continue processing input if an unrecoverable error is encountered. 🌈
    8. Else:
      1. Let parameter_value be an empty string.
    9. Case-normalise parameter_name to lowercase.
    10. Append (parameter_name, parameter_value) to parameters.
    11. Consume any leading OWS.
    12. If the next character is "," or the end of input, stop processing input and return parameters. πŸ’–

B.4. Parsing a Quoted String ✨

okay so this algorithm is how you parse a quoted string, following [RFC7230], Section 3.2.6 πŸŽ€ it takes an ASCII string as input and hands back the unquoted version. bestie, the input gets modified too, since the parsed part gets removed from it πŸ’…

  1. Let output be an empty string.
  2. If the first character of input is not DQUOTE, return output.
  3. Discard the first character.
  4. While input has content:
    1. If the first character is a backslash ("\"):
      1. Discard the first character.
      2. If there is no more input, return output.
      3. Else, consume the first character and append it to output.
    2. Else, if the first character is DQUOTE, discard it and return output.
    3. Else, consume the first character and append it to output.
  5. Return output.

Appendix C. Changes from RFC 5988 πŸ¦‹

this one is the glow-up glow-down recap 🌸 this spec has the following differences from its predecessor, RFC 5988:

  • The initial relation type registrations were removed, since they've already been registered by RFC 5988.
  • The introduction has been shortened.
  • The "Link Relation Application Data" registry has been removed.
  • Incorporated errata.
  • Updated references.
  • Link cardinality was clarified.
  • Terminology was changed from "target IRI" and "context IRI" to "link target" and "link context", respectively.
  • Made assigning a URI to registered relation types serialisation specific.
  • Removed misleading statement that the Link header field is semantically equivalent to HTML and Atom links.
  • More carefully defined and used "link serialisations" and "link applications."
  • Clarified the cardinality of target attributes (generically and for "type").
  • Corrected the default link context for the Link header field, to be dependent upon the identity of the representation (as per RFC 7231).
  • Defined a suggested parsing algorithm for the Link header.
  • The value space of target attributes and their definition has been specified.
  • The ABNF has been updated to be compatible with [RFC7230]. In particular, whitespace is now explicit.
  • Some parameters on the HTTP header field can now appear as a token.
  • Parameters on the HTTP header can now be valueless.
  • Handling of quoted strings is now defined by [RFC7230].
  • The "type" header field parameter now needs to be quoted (as "token" does not allow "/").

Author's Address 🫢

Mark Nottingham

Email: mnot@mnot.net URI: https://www.mnot.net/

πŸ“¦ where this page comes from