-
-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
spec: allow to select rel, hreflang and media types (#54)
* spec: allow to select rel and media types * Update spec/vulcain.md Co-authored-by: Grégoire Hébert <[email protected]> * Update spec/vulcain.md Co-authored-by: André R. <[email protected]> * Update spec/vulcain.md Co-authored-by: André R. <[email protected]> * spec: clarify the content negotiation part * spec: better Co-authored-by: Grégoire Hébert <[email protected]> Co-authored-by: André R. <[email protected]>
- Loading branch information
1 parent
2fdc394
commit 3424c12
Showing
1 changed file
with
240 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,13 @@ | |
title = "The Vulcain Protocol" | ||
area = "Internet" | ||
workgroup = "Network Working Group" | ||
submissiontype = "IETF" | ||
|
||
[seriesInfo] | ||
name = "Internet-Draft" | ||
value = "draft-dunglas-vulcain-00" | ||
value = "draft-dunglas-vulcain-01" | ||
stream = "IETF" | ||
status = "informational" | ||
status = "standard" | ||
|
||
[[author]] | ||
initials="K." | ||
|
@@ -19,9 +20,8 @@ organization = "Les-Tilleuls.coop" | |
email = "[email protected]" | ||
[author.address.postal] | ||
city = "Lille" | ||
street = "2 rue Hegel" | ||
code = "59000" | ||
postalline= ["Bâtiment Canal"] | ||
street = "82 rue Winston Churchill" | ||
code = "59160" | ||
country = "France" | ||
%%% | ||
|
||
|
@@ -57,16 +57,87 @@ and [JSON:API](https://jsonapi.org/) allow the use of Web Linking [@!RFC5988] to | |
references between resources. | ||
|
||
The `Preload` HTTP header allows the client to ask the server to transmit resources linked to the | ||
main resource it will need as soon as possible. To do so, the `Preload` header `MUST` contain a | ||
selector [#selectors] referencing links to resources that `SHOULD` be preloaded. | ||
main resource it will need as soon as possible. | ||
|
||
The server `MUST` recursively follow links referenced by the selector. When a selector traverses | ||
`Preload` is a List Structured Header [@!I-D.ietf-httpbis-header-structure]. Its values `MUST` be | ||
Strings (Section 3.3.3 of [@!I-D.ietf-httpbis-header-structure]). Its ABNF is: | ||
|
||
~~~ abnf | ||
Preload = sf-list | ||
sf-item = sf-string | ||
~~~ | ||
|
||
Its values are selectors (#selectors) matching links to resources that `SHOULD` be preloaded. If a | ||
value is an empty String, then all links of the current documents are matched. | ||
|
||
The server `MUST` recursively follow links matched by the selector. When a selector traverses | ||
several resources, all the traversed resources `SHOULD` be sent to the client. If several links | ||
referencing the same resource are selected, this resource `MUST` be sent at most once. | ||
|
||
The server `MAY` limit the number resources that it sends in response to one request. | ||
|
||
Multiple selectors can be sent by passing multiple `Preload` HTTP headers. | ||
Example: | ||
|
||
~~~ http | ||
Preload: "/member/*/author", "/member/*/comments" | ||
~~~ | ||
|
||
The following optional parameters are defined: | ||
|
||
* A Parameter whose name is `rel`, and whose value is a String (Section 3.3.3 | ||
of [@!I-D.ietf-httpbis-header-structure]) or a Token (Section 3.3.4 of | ||
[@!I-D.ietf-httpbis-header-structure]), conveying the expected relation type of the selected | ||
links. | ||
|
||
* A Parameter whose name is `hreflang`, and whose value is a String (Section 3.3.3 of | ||
[@!I-D.ietf-httpbis-header-structure]), conveying the expected language of the selected links. | ||
|
||
* A Parameter whose name is `type`, and whose value is a String (Section 3.3.3 of | ||
[@!I-D.ietf-httpbis-header-structure]), conveying the expected media type of the selected links. | ||
|
||
The `rel` parameter contains a relation type as defined in [@!RFC5988]. If this parameter is | ||
provided, the server `SHOULD` preload only relations matched by the provided selector and having | ||
this type. | ||
|
||
The `hreflang` parameter contains a language as defined in [@!RFC5988]. If this parameter is | ||
provided, the server `SHOULD` preload only relations matched by the provided selector and in this | ||
language. When possible (for instance, when doing a HTTP/2 Server Push), the server `SHOULD` set | ||
the `Accept-Language` request header to this value. If the `hreflang` parameter isn't provided but | ||
the server is able to guess the expected language of the relation using other mechanisms (such as | ||
the `hreflang` attribute defined by the Atom format for the `atom:link` element, [@RFC4287] Section | ||
4.2.7.4), then the `Accept-Language` request header `SHOULD` be set to the guessed value. | ||
|
||
The `type` parameter contains a media type as defined in [@!RFC5988]. If this parameter is provided, | ||
the server `SHOULD` preload only relations matched by the provided selector and having this media | ||
type. When possible (for instance, when doing a HTTP/2 Server Push), the server `SHOULD` set the | ||
`Accept` request header to this value. If the `type` parameter isn't provided but the server is | ||
able to guess the expected media type of the relation using other mechanisms (such as the `type` | ||
attribute defined by the Atom format for the `atom:link` element, [@RFC4287] Section 4.2.7.3), then | ||
the `Accept` request header `SHOULD` be set to the guessed value. | ||
|
||
If several parameters are provided for the same selector, the server `SHOULD` preload only relations | ||
matching the selector and constraints hinted by the parameters. | ||
|
||
Examples: | ||
|
||
~~~ http | ||
Preload: "/member/*/author"; hreflang="fr-FR" | ||
Preload: "/member/*/author/avatar"; type="image/webp" | ||
~~~ | ||
|
||
The server `SHOULD` preload all links matched by the `/member/*/author` selector and having a lang | ||
of `fr-FR`, as well as all links matching the `/member/*/author/avatar` selector and having a type | ||
of `image/webp`. | ||
|
||
~~~ http | ||
Preload: ""; rel=author | ||
Preload: ""; rel="https://example.com/custom-rel" | ||
~~~ | ||
|
||
The server `SHOULD` preload all links of the requested resource having the relation type `author` or | ||
`https://example.com/custom-rel`. | ||
|
||
## Preload Example | ||
|
||
Considering the following resources: | ||
|
||
|
@@ -113,7 +184,7 @@ requested one: | |
|
||
~~~ http | ||
GET /books/ HTTP/2 | ||
Preload: /member/*/author | ||
Preload: "/member/*/author" | ||
~~~ | ||
|
||
In addition to `/books`, the server `SHOULD` use HTTP/2 Server Push to push the `/books/1`, | ||
|
@@ -124,20 +195,18 @@ Server Push requests generated by the server for related resources `MUST` includ | |
selector in a `Preload` HTTP header. When requesting a pushed relation, the client `MUST` compute | ||
the remaining selector and pass it in the `Preload` header. | ||
|
||
Example: | ||
|
||
Explicit Request: | ||
|
||
~~~ http | ||
GET /books/ HTTP/2 | ||
Preload: /member/*/author | ||
Preload: "/member/*/author" | ||
~~~ | ||
|
||
Request to a relation generated by the server (for the push) and the client: | ||
|
||
~~~ http | ||
GET /books/1 HTTP/2 | ||
Preload: /author | ||
Preload: "/author" | ||
~~~ | ||
|
||
## Using Preload Link Relations | ||
|
@@ -154,11 +223,15 @@ Server Push. | |
The `Fields` HTTP header allows the client to ask the server to return only the specified fields of | ||
the requested resource, and of the preloaded related resources. | ||
|
||
The `Fields` HTTP header is a List Structured Header accepting the exact same values than the | ||
`Preload` HTTP header defined in (#preload). | ||
|
||
The `Fields` HTTP header `MUST` contain a selector (see #Selector). The server `SHOULD` return only | ||
the fields matching this selector. | ||
|
||
Multiple `Fields` HTTP headers can be passed. All fields matching at least one of these headers | ||
`MUST` be returned. Other fields of the resource `MAY` be omitted. | ||
All matched fields `MUST` be returned if they exist. Other fields of the resource `MAY` be omitted. | ||
|
||
## Fields Example | ||
|
||
Considering the following resources: | ||
|
||
|
@@ -185,9 +258,9 @@ And the following HTTP request: | |
|
||
~~~ http | ||
GET /books/1 HTTP/2 | ||
Preload: /author | ||
Fields: /author/familyName | ||
Fields: /genre | ||
Preload: "/author" | ||
Fields: "/author/familyName" | ||
Fields: "/genre" | ||
~~~ | ||
|
||
The server must return a response containing the following JSON document: | ||
|
@@ -217,14 +290,14 @@ Explicit Request: | |
|
||
~~~ http | ||
GET /books/ HTTP/2 | ||
Fields: /member/*/author | ||
Fields: "/member/*/author" | ||
~~~ | ||
|
||
Request to a relation generated by the server (for the push) and the client: | ||
|
||
~~~ http | ||
GET /books/1 HTTP/2 | ||
Fields: /author | ||
Fields: "/author" | ||
~~~ | ||
|
||
# Selectors | ||
|
@@ -243,7 +316,7 @@ server to use a specific selector format: | |
GET /books/1 HTTP/2 | ||
Accept: text/xml | ||
Prefer: selector=css | ||
Fields: brand > name | ||
Fields: "brand > name" | ||
~~~ | ||
|
||
If no explicit preferences have been passed, the server `MUST` assume that the selector format is | ||
|
@@ -295,31 +368,59 @@ complexity of requests executed by the server. | |
# Query Parameters | ||
|
||
Another option available to clients is to utilize Request URI query-string parameters to pass | ||
preload and fields selectors. The `preload` and `query` parameters `MAY` be used to pass selectors | ||
corresponding respectively to the `Preload` and `Fields` HTTP headers. To pass multiple selectors, | ||
parameters can be passed multiple times. | ||
preload and fields selectors. | ||
|
||
The `preload` and `query` parameters `MAY` be used to pass selectors corresponding respectively to | ||
the `Preload` and `Fields` HTTP headers. Valid values for these query parameters are exactly the | ||
same than the ones defined of the `Preload` and `Fields` HTTP headers. | ||
|
||
Example: `/books/1?fields=/title&fields=/author&preload=/author` | ||
In conformance with the Section 3.4 of the URI RFC [@!RFC3986], values of query parameters `MUST` be | ||
percent-encoded. To pass multiple selectors, parameters can be passed multiple times. | ||
|
||
Example: `/books/1?fields=%22%2Ftitle%22&fields=%22%2Fauthor%22&preload=%22%2Fauthor%22` | ||
|
||
When using query parameters, the server `MUST` pass the remaining part of the selector as parameter | ||
of the generated link. | ||
|
||
`Preload` and `Fields` HTTP headers aren't [CORS safe-listed | ||
request-headers](https://fetch.spec.whatwg.org/#cors-safelisted-request-header). Query parameters, | ||
on the other hand, allow to send cross-site requests that don't trigger preflight requests. Also, | ||
query parameters don't require clients to compute the remaining part of the selector when requesting | ||
relations. | ||
|
||
However, support for query parameters can be challenging to implement by servers (links contained in | ||
served documents `MUST` be modified) and generate URLs that are hard to read for a human. | ||
|
||
Altering the URI can also have undesirable effects. | ||
|
||
For these reasons, using HTTP headers `SHOULD` be preferred. Support for query parameters is | ||
`OPTIONAL`. A server supporting query parameters `MUST` also support the corresponding HTTP headers. | ||
|
||
Example: | ||
|
||
~~~ http | ||
GET /books/?preload=/member/*/author HTTP/2 | ||
GET /books/?preload=%22%2Fmember%2F%2A%2Fauthor%22 HTTP/2 | ||
{ | ||
"member": { | ||
"/books/1?preload=/author", | ||
"/books/1?preload=/author" | ||
"/books/1?preload=%22%2Fauthor%22", | ||
"/books/1?preload=%22%2Fauthor%22" | ||
} | ||
} | ||
~~~ | ||
|
||
As altering the URI can have undesirable effects, using HTTP headers `SHOULD` be preferred. Support | ||
for query parameters is `OPTIONAL`. A server supporting query parameters `MUST` also support the | ||
corresponding HTTP headers. | ||
Example using parameters: | ||
|
||
~~~ http | ||
GET /books/?preload=%22%2Fmember%2F%2A%22%3B%20rel%3Dauthor HTTP/2 | ||
{ | ||
"member": { | ||
"/books/1?preload=%22%22%3B%20rel%3Dauthor", | ||
"/books/1?preload=%22%22%3B%20rel%3Dauthor" | ||
} | ||
} | ||
~~~ | ||
|
||
# Computing Links Server-Side | ||
|
||
|
@@ -373,4 +474,111 @@ registry defined in [@!RFC3864]. | |
|
||
A selector registry could also be added. | ||
|
||
# Implementation Status | ||
|
||
[RFC Editor Note: Please remove this entire section prior to publication as an RFC.] | ||
|
||
This section records the status of known implementations of the protocol defined by this | ||
specification at the time of posting of this Internet-Draft, and is based on a proposal described | ||
in [@RFC6982]. The description of implementations in this section is intended to assist the IETF in | ||
its decision processes in progressing drafts to RFCs. Please note that the listing of any individual | ||
implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to | ||
verify the information presented here that was supplied by IETF contributors. This is not intended | ||
as, and must not be construed to be, a catalog of available implementations or their features. | ||
Readers are advised to note that other implementations may exist. According to RFC 6982, "this will | ||
allow reviewers and working groups to assign due consideration to documents that have the benefit | ||
of running code, which may serve as evidence of valuable experimentation and feedback that have | ||
made the implemented protocols more mature. It is up to the individual working groups to use this | ||
information as they see fit." | ||
|
||
## Vulcain Gateway Server | ||
|
||
Organization responsible for the implementation: | ||
|
||
Les-Tilleuls.coop | ||
|
||
Implementation Name and Details: | ||
|
||
Vulcain.rocks, available at <https://vulcain.rocks> | ||
|
||
Brief Description: | ||
|
||
A gateway server allowing to add support for the Vulcain protocol to any existing API. It is written | ||
in Go and is optimized for performance. | ||
|
||
Level of Maturity: | ||
|
||
Beta. | ||
|
||
Coverage: | ||
|
||
All the features of the protocol as well as the extended JSON pointer selector. | ||
|
||
Version compatibility: | ||
|
||
The implementation follows the draft version 00. | ||
|
||
Licensing: | ||
|
||
All code is covered under the GNU Affero Public License version 3 or later. | ||
|
||
Implementation Experience: | ||
|
||
Used in production. | ||
|
||
Contact Information: | ||
|
||
Kévin Dunglas, [[email protected]](mailto:[email protected]) <https://vulcain.rocks> | ||
|
||
Interoperability: | ||
|
||
Reported compatible with all major browsers and server-side tools. | ||
|
||
## Helix Vulcain Filters | ||
|
||
Organization responsible for the implementation: | ||
|
||
Adobe | ||
|
||
Implementation Name and Details: | ||
|
||
Helix Vulcain Filters, available at <https://github.com/adobe/helix-vulcain-filters> | ||
|
||
Brief Description: | ||
|
||
Vulcain-like filters for OpenWhisk web actions. | ||
|
||
Level of Maturity: | ||
|
||
Stable. | ||
|
||
Coverage: | ||
|
||
HTTP headers as well as the extended JSON pointer selector. | ||
|
||
Version compatibility: | ||
|
||
The implementation follows the draft version 00. | ||
|
||
Licensing: | ||
|
||
All code is covered under the Apache License 2.0. | ||
|
||
Implementation Experience: | ||
|
||
Used in production. | ||
|
||
Contact Information: | ||
|
||
<https://www.adobe.com/about-adobe/contact.html> | ||
|
||
Interoperability: | ||
|
||
Reported compatible with all major browsers and server-side tools. | ||
|
||
# Acknowledgements | ||
|
||
The author would like to thank Evert Pot, who authored the Prefer-Push Internet-Draft from which | ||
some parts of this specification is inspired, and André R. who gave good design ideas. | ||
|
||
{backmatter} |