Network Working Group                                         J. Yasskin
Internet-Draft                                                    Google
Intended status: Standards Track                           June 13, 2018
Expires: December 15, 2018


                         Bundled HTTP Exchanges
                draft-yasskin-wpack-bundled-exchanges-00

Abstract

   Bundled exchanges provide a way to bundle up groups of HTTP
   request+response pairs to transmit or store them together.  They can
   include multiple top-level resources with one identified as the
   default by a manifest, provide random access to their component
   exchanges, and efficiently store 8-bit resources.

Note to Readers

   Discussion of this draft takes place on the ART area mailing list
   (art@ietf.org), which is archived at
   https://mailarchive.ietf.org/arch/search/?email_list=art [1].

   The source code and issues list for this draft can be found in
   https://github.com/WICG/webpackage [2].

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on December 15, 2018.

Copyright Notice

   Copyright (c) 2018 IETF Trust and the persons identified as the
   document authors.  All rights reserved.




Yasskin                 Expires December 15, 2018               [Page 1]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (https://trustee.ietf.org/license-info) in effect on the date of
   publication of this document.  Please review these documents
   carefully, as they describe your rights and restrictions with respect
   to this document.  Code Components extracted from this document must
   include Simplified BSD License text as described in Section 4.e of
   the Trust Legal Provisions and are provided without warranty as
   described in the Simplified BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
     1.1.  Terminology . . . . . . . . . . . . . . . . . . . . . . .   3
     1.2.  Mode of specification . . . . . . . . . . . . . . . . . .   3
   2.  Semantics . . . . . . . . . . . . . . . . . . . . . . . . . .   3
     2.1.  Stream attributes and operations  . . . . . . . . . . . .   4
     2.2.  Load a bundle's metadata  . . . . . . . . . . . . . . . .   4
       2.2.1.  Load a bundle's metadata from the end . . . . . . . .   5
     2.3.  Load a response from a bundle . . . . . . . . . . . . . .   5
   3.  Format  . . . . . . . . . . . . . . . . . . . . . . . . . . .   5
     3.1.  Top-level structure . . . . . . . . . . . . . . . . . . .   5
     3.2.  Load a bundle's metadata  . . . . . . . . . . . . . . . .   6
       3.2.1.  Parsing the index section . . . . . . . . . . . . . .   8
       3.2.2.  Parsing the manifest section  . . . . . . . . . . . .   9
       3.2.3.  Parsing the critical section  . . . . . . . . . . . .  10
       3.2.4.  The responses section . . . . . . . . . . . . . . . .  10
       3.2.5.  Starting from the end . . . . . . . . . . . . . . . .  10
     3.3.  Load a response from a bundle . . . . . . . . . . . . . .  11
     3.4.  Parsing CBOR items  . . . . . . . . . . . . . . . . . . .  13
       3.4.1.  Parse a known-length item . . . . . . . . . . . . . .  13
       3.4.2.  Parsing variable-length data from a bytestring  . . .  13
     3.5.  Interpreting CBOR HTTP headers  . . . . . . . . . . . . .  14
   4.  Guidelines for bundle authors . . . . . . . . . . . . . . . .  15
   5.  Security Considerations . . . . . . . . . . . . . . . . . . .  15
   6.  IANA considerations . . . . . . . . . . . . . . . . . . . . .  16
     6.1.  Internet Media Type Registration  . . . . . . . . . . . .  16
     6.2.  Web Bundle Section Name Registry  . . . . . . . . . . . .  17
   7.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  17
     7.1.  Normative References  . . . . . . . . . . . . . . . . . .  17
     7.2.  Informative References  . . . . . . . . . . . . . . . . .  19
     7.3.  URIs  . . . . . . . . . . . . . . . . . . . . . . . . . .  19
   Appendix A.  Acknowledgements . . . . . . . . . . . . . . . . . .  19
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  19







Yasskin                 Expires December 15, 2018               [Page 2]


Internet-Draft           Bundled HTTP Exchanges                June 2018


1.  Introduction

   To satisfy the use cases in [I-D.yasskin-webpackage-use-cases], this
   document proposes a new bundling format to group HTTP resources.
   Several of the use cases require the resources to be signed: that's
   provided by bundling signed exchanges
   ([I-D.yasskin-http-origin-signed-responses]) rather than natively in
   this format.

1.1.  Terminology

   Exchange (noun)  An HTTP request+response pair.  This can either be a
      request from a client and the matching response from a server or
      the request in a PUSH_PROMISE and its matching response stream.
      Defined by Section 8 of [RFC7540].

   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 interpreted as described in BCP
   14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

1.2.  Mode of specification

   This specification defines how conformant bundle parsers work.  It
   does not constrain how encoders produce a bundle: although there are
   some guidelines in Section 4, encoders MAY produce any sequence of
   bytes that a conformant parser would parse into the intended
   semantics.

   This specification uses the conventions and terminology defined in
   the Infra Standard ([INFRA]).

2.  Semantics

   A bundle is logically a set of HTTP exchanges, with a URL identifying
   the manifest(s) of the bundle itself.

   While the order of the exchanges is not semantically meaningful, it
   can significantly affect performance when the bundle is loaded from a
   network stream.

   A bundle is parsed from a stream of bytes, which is assumed to have
   the attributes and operations described in Section 2.1.

   Bundle parsers support two operations, Load a bundle's metadata
   (Section 2.2) and Load a response from a bundle (Section 2.3) each of
   which can return an error instead of their normal result.



Yasskin                 Expires December 15, 2018               [Page 3]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   A client is expected to load the metadata for a bundle as soon as it
   start downloading it or otherwise discovers it.  Then, when fetching
   ([FETCH]) a request, the cliend is expected to match it against the
   requests in the metadata, and if one matches, load that request's
   response.

2.1.  Stream attributes and operations

   o  A sequence of *available bytes*. As the stream delivers bytes,
      these are appended to the available bytes.

   o  An *EOF* flag that's true if the available bytes include the
      entire stream.

   o  A *current offset* within the available bytes.

   o  A *seek to offset N* operation to set the current offset to N
      bytes past the beginning of the available bytes.  A seek past the
      end of the available bytes blocks until N bytes are available.  If
      the stream ends before enough bytes are received, either due to a
      network error or because the stream has a finite length, the seek
      fails.

   o  A *read N bytes* operation, which blocks until N bytes are
      available past the current offset, and then returns them and seeks
      forward by N bytes.  If the stream ends before enough bytes are
      received, either due to a network error or because the stream has
      a finite length, the read operation returns an error instead.

2.2.  Load a bundle's metadata

   This takes the bundle's stream and returns a map ([INFRA]) of
   metadata containing at least keys named:

   requests  A map ([INFRA]) whose keys are [FETCH] requests for the
      HTTP exchanges in the bundle, and whose values are opaque metadata
      that Load a response from a bundle can use to find the matching
      response.

   manifest  The URL of the bundle's manifest(s).  This is a URL to
      support bundles with multiple different manifests, where the
      client uses content negotiation to select the most appropriate
      one.

   The map may include other items added by sections defined in the
   Web Bundle Section Name Registry.





Yasskin                 Expires December 15, 2018               [Page 4]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   This operation only waits for a prefix of the stream that, if the
   bundle is encoded with the "responses" section last, ends before the
   first response.

   This operation's implementation is in Section 3.2.

2.2.1.  Load a bundle's metadata from the end

   If a bundle's bytes are embedded in a longer sequence rather than
   being streamed, a parser can also load them starting from a pointer
   to the last byte of the bundle.  This returns the same data as
   Section 2.2.

   This operation's implementation is in Section 3.2.5.

2.3.  Load a response from a bundle

   This takes the sequence of bytes representing the bundle and one
   request returned from Section 2.2 with its metadata, and returns the
   response ([FETCH]) matching that request.

   This operation can be completed without inspecting bytes other than
   those that make up the loaded response, although higher-level
   operations like proving that an exchange is correctly signed
   ([I-D.yasskin-http-origin-signed-responses]) may need to load other
   responses.

   Note that this operation uses the metadata for a particular request
   returned by Section 2.2, while a client will generally want to load
   the response for a request that the client generated.  TODO: Specify
   how a client determines the best available bundled response, if any,
   for that client-generated request, in this or another document.

   This operation's implementation is in Section 3.3.

3.  Format

3.1.  Top-level structure

   _This section is non-normative._

   A bundle holds a series of named sections.  The beginning of the
   bundle maps section names to the range of bytes holding that section.
   The most important section is the "index" (Section 3.2.1), which
   similarly maps serialized HTTP requests to the range of bytes holding
   that request's serialized response.  Byte ranges are represented
   using an offset from some point in the bundle _after_ the encoding of




Yasskin                 Expires December 15, 2018               [Page 5]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   the range itself, to reduce the amount of work needed to use the
   shortest possible encoding of the range.

   Future specifications can define new sections with extra data, and if
   necessary, these sections can be marked "critical" (Section 3.2.3) to
   prevent older parsers from using the rest of the bundle incorrectly.

   The bundle is roughly a CBOR item ([I-D.ietf-cbor-7049bis]) with the
   following CDDL ([I-D.ietf-cbor-cddl]) schema, but bundle parsers are
   required to successfully parse some byte strings that aren't valid
   CBOR.  For example, sections might have padding between them, or even
   overlap, as long as the embedded relative offsets cause the parsing
   algorithms in this specification to return data.

   webbundle = [
     ; 🌐📦 in UTF-8.
     magic: h'F0 9F 8C 90 F0 9F 93 A6',
     section-offsets: bytes .cbor {* ($section-name .within tstr) =>
                                     [ offset: uint, length: uint] },
     sections: [* $section ],
     length: bytes .size 8,  ; Big-endian number of bytes in the bundle.
   ]

   $section-name /= "index" / "manifest" / "critical" / "responses"

   $section /= index / manifest / critical / responses

   responses = [*response]


3.2.  Load a bundle's metadata

   A bundle holds a series of sections, which can be accessed randomly
   using the information in the "section-offset" CBOR item:

   section-offsets = {* tstr => [ offset: uint, length: uint] },

   Offsets in this item are relative to the _end_ of the section-offset
   item.

   To implement Section 2.2, the parser MUST run the following steps,
   taking the "stream" as input.

   1.   Seek to offset 0 in "stream".  Assert: this operation doesn't
        fail.

   2.   If reading 10 bytes from "stream" returns an error or doesn't
        return the bytes with hex encoding "84 48 F0 9F 8C 90 F0 9F 93



Yasskin                 Expires December 15, 2018               [Page 6]


Internet-Draft           Bundled HTTP Exchanges                June 2018


        A6" (the CBOR encoding of the 4-item array initial byte and
        8-byte bytestring initial byte, followed by 🌐📦
        in UTF-8), return an error.

   3.   Let "sectionOffsetsLength" be the result of getting the length
        of the CBOR bytestring header from "stream" (Section 3.4.2).  If
        this is an error, return that error.

   4.   If "sectionOffsetsLength" is TBD or greater, return an error.

   5.   Let "sectionOffsetsBytes" be the result of reading
        "sectionOffsetsLength" bytes from "stream".  If
        "sectionOffsetsBytes" is an error, return that error.

   6.   Let "sectionOffsets" be the result of parsing one CBOR item
        (Section 3.4) from "sectionOffsetsBytes", matching the section-
        offsets rule in the CDDL ([I-D.ietf-cbor-cddl]) above.  If
        "sectionOffsets" is an error, return an error.

   7.   Let "sectionsStart" be the current offset within "stream".  For
        example, if "sectionOffsetsLength" were 52, "sectionsStart"
        would be 64.

   8.   Let "knownSections" be the subset of the Section 6.2 that this
        client has implemented.

   9.   Let "ignoredSections" be an empty set.

   10.  For each ""name"" key in "sectionOffsets", if ""name""'s
        specification in "knownSections" says not to process other
        sections, add those sections' names to "ignoredSections".

   11.  Let "metadata" be an empty map ([INFRA]).

   12.  For each ""name""/["offset", "length"] triple in
        "sectionOffsets":

        1.  If ""name"" isn't in "knownSections", continue to the next
            triple.

        2.  If ""name""'s Metadata field is "No", continue to the next
            triple.

        3.  If ""name"" is in "ignoredSections", continue to the next
            triple.

        4.  Seek to offset "sectionsStart + offset" in "stream".  If
            this fails, return an error.



Yasskin                 Expires December 15, 2018               [Page 7]


Internet-Draft           Bundled HTTP Exchanges                June 2018


        5.  Let "sectionContents" be the result of reading "length"
            bytes from "stream".  If "sectionContents" is an error,
            return that error.

        6.  Follow ""name""'s specification from "knownSections" to
            process the section, passing "sectionContents", "stream",
            "sectionOffsets", "sectionsStart", and "metadata".  If this
            returns an error, return it.

   13.  If "metadata" doesn't have entries with keys "requests" and
        "manifest", return an error.

   14.  Return "metadata".

3.2.1.  Parsing the index section

   The "index" section defines the set of HTTP requests in the bundle
   and identifies their locations in the "responses" section.

   index = {* headers => [ offset: uint,
                           length: uint] }

   To parse the index section, given its "sectionContents", the
   "sectionsStart" offset, the "sectionOffsets" CBOR item, and the
   "metadata" map to fill in, the parser MUST do the following:

   1.  Let "index" be the result of parsing "sectionContents" as a CBOR
       item matching the "index" rule in the above CDDL (Section 3.4).
       If "index" is an error, return an error.

   2.  Let "requests" be an initially-empty map ([INFRA]) from HTTP
       requests ([FETCH]) to structs ([INFRA]) with items named "offset"
       and "length".

   3.  For each "cbor-http-request"/["offset", "length"] triple in
       "index":

       1.  Let "headers"/"pseudos" be the result of converting "cbor-
           http-request" to a header list and pseudoheaders using the
           algorithm in Section 3.5.  If this returns an error, return
           that error.

       2.  If "pseudos" does not have keys named ':method' and ':url',
           or its size isn't 2, return an error.

       3.  If "pseudos[':method']" is not 'GET', return an error.





Yasskin                 Expires December 15, 2018               [Page 8]


Internet-Draft           Bundled HTTP Exchanges                June 2018


           Note: This could probably support any cacheable
           (Section 4.2.3) of [RFC7231]) and safe (Section 4.2.1 of
           [RFC7231]) method, matching PUSH_PROMISE (Section 8.2 of
           [RFC7540]), but today that's only HEAD and GET, and HEAD can
           be served as a transformation of GET, so this version of the
           specification keeps the method simple.

       4.  Let "parsedUrl" be the result of parsing ([URL])
           "pseudos[':url']" with no base URL.

       5.  If "parsedUrl" is a failure, its fragment is not null, or it
           includes credentials, return an error.

       6.  Let "http-request" be a new request ([FETCH]) whose:

           +  method is "pseudos[':method']",

           +  url is "parsedUrl",

           +  header list is "headers", and

           +  client is null.

       7.  Let "streamOffset" be "sectionsStart + section-
           offsets["responses"].offset + offset".  That is, offsets in
           the index are relative to the start of the "responses"
           section.

       8.  If "offset + length" is greater than
           "sectionOffsets["responses"].length", return an error.

       9.  Set "requests"["http-request"] to a struct whose "offset"
           item is "streamOffset" and whose "length" item is "length".

   4.  Set "metadata["requests"]" to "requests".

3.2.2.  Parsing the manifest section

   The "manifest" section records a single URL identifying the manifest
   of the bundle.  The bundle can contain multiple resources at this
   URL, and the client is expected to content-negotiate for the best
   one.  For example, a client might select the one with an "accept"
   header of "application/manifest+json" ([appmanifest]) and an "accept-
   language" header of "es-419".

   manifest = text





Yasskin                 Expires December 15, 2018               [Page 9]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   To parse the manifest section, given its "sectionContents" and the
   "metadata" map to fill in, the parser MUST do the following:

   1.  Let "urlString" be the result of parsing "sectionContents" as a
       CBOR item matching the above "manifest" rule (Section 3.4.  If
       "urlString" is an error, return that error.

   2.  Let "url" be the result of parsing ([URL]) "urlString" with no
       base URL.

   3.  If "url" is a failure, its fragment is not null, or it includes
       credentials, return an error.

   4.  Set "metadata["manifest"]" to "url".

3.2.3.  Parsing the critical section

   The "critical" section lists sections of the bundle that the client
   needs to understand in order to load the bundle correctly.  Other
   sections are assumed to be optional.

   critical = [*tstr]

   To parse the critical section, given its "sectionContents" and the
   "metadata" map to fill in, the parser MUST do the following:

   1.  Let "critical" be the result of parsing "sectionContents" as a
       CBOR item matching the above "critical" rule (Section 3.4).  If
       "critical" is an error, return that error.

   2.  For each value "sectionName" in the "critical" list, if the
       client has not implemented sections named "sectionName", return
       an error.

   This section does not modify the returned metadata.

3.2.4.  The responses section

   The responses section does not add any items to the bundle metadata
   map.  Instead, its offset and length are used in processing the index
   section (Section 3.2.1).

3.2.5.  Starting from the end

   The length of a bundle is encoded as a big-endian integer inside a
   CBOR byte string at the end of the bundle.





Yasskin                 Expires December 15, 2018              [Page 10]


Internet-Draft           Bundled HTTP Exchanges                June 2018


    +------------+-----+----+----+----+----+----+----+----+----+----+
    | first byte | ... | 48 | 00 | 00 | 00 | 00 | 00 | BC | 61 | 4E |
    +------------+-----+----+----+----+----+----+----+----+----+----+
                /       \
          0xBC614E-10=12345668 omitted bytes

                     Figure 1: Example trailing bytes

   Parsing from the end allows the bundle to be appended to another
   format such as a self-extracting executable.

   To implement Section 2.2.1, taking a sequence of bytes "bytes", the
   client MUST:

   1.  Let "byteStringHeader" be "bytes[bytes.length - 9]".  If
       "byteStringHeader is not "0x48` (the CBOR
       ([I-D.ietf-cbor-7049bis]) initial byte for an 8-byte byte
       string), return an error.

   2.  Let "bundleLength" be "[bytes[bytes.length - 8],
       bytes[bytes.length])" (the last 8 bytes) interpreted as a big-
       endian integer.

   3.  If "bundleLength > bytes.length", return an error.

   4.  Let "stream" be a new stream whose:

       *  Available bytes are "[bytes[bytes.length - bundleLength],
          bytes[bytes.length])".

       *  EOF flag is set.

       *  Current offset is initially 0.

       *  The seek to offset N and read N bytes operations succeed
          immediately if "currentOffset + N <= bundleLength" and fail
          otherwise.

   5.  Return the result of running Section 3.2 with "stream" as input.

3.3.  Load a response from a bundle

   The result of Load a bundle's metadata maps each request to a
   response, which consists of headers and a payload.  The headers can
   be loaded from the bundle's stream before waiting for the payload,
   and similarly the payload can be streamed to downstream consumers.

   response = [headers: bstr .cbor headers, payload: bstr]



Yasskin                 Expires December 15, 2018              [Page 11]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   To implement Section 2.3, the parser MUST run the following steps,
   taking the bundle's "stream" and one "request" and its
   "requestMetadata" as returned by Section 2.2.

   1.   Seek to offset "requestMetadata.offset" in "stream".  If this
        fails, return an error.

   2.   Read 1 byte from "stream".  If this is an error or isn't "0x82",
        return an error.

   3.   Let "headerLength" be the result of getting the length of a CBOR
        bytestring header from "stream" (Section 3.4.2).  If
        "headerLength" is an error, return that error.

   4.   If "headerLength" is TBD or greater, return an error.

   5.   Let "headerCbor" be the result of reading "headerLength" bytes
        from "stream" and parsing a CBOR item from them matching the
        "headers" CDDL rule.  If either the read or parse returns an
        error, return that error.

   6.   Let "headers"/"pseudos" be the result of converting "cbor-http-
        request" to a header list and pseudoheaders using the algorithm
        in Section 3.5.  If this returns an error, return that error.

   7.   If "pseudos" does not have a key named ':status' or its size
        isn't 1, return an error.

   8.   If "pseudos[':status']" isn't exactly 3 ASCII decimal digits,
        return an error.

   9.   Let "payloadLength" be the result of getting the length of a
        CBOR bytestring header from "stream" (Section 3.4.2).  If
        "payloadLength" is an error, return that error.

   10.  If "stream.currentOffset + payloadLength !=
        requestMetadata.offset + requestMetadata.length", return an
        error.

   11.  Let "body" be a new body ([FETCH]) whose stream is a tee'd copy
        of "stream" starting at the current offset and ending after
        "payloadLength" bytes.

        TODO: Add the rest of the details of creating a "ReadableStream"
        object.

   12.  Let "response" be a new response ([FETCH]) whose:




Yasskin                 Expires December 15, 2018              [Page 12]


Internet-Draft           Bundled HTTP Exchanges                June 2018


        *  Url list is "request"'s url list,

        *  status is "pseudos[':status']",

        *  header list is "headers", and

        *  body is "body".

   13.  Return "response".

3.4.  Parsing CBOR items

   Parsing a bundle involves parsing many CBOR items.  All of these
   items need to be canonically encoded.

3.4.1.  Parse a known-length item

   To parse a CBOR item ([I-D.ietf-cbor-7049bis]), optionally matching a
   CDDL rule ([I-D.ietf-cbor-cddl]), from a sequence of bytes, "bytes",
   the parser MUST do the following:

   1.  If "bytes" are not a well-formed CBOR item, return an error.

   2.  If "bytes" does not satisfy the core canonicalization
       requirements from Section 4.9 of [I-D.ietf-cbor-7049bis], return
       an error.  This format does not use floating point values or
       tags, so this specification does not add any canonicalization
       rules for them.

   3.  If "bytes" includes extra bytes after the encoding of a CBOR
       item, return an error.

   4.  Let "item" be the result of decoding "bytes" as a CBOR item.

   5.  If a CDDL rule was specified, but "item" does not match it,
       return an error.

   6.  Return "item".

3.4.2.  Parsing variable-length data from a bytestring

   Bundles encode variable-length data in CBOR bytestrings, which are
   prefixed with their length.  This algorithm returns the number of
   bytes in the variable-length item and sets the stream's current
   offset to the first byte of the contents.

   To get the length of a CBOR bytestring header from a bundle's stream,
   the parser MUST do the following:



Yasskin                 Expires December 15, 2018              [Page 13]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   1.  Let "firstByte" be the result of reading 1 byte from the stream.
       If "firstByte" is an error, return that error.

   2.  If "firstByte & 0xE0" is not "0x40", the item is not a
       bytestring.  Return an error.

   3.  If "firstByte & 0x1F" is:

       0..23, inclusive  Return "firstByte".

       24 Let "content" be the result of reading 1 byte from the stream.
          If "content" is an error or is less than 24, return an error.

       25 Let "content" be the result of reading 2 bytes from the
          stream.  If "content" is an error or its first byte is 0,
          return an error.

       26 Let "content" be the result of reading 4 bytes from the
          stream.  If "content" is an error or its first two bytes are
          0, return an error.

       27 Let "content" be the result of reading 8 bytes from the
          stream.  If "content" is an error or its first four bytes are
          0, return an error.

       28..31, inclusive  Return an error.

   4.  Return the big-endian integer encoded in "content".

3.5.  Interpreting CBOR HTTP headers

   Bundles represent HTTP requests and responses as a list of headers,
   matching the following CDDL ([I-D.ietf-cbor-cddl]):

   headers = {* bstr => bstr}

   Pseudo-headers starting with a ":" provide the non-header information
   needed to create a request or response as appropriate

   To convert a CBOR item "item" into a [FETCH] header list and
   pseudoheaders, parsers MUST do the following:

   1.  If "item" doesn't match the "headers" rule in the above CDDL,
       return an error.

   2.  Let "headers" be a new header list ([FETCH]).

   3.  Let "pseudos" be an empty map ([INFRA]).



Yasskin                 Expires December 15, 2018              [Page 14]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   4.  For each pair "name"/"value" in "item":

       1.  If "name" contains any upper-case or non-ASCII characters,
           return an error.  This matches the requirement in
           Section 8.1.2 of [RFC7540].

       2.  If "name" starts with a ':':

           1.  Assert: "pseudos[name]" does not exist, because CBOR maps
               cannot contain duplicate keys.

           2.  Set "pseudos[name]" to "value".

           3.  Continue.

       3.  If "name" or "value" doesn't satisfy the requirements for a
           header in [FETCH], return an error.

       4.  Assert: "headers" does not contain ([FETCH]) "name", because
           CBOR maps cannot contain duplicate keys and an earlier step
           rejected upper-case bytes.

           Note: This means that a response cannot set more than one
           cookie, because the "Set-Cookie" header ([RFC6265]) has to
           appear multiple times to set multiple cookies.

       5.  Append "name"/"value" to "headers".

   5.  Return "headers"/"pseudos".

4.  Guidelines for bundle authors

   Bundles SHOULD consist of a single CBOR item satisfying the core
   canonicalization requirements (Section 3.4) and matching the
   "webbundle" CDDL rule in Section 3.1.

5.  Security Considerations

   Bundles currently have no mechanism for ensuring that the signed
   exchanges they contain constitute a consistent version of those
   resources.  Even if a website never has a security vulnerability when
   resources are fetched at a single time, an attacker might be able to
   combine a set of resources pulled from different versions of the
   website to build a vulnerable site.  While the vulnerable site could
   have occurred by chance on a client's machine due to normal HTTP
   caching, bundling allows an attacker to guarantee that it happens.
   Future work in this specification might allow a bundle to constrain
   its resources to come from a consistent version.



Yasskin                 Expires December 15, 2018              [Page 15]


Internet-Draft           Bundled HTTP Exchanges                June 2018


6.  IANA considerations

6.1.  Internet Media Type Registration

   IANA maintains the registry of Internet Media Types [RFC6838] at
   https://www.iana.org/assignments/media-types [3].

   o  Type name: application

   o  Subtype name: webbundle

   o  Required parameters: N/A

   o  Optional parameters: N/A

   o  Encoding considerations: binary

   o  Security considerations: See Section 5 of this document.

   o  Interoperability considerations: N/A

   o  Published specification: This document

   o  Applications that use this media type: None yet, but it is
      expected that web browsers will use this format.

   o  Fragment identifier considerations: N/A

   o  Additional information:

      *  Deprecated alias names for this type: N/A

      *  Magic number(s): 84 48 F0 9F 8C 90 F0 9F 93 A6

      *  File extension(s): .wbn

      *  Macintosh file type code(s): N/A

   o  Person & email address to contact for further information: See the
      Author's Address section of this specification.

   o  Intended usage: COMMON

   o  Restrictions on usage: N/A

   o  Author: See the Author's Address section of this specification.

   o  Change controller: The IESG iesg@ietf.org [4]



Yasskin                 Expires December 15, 2018              [Page 16]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   o  Provisional registration? (standards tree only): Not yet.

6.2.  Web Bundle Section Name Registry

   IANA is directed to create a new registry with the following
   attributes:

   Name: Web Bundle Section Names

   Review Process: Specification Required

   Initial Assignments:

                +--------------+---------------+----------+
                | Section Name | Specification | Metadata |
                +--------------+---------------+----------+
                | "index"      | Section 3.2.1 | Yes      |
                |              |               |          |
                | "manifest    | Section 3.2.2 | Yes      |
                |              |               |          |
                | "critical    | Section 3.2.3 | Yes      |
                |              |               |          |
                | "responses"  | Section 3.2.4 | No       |
                +--------------+---------------+----------+

   Requirements on new assignments:

   Section Names MUST be encoded in UTF-8.

   Assignments must specify whether the section is parsed during
   Load a bundle's metadata (Metadata=Yes) or not (Metadata=No).

   The section's specification can use the bytes making up the section,
   the bundle's stream (Section 2.1), the "sectionOffsets" CBOR item
   (Section 3.2), and the offset within the stream where sections start,
   as input, and MUST say if an error is returned, and otherwise what
   items, if any, are added to the map that Section 3.2 returns.  A
   section's specification MAY say that, if it is present, another
   section is not processed.

7.  References

7.1.  Normative References








Yasskin                 Expires December 15, 2018              [Page 17]


Internet-Draft           Bundled HTTP Exchanges                June 2018


   [appmanifest]
              Caceres, M., Christiansen, K., Lamouri, M., Kostiainen,
              A., Dolin, R., and M. Giuca, "Web App Manifest", World
              Wide Web Consortium WD WD-appmanifest-20180523, May 2018,
              <https://www.w3.org/TR/2018/WD-appmanifest-20180523>.

   [FETCH]    WHATWG, "Fetch", June 2018,
              <https://fetch.spec.whatwg.org/>.

   [I-D.ietf-cbor-7049bis]
              Bormann, C. and P. Hoffman, "Concise Binary Object
              Representation (CBOR)", draft-ietf-cbor-7049bis-02 (work
              in progress), March 2018.

   [I-D.ietf-cbor-cddl]
              Birkholz, H., Vigano, C., and C. Bormann, "Concise data
              definition language (CDDL): a notational convention to
              express CBOR data structures", draft-ietf-cbor-cddl-02
              (work in progress), February 2018.

   [INFRA]    WHATWG, "Infra", June 2018,
              <https://infra.spec.whatwg.org/>.

   [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>.

   [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>.

   [RFC7540]  Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext
              Transfer Protocol Version 2 (HTTP/2)", RFC 7540,
              DOI 10.17487/RFC7540, May 2015,
              <https://www.rfc-editor.org/info/rfc7540>.

   [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>.

   [SRI]      Akhawe, D., Braun, F., Marier, F., and J. Weinberger,
              "Subresource Integrity", World Wide Web Consortium
              Recommendation REC-SRI-20160623, June 2016,
              <http://www.w3.org/TR/2016/REC-SRI-20160623>.

   [URL]      WHATWG, "URL", June 2018, <https://url.spec.whatwg.org/>.



Yasskin                 Expires December 15, 2018              [Page 18]


Internet-Draft           Bundled HTTP Exchanges                June 2018


7.2.  Informative References

   [I-D.yasskin-http-origin-signed-responses]
              Yasskin, J., "Signed HTTP Exchanges", draft-yasskin-http-
              origin-signed-responses-03 (work in progress), March 2018.

   [I-D.yasskin-webpackage-use-cases]
              Yasskin, J., "Use Cases and Requirements for Web
              Packages", draft-yasskin-webpackage-use-cases-01 (work in
              progress), March 2018.

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

   [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>.

7.3.  URIs

   [1] https://mailarchive.ietf.org/arch/search/?email_list=art

   [2] https://github.com/WICG/webpackage

   [3] https://www.iana.org/assignments/media-types

   [4] mailto:iesg@ietf.org

Appendix A.  Acknowledgements

Author's Address

   Jeffrey Yasskin
   Google

   Email: jyasskin@chromium.org













Yasskin                 Expires December 15, 2018              [Page 19]