[Docs] [txt|pdf|xml|html] [Tracker] [Email] [Diff1] [Diff2] [Nits]

Versions: 00 01 02

httpbis Working Group                                             G. Xie
Internet-Draft                                               A. Frindell
Intended status: Standards Track                           Facebook Inc.
Expires: January 9, 2020                                   July 08, 2019

      An HTTP/2 Extension for Bidirectional Message Communication


   This draft proposes an HTTP/2 protocol extension that enables
   bidirectional messaging communication between client and server.

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 January 9, 2020.

Copyright Notice

   Copyright (c) 2019 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) 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.

Xie & Frindell           Expires January 9, 2020                [Page 1]

Internet-Draft                 HTTP-PUBSUB                     July 2019

1.  Introduction

   HTTP/2 [RFC7540] transports HTTP messages via a framing layer that
   includes many technologies and optimizations designed to make
   communication more efficient between clients and servers.  These
   include multiplexing of multiple streams on a single underlying
   transport connection, flow control, stream dependencies and
   priorities, header compression, and exchange of configuration
   information between endpoints.

   Many of these capabilities are generic and can be useful in
   applications beyond web browsing, such as Publish/Subscribe protocols
   or RPC.  However, HTTP/2 framing's request/response client to server
   communication pattern prevents wider use in this type of application.
   This draft proposes an HTTP/2 protocol extension that enables
   bidirectional communication between client and server.

   Currently, the only mechanism in HTTP/2 for server to client
   communication is server push.  That is, servers can initiate
   unidirectional push promised streams to clients, but clients cannot
   respond to them and either accept or discard them silently.
   Additionally, intermediaries along the path may have different server
   push policies and may not forward push promised streams to the
   downstream client.  This best effort mechanism is not sufficient to
   reliably deliver content from servers to clients, limiting additional
   use-cases, such as sending messages and notifications from servers to
   clients immediately when they become available.

   Several techniques have been developed to workaround these
   limitations: long polling [RFC6202], WebSocket [RFC8441], and
   tunneling using the CONNECT method.  All of these approaches layer an
   application protocol on top of HTTP/2, using HTTP/2 streams as
   transport connections.  This layering defeats the optimizations
   provided by HTTP/2.  For example, multiplexing multiple parallel
   interactions onto one HTTP/2 stream reintroduces head of line
   blocking.  Also, application metadata is encapsulated into DATA
   frames, rather than HEADERS frames, making header compression
   impossible.  Further, user data is framed multiple times at different
   protocol layers, which offsets the wire efficiency of HTTP/2 binary
   framing.  Take WebSocket over HTTP/2 as an example, user data is
   framed at the application protocol, WebSocket, and HTTP/2 layers.
   This not only introduces overhead on the wire, but also complicates
   data processing.  Finally, intermediaries have no visibility to user
   interactions layered on a single HTTP/2 stream, and lose the
   capability to collect telemetry metrics (e.g., time to the first/last
   byte of request and response) for services.

Xie & Frindell           Expires January 9, 2020                [Page 2]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   These techniques also pose new operational challenges to
   intermediaries.  Because all traffic from a user's session is
   encapsulated into one HTTP/2 stream, this stream can last a very long
   time.  Intermediaries may take a long time to drain these streams.
   HTTP/2 GOAWAY only signals the remote endpoint to stop using the
   connection for new streams; additional work is required to prevent
   new application messages from being initiated on the long lived

   In this draft, a new HTTP/2 frame is introduced which has the routing
   properties of a PUSH_PROMISE frame and the bi-directionality of a
   HEADERS frame.  The extension provides several benefits:

   1.  After a HTTP/2 connection is established, a server can initiate
       streams to the client at any time, and the client can respond to
       the incoming streams accordingly.  That is, the communication
       over HTTP/2 is bidirectional and symmetric.

   2.  All of the HTTP/2 technologies and optimizations still apply.
       Intermediaries also have all the necessary metadata to properly
       handle the communication between the client and the server.

   3.  Clients are able to group streams together for routing purposes,
       such that each individual stream group can be used for a
       different service, within the same HTTP/2 connection.

2.  Conventions and Terminology

   The keywords *MUST*, *MUST NOT*, *REQUIRED*, *SHALL*, *SHALL NOT*,
   they appear in this document, are to be interpreted as described in

   All the terms defined in the Conventions and Terminology section in
   [RFC7540] apply to this document.

3.  Solution Overview

3.1.  RStream and XStream

   A routing stream (RStream) is a regular HTTP/2 stream.  It is opened
   by a HEADERS frame, and *MAY* be continued by CONTINUATION and DATA
   frames.  RStreams are initiated by clients to servers, and can be
   independently routed by intermediaries on the network path.  The main
   purpose for an RStream is to facilitate XStreams' intermediary

Xie & Frindell           Expires January 9, 2020                [Page 3]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   A new HTTP/2 stream called eXtended stream (XStream) is introduced
   for exchanging user data bidirectionally.  An XStream is opened by an
   XHEADERS frame, and *MAY* be continued by CONTINUATION and DATA
   frames.  XStreams can be initiated by either clients or servers.
   Unlike a regular stream, an XStream *MUST* be associated with an open
   RStream.  In this way, XStreams can be routed according to their
   RStreams by intermediaries and servers.  XStream *MUST NOT* be
   associated with any other XStream, or any closed RStream.  Otherwise,
   it cannot be routed properly.

3.2.  Bidirectional Communication

   With RStreams and XStreams, HTTP/2 framing can be used natively for
   bidirectional communication.  As shown in Figure 1 and Figure 2 , as
   long as an RStream is open from client to server, either endpoint can
   initiate an XStream to its peer.

   +--------+   RStream (5)   +---------+    RStream (1)   +--------+
   | client |>--------------->|  proxy  |>---------------->| server |
   +--------+                 +---------+                  +--------+
       v                        ^     v                        ^
       |    XStream(7, RS=5)    |     |    XStream(3, RS=1)    |
       +------------------------+     +------------------------+

             Figure 1: Client initiates an XStream to server.

   +--------+   RStream (5)   +---------+    RStream (1)   +--------+
   | client |>--------------->|  proxy  |>---------------->| server |
   +--------+                 +---------+                  +--------+
        ^                        v     ^                        v
        |    XStream(4, RS=5)    |     |    XStream(2, RS=1)    |
        +------------------------+     +------------------------+

             Figure 2: Server initiates an XStream to client.

3.3.  XStream Grouping

   A client can multiplex RStreams, XStreams and regular HTTP/2 streams
   into a single HTTP/2 connection.  Additionally, all of the XStreams
   associated with the same RStream form a logical stream group, and are
   routed to the same endpoint.  This enables clients to access
   different services without initiating new connections,or including
   routing metadata in every message.  As shown in Figure 3, the client
   can exchange data with three different services (PubSub, RPC, and
   CDN) using one HTTP/2 connection.

Xie & Frindell           Expires January 9, 2020                [Page 4]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   +--------+   RStream (5)   +---------+    RStream (1)   +----------+
   | client |>--------------->|  proxy  |>---------------->|  PubSub  |
   +--------+   XStream (7)   +---------+    XStream (3)   +----------+
     v   v                     ^ ^  v  v
     |   |                    |  |  |  |
     |   |     RStream (11)   |  |  |  |    RStream (5)    +----------+
     |   +--------------------+  |  |  +------------------>|    RPC   |
     |         XStream (13)      |  |       XStream (7)    +----------+
     |                           |  |
     |                           |  |
     |         Stream (21)       |  |      Stream (9)      +----------+
     +---------------------------+  +--------------------->|    CDN   |

     Figure 3: Client opens multiple RStreams, XStreams and an HTTP/2
                   stream within one HTTP/2 connection.

   Reusing one connection for different purposes saves the latency of
   setting up new connections.  This is especially desirable for mobile
   devices which often have higher latency network connectivity and
   tighter battery constraints.  Multiplexing these services also allows
   them to share a single transport connection congestion control
   context.  It also opens new optimization opportunities, like
   prioritizing interactive streams over streams used to fetch static
   content.  It also reduces the number of connections that are adding
   load to intermediaries and servers in the network.

3.4.  Recommended Usage

   RStreams and XStreams are designed for different purposes.  RStreams
   are *RECOMMENDED* for exchanging metadata only, and *SHOULD* be long
   lived, as once an RStream is closed any routing information it
   carried is lost.  Unless a new RStream is re-established promptly, no
   new XStreams can be initiated.  To keep an RStream open, endpoints
   *SHOULD NOT* send a HEADERS or DATA frame containing the END_STREAM
   flag.  Implementations might require special logic to prevent
   RStreams from timing out.  For example, refresh the timeouts on
   RStreams if a new XStream is exchanged.

   By contrast, XStreams are *RECOMMENDED* for exchanging user data, and
   *SHOULD* be short lived.  In long polling, WebSocket and tunneling
   solutions, streams have to be kept alive for a long time because
   servers need those streams for sending data to the client in the
   future.  With this extension, servers are able to initiate new
   XStreams as long as RStreams are still open and no longer need to
   keep idle streams around for future use.  This allows all parties
   involved in the connection to keep resource usage to a minimum.
   Morever, short lived XStreams make graceful shutdown of a connection

Xie & Frindell           Expires January 9, 2020                [Page 5]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   easier for intermediaries and servers.  After exchanging GOAWAY
   frames, short lived XStreams will naturally drain within a short
   period of time.

3.5.  States of RStream and XStream

   RStreams are regular HTTP/2 streams that follow the stream lifecycle
   described in [RFC7540], section 5.1.  XStreams use the same lifecycle
   as regular HTTP/2 streams, but have extra dependency on their
   RStreams.  If an RStream is reset, endpoints *MUST* reset the
   XStreams associated with that RStream.  If the RStream is closed,
   endpoints *SHOULD* allow the existing XStreams to complete normally.
   The RStream *SHOULD* remain open while communication is ongoing.
   Endpoints *SHOULD* refresh any timeout on the RStream while its
   associated XStreams are open.

   A sender *MUST NOT* initiate new XStreams with an RStream that is in
   the closed or half closed (remote) state.

   Endpoints process new XStreams only when the associated RStream is in
   the open or half closed (local) state.  If an endpoint receives an
   XHEADERS frame specifying an RStream in the closed or half closed
   (remote) state, it *MUST* respond with a connection error of type

3.6.  Negotiating the Extension

   The extension *SHOULD* be disabled by default.  As noted in
   [RFC7540], section 5.5, HTTP/2 compliant implementations which do not
   support this extension *MUST* ignore the unknown ENABLE_XHEADERS
   setting and XHEADERS frame.  Endpoints can negotiate the use of this
   extension through the SETTINGS frame, and once enabled, this
   extension *MUST NOT* be disabled over the lifetime of the connection.

   This document introduces another SETTINGS parameter, ENABLE_XHEADERS,
   which *MUST* have a value of 0 or 1.

   Once a ENABLE_XHEADERS parameter has been sent with a value of 1, an
   endpoint *MUST NOT* send the parameter with a value of 0.

   If an implementation supports the extension, it is *RECOMMENDED* to
   include the ENABLE_XHEADERS setting in the initial SETTINGS frame,
   such that the remote endpoint can disover the support at the earliest
   possible time.

   An endpoint can send XHEADERS frames immediately upon receiving a
   SETTINGS frame with ENABLE_XHEADERS=1.  An endpoint *MUST NOT* send
   out XHEADERS before receiving a SETTINGS frame with the

Xie & Frindell           Expires January 9, 2020                [Page 6]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   ENABLE_XHEADERS=1.  If a remote endpoint does not support this
   extension, the XHEADERS will be ignored, making the header
   compression context inconsistent between sender and receiver.

   If an endpoint supports this extension, but receives XHEADERS frames
   before ENABLE_XHEADERS, it *SHOULD* to respond with a connection
   error XHEADER_NOT_ENABLED_ERROR.  This helps the remote endpoint to
   implement this extension properly.

   Intermediaries *SHOULD* send the ENABLE_XHEADERS setting to clients
   only if intermediaries and their upstream servers support this
   extension.  If an intermediary receives an XStream but discovers the
   destination endpoint does not support the extension, it *MUST* reset
   the stream with XHEADER_NOT_ENABLED_ERROR.

3.7.  Interaction with Standard HTTP/2 Features

   XStreams are extended HTTP/2 streams, thus all the standard HTTP/2
   features for streams still apply to XStreams.  For example, like
   streams, XStreams are counted against the concurrent stream limit,
   defined in [RFC7540], Section 5.1.2.  The connection level and stream
   level flow control principles are still valid for XStreams.  However,
   for the stream priority and dependencies, XStreams have one extra
   constraint: a XStream can have a dependency on its RStream, or any
   XStream sharing with the same RStream.  Prioritizing the XStreams
   across different RStream groups does not make sense, because they
   belong to different services.


   The XHEADERS frame (type=0xfb) has all the fields and frame header
   flags defined by HEADERS frame in HEADERS [RFC7540], section 6.2.
   The XHEADERS frame has one extra field, Routing Stream ID.  It is
   used to open an XStream, and additionally carries a header block
   fragment.  XHEADERS frames can be sent on a stream in the "idle",
   "open", or "half-closed (remote)" state.

   Like HEADERS, the CONTINUATION frame (type=0x9) is used to continue a
   sequence of header block fragments, if the headers do not fit into
   one XHEADERS frame.

4.1.  Definition

Xie & Frindell           Expires January 9, 2020                [Page 7]

Internet-Draft                 HTTP-PUBSUB                     July 2019

    |Pad Length? (8)|
    |E|                 Stream Dependency? (31)                     |
    |  Weight? (8)  |
    |R|                 Routing Stream ID (31)                      |
    |                   Header Block Fragment (*)                 ...
    |                           Padding (*)                       ...

                     Figure 4: XHEADERS Frame Payload

   The RStream specified in a XHEADERS frame *MUST* be an open stream.
   The recipient *MUST* respond with a connection error of type
   ROUTING_STREAM_ERROR PROTOCOL_ERROR, if the specified RStream is
   missing, is an XStream rather than a regualr HTTP/2 stream, or is
   closed or half-closed (remote).  Otherwise, the states maintained for
   header compression or flow control may be out of sync.

4.2.  Examples

   This section shows HTTP/1.1 request and response messages that are
   transmitted on an RStream with regualar HEADERS frames, and on an
   XStream with HTTP/2 XHAEDERS frames.

     GET /login HTTP/1.1               HEADERS
     Host: example.org          ==>     - END_STREAM
                                        + END_HEADERS
                                          :method = GET
                                          :scheme = https
                                          :path = /login
                                          host = example.org

     {binary data .... }        ==>    DATA
                                        - END_STREAM
                                          {binary data ... }

       Figure 5: The request message and HEADERS frame on an RStream

Xie & Frindell           Expires January 9, 2020                [Page 8]

Internet-Draft                 HTTP-PUBSUB                     July 2019

     HTTP/1.1 200 OK                   HEADERS
                               ==>      - END_STREAM
                                        + END_HEADERS
                                          :status = 200

     {binary data .... }       ==>     DATA
                                        - END_STREAM
                                          {binary data...}

      Figure 6: The response message and HEADERS frame on an RStream

   The server initiates an XStream to this client.

     POST /new_msg HTTP/1.1            XHEADERS
                                          RStream_ID = 3
     Host: example.org          ==>     - END_STREAM
                                        + END_HEADERS
                                          :method = POST
                                          :scheme = https
                                          :path = /new_msg
                                          host = example.org
     {binary data}              ==>    DATA
                                        + END_STREAM
                                          {binary data}

      Figure 7: The request message and XHEADERS frame on an XStream

     HTTP/1.1 200 OK                   XHEADERS
                                          RStream_ID = 3
                                ==>     + END_STREAM
                                        + END_HEADERS
                                          :status = 200

      Figure 8: The response message and XHEADERS frame on an XStream

5.  IANA Considerations

   This specification adds an entry to the "HTTP/2 Frame Type" registry,
   the "HTTP/2 Settings" registry, and the "HTTP/2 Error Code" registry,
   all defined in [RFC7540].

5.1.  FRAME TYPE Registry

   The entry in the following table are registered by this document.

Xie & Frindell           Expires January 9, 2020                [Page 9]

Internet-Draft                 HTTP-PUBSUB                     July 2019

      | Frame Type    | Code | Section      |
      | XHEADERS      | 0xfb |              |

5.2.  Settings Registry

   The entry in the following table are registered by this document.

   | Name                   | Code   | Initial Value | Specification |
   | ENABLE_XHEADERS        | 0xfbfb | 0             |               |

5.3.  Error Code Registry

   The entry in the following table are registered by this document.

   | Name                 | Code | Description       | Specification |
   | ROUTING_STREAM_ERROR | 0xfb | Routing stream is |               |
   |                      |      | not open          |               |
   | XHEADERS_NOT_        | 0xfc | XHEADERS is not   |               |
   | ENABLED_ERROR        |      | enabled yet       |               |

6.  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,

   [RFC6202]  Loreto, S., Saint-Andre, P., Salsano, S., and G. Wilkins,
              "Known Issues and Best Practices for the Use of Long
              Polling and Streaming in Bidirectional HTTP", RFC 6202,
              DOI 10.17487/RFC6202, April 2011,

   [RFC7540]  Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext
              Transfer Protocol Version 2 (HTTP/2)", RFC 7540,
              DOI 10.17487/RFC7540, May 2015,

Xie & Frindell           Expires January 9, 2020               [Page 10]

Internet-Draft                 HTTP-PUBSUB                     July 2019

   [RFC8441]  McManus, P., "Bootstrapping WebSockets with HTTP/2",
              RFC 8441, DOI 10.17487/RFC8441, September 2018,

Authors' Addresses

   Guowu Xie
   Facebook Inc.

   Email: woo@fb.com

   Alan Frindell
   Facebook Inc.

   Email: afrind@fb.com

Xie & Frindell           Expires January 9, 2020               [Page 11]

Html markup produced by rfcmarkup 1.129c, available from https://tools.ietf.org/tools/rfcmarkup/