2017-11-16 18:15:13 +00:00
|
|
|
|
[DRAFT]
|
|
|
|
|
|
2017-11-17 00:38:05 +00:00
|
|
|
|
Introduction:
|
|
|
|
|
|
|
|
|
|
This document is a draft proposal for Shard Brotli dictionaries in the fetch spec
|
|
|
|
|
(https://fetch.spec.whatwg.org/).
|
|
|
|
|
|
|
|
|
|
The goal is to add support for custom dictionaries for Brotli. A dictionary is used
|
|
|
|
|
to improve compression. A client can download a dictionary from a server and then
|
|
|
|
|
use it to decompress resources compressed with this dictionary.
|
|
|
|
|
|
|
|
|
|
This document specifies how the client and server negotiate the dictionary over HTTP.
|
|
|
|
|
A high level overview is as follows: The server adds an HTTP header to the response
|
|
|
|
|
with a URL of the dictionary. The browser downloads the dictionary from the URL and
|
|
|
|
|
then caches it so it can be reused. The server also adds a checksum to an HTTP header
|
|
|
|
|
which the client uses to verify the dictionary. Caching, CORS, and other existing
|
|
|
|
|
mechanisms are used. A dictionary can be a pre-made static dictionary, but does not
|
|
|
|
|
have to be, for example a previous page loaded from this server, or an old version
|
|
|
|
|
of a page, can be used as well.
|
|
|
|
|
|
|
|
|
|
Below are changes and additions to add Shared Brotli dictionaries to the fetch spec
|
|
|
|
|
at https://fetch.spec.whatwg.org/:
|
2017-11-16 18:13:39 +00:00
|
|
|
|
|
|
|
|
|
Additions to `4.5. HTTP-network-or-cache fetch`
|
|
|
|
|
|
|
|
|
|
Add to point `15. Modify httpRequest’s header list per HTTP.`:
|
|
|
|
|
|
|
|
|
|
If the recursive-sbr flag is enabled, `Accept-Encoding` may not contain `sbr`
|
|
|
|
|
[NOTE-BOX] When sbr can be used, it is possible to add a header Available-Dict
|
|
|
|
|
with the URL and hash code of a cached resource. The server may then use it as
|
|
|
|
|
shared dictionary.
|
|
|
|
|
|
|
|
|
|
Additions to `4.6. HTTP-network fetch`
|
|
|
|
|
|
|
|
|
|
Add after point `10. Run these steps, but abort if the ongoing fetch is terminated`:
|
|
|
|
|
|
|
|
|
|
11. Let codings be the result of extracting header list values given
|
|
|
|
|
`Content-Encoding` and response’s header list.
|
|
|
|
|
12. If codings contains `sbr`
|
|
|
|
|
1. If the header list does not contain `Sbr-Dict`, return a network error
|
|
|
|
|
2. Let dictionaryId be the result of extracting header list values given
|
|
|
|
|
`Sbr-Dict` and response’s header list.
|
|
|
|
|
|
|
|
|
|
To point `12. Run these substeps in parallel:`, add new first sub-point:
|
|
|
|
|
|
|
|
|
|
1. If codings contains `sbr`, run these subsubsteps:
|
|
|
|
|
1. Let dictionaryResponse be the result of performing a
|
|
|
|
|
Shared-Brotli-dictionary fetch given dictionaryId and request.
|
|
|
|
|
2. If dictionaryResponse is a network error, return a network error.
|
|
|
|
|
|
|
|
|
|
Change point `12.4. Set bytes to the result of handling content codings given codings and bytes.` to:
|
|
|
|
|
|
|
|
|
|
4. Set bytes to the result of handling content codings given codings, bytes
|
|
|
|
|
and, if codings contains `sbr`, also dictionaryResponse's body.
|
|
|
|
|
[NOTE-BOX] If the dictionary is still being fetched, which happens in
|
|
|
|
|
parallel, enqueue bytes in a compressed buffer and handle content coding
|
|
|
|
|
once the dictionary is fetched
|
|
|
|
|
|
|
|
|
|
Additions to `2.2.4. Bodies`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Change last section `To handle content codings ...` to:
|
|
|
|
|
|
|
|
|
|
To handle content codings given codings, bytes and optionally a dictionary, run these substeps:
|
|
|
|
|
1. If codings are not supported, return bytes.
|
|
|
|
|
2. If the codings has `sbr`, run these subsubsteps:
|
|
|
|
|
a. Return the result of decoding bytes and dictionary with the Shared
|
|
|
|
|
Brotli decoder.
|
|
|
|
|
[Shared Brotli Spec] [IANA Brotli](https://www.iana.org/assignments/http-parameters/http-parameters.xhtml)
|
|
|
|
|
3. Else:
|
|
|
|
|
a. Return the result of decoding bytes with the given codings, as
|
|
|
|
|
explained in HTTP. [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING]
|
|
|
|
|
[HTTP-AUTH]
|
|
|
|
|
|
|
|
|
|
New section `4.10. Shared-Brotli-dictionary fetch`
|
|
|
|
|
|
|
|
|
|
To perform a Shared-Brotli-dictionary fetch using dictionaryId, and parentRequest, perform these steps:
|
|
|
|
|
|
|
|
|
|
1. Let dictionaryURL be the URL extracted from dictionaryId
|
|
|
|
|
2. Let dictionaryHash be the hash id extracted from dictionaryId
|
|
|
|
|
3. Let dictionaryRequest be a new request whose method is `GET`, url is
|
|
|
|
|
dictionaryURL, mode is "cors", and client is parentRequest's client.
|
|
|
|
|
4. Let dictionaryResponse be the result of performing an
|
|
|
|
|
[HTTP-network-or-cache](https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch)
|
|
|
|
|
fetch using dictionaryRequest with the recursive-sbr flag set to true.
|
|
|
|
|
[NOTE-BOX] For compression benefits, the dictionary should be reused to
|
|
|
|
|
decode multiple different responses. We rely on caching to achieve this.
|
|
|
|
|
It is suggested for servers to not add any "no-cache" or short "max-age"
|
|
|
|
|
Cache-Control directives, and it is suggested for the client to effectively
|
|
|
|
|
support caching it.
|
|
|
|
|
[NOTE-BOX] Since the same dictionary can be identified by a hash code, a
|
|
|
|
|
browser can avoid fetching a dictionary if it already has one with the same
|
|
|
|
|
hashed cached from a different source URL.
|
|
|
|
|
[NOTE-BOX] It is suggested that a server does not reuse the same URL
|
|
|
|
|
to host an updated or different dictionary. Instead the same dictionary URL
|
|
|
|
|
should contain a dictionary with the same content and same hash.
|
|
|
|
|
5. If dictionaryResponse is a network error, return a network error.
|
|
|
|
|
6. If dictionaryResponse's status is not an ok status, return a network error.
|
|
|
|
|
7. Let tokens be the result of
|
|
|
|
|
[parsing metadata](https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata)
|
|
|
|
|
given dictionaryHash.
|
|
|
|
|
[Subresource Integrity](https://w3c.github.io/webappsec-subresource-integrity/)
|
|
|
|
|
8. If tokens is no metadata or the length of tokens is not 1, return a network
|
|
|
|
|
error
|
|
|
|
|
9. Let algorithm be the alg component of tokens[0]. If alg is 'hw3', set
|
|
|
|
|
algorithm to 256-bit HighwayHash
|
|
|
|
|
10. Let digest be the val component of tokens[1].
|
|
|
|
|
11. Let hashValue be the result of base64 decoding digest
|
|
|
|
|
[base64](https://tools.ietf.org/html/rfc4648)
|
|
|
|
|
12. If hashValue is not a valid base64 encoding, return a network error
|
|
|
|
|
[NOTE-BOX] All of the supported hashing algorithms are cryptographically
|
|
|
|
|
secure.
|
|
|
|
|
13. Compute the hash code of dictionaryResponse's body using algorithm and
|
|
|
|
|
compare this checksum for equality with hashValue. If the computed
|
|
|
|
|
checksum does not match hashValue, return a network error.
|
|
|
|
|
14. Return dictionaryResponse.
|