HTTP2

Introduction

There are 2 classes of HTTP Protocol and one open networking protocol called SPDY by Google.

· HTTP/1.0 is the initial major version of HTTP network protocol.

· HTTP/2 (originally names HTTP/2.0) is subsequent major version of HTTP network protocol.

· SPDY (pronounced speedy) is an open networking protocol developed primarily at Google for transporting web content. SPDY manipulates HTTP traffic, with particular goals of reducing web page load latency and improving web security.

What’s wrong with HTTP/1.0

HTTP 1.0 was notoriously sensitive to high latency connections, as each request had to be made sequentially. If you wanted to make two requests, you had to wait until the first was completed before making the second.

HTTP 1.1 improved this, by enabling pipelining. Now if the user wanted to make two requests, they could send off both requests and then receive the responses back in order. However this suffered from head-of-line blocking, which mean trivial requests would get blocked until an earlier, potentially intensive or slow request completed.

Most browsers these days work around the above issues by opening multiple connections to a server. But this can lead to other problems, notably increased load, especially on the server.

HTTP/2 aims to address these issues by changing how the client and server communicate over the wire. To do this it introduces two new concepts: frames and streams.

Frames

Frames are the new basic unit of communication in HTTP/2 and replace the familiar header & body format of current HTTP requests/responses. Instead, each piece of communication between the client and server is packed up into a binary “frame” before it is sent over the connection. (The specification defines many “types” of frames - header frame, data frame, etc. You can read the full list and details of their usage in the HTTP/2 spec.)

So as an example, a client requesting a resource would send a headers frame to the server requesting the resource, the server will reply with a headers frame telling the client details about the resource, and finally the server will then send one or more subsequent data frames that can be used to construct the file.

One major advantage of this approach is that because the headers are now packaged into frames and treated equally to data, it allows for them to be compressed. Header compression has been a long requested feature, and should not only help reduce bandwidth usage, but should also reduce initial load times by a surprising amount because of TCP’s Slow Start mechanism.

Streams

Streams are another new concept in HTTP/2, and can be thought of as a logical single request/response communication. In reality, a stream is just a bi-directional sequence of frames that share a common identifier (a stream id). This enables interleaving of frames from multiple streams together, which allows for true multiplexed communication over a single connection - a big new feature.

Note that each logical request is given a stream id unique to that session, and to avoid collisions, any request initiated by the client uses odd number and even numbers for the server.

This fixes the “Head of Line” blocking that has plagued HTTP/1, as it means requests made on the same connection can now be responded to out of order. This not only lets the server make Quality of Service decision about what to return first, but it also means the client can now happily use a single TCP connection to make all their requests. As a result, the reduced memory, network and CPU load should be a big win for both the client and the server.

Stream

A bidirectional flow of bytes within an established connection, which may carry one or more messages.

Message

A complete sequence of frames that map to a logical request or response message.

Frame

The smallest unit of communication in HTTP/2, each containing a frame header, which at a minimum identifies the stream to which the frame belongs.

Why HTTP2?

The main focus of both SPDY and HTTP/2 is performance, especially latency as perceived by the end-user while using a browser, with a secondary focus on network and server resource usage. One large benefit of HTTP/2 is the ability to use a single TCP connection from a browser to a website.

Although HTTP/2 is based on Google's experimental SPDY protocol, it has evolved, incorporating several improvements in the process. Nevertheless, it maintains many of the benefits known from SPDY.

· Multiplexing and concurrency: Several requests can be sent over the same TCP connection, and responses can be received out of order, eliminating the need for multiple connections between the client and the server and reducing head-of-line blocking.

· Stream dependencies: The client can indicate to the server which resources are more important than others.

· Header compression: HTTP header size is reduced.

· Server push: The server can send resources the client has not yet requested

Relation of SPDY (deprecated) with HTTP

SPDY does not replace HTTP; it modifies the way HTTP requests and responses are sent over the wire.[1] This means that all existing server-side applications can be used without modification if a SPDY-compatible translation layer is put in place.

SPDY is effectively a tunnel for the HTTP and HTTPS protocols. When sent over SPDY, HTTP requests are processed, tokenized, simplified and compressed. For example, each SPDY endpoint keeps track of which headers have been sent in past requests and can avoid resending the headers that have not changed; those that must be sent are compressed.

In February 2015, Google announced its plans to remove support for SPDY in favor of HTTP/2.

On February 11, 2016, Google announced that Chrome will no longer support SPDY.

Upgrading HTTP to HTTP2

If a client is connecting to a server and does not have prior knowledge that it supports HTTP/2, it can connect via HTTP/1 and request upgrading the connection to HTTP/2 if available.

This can happen in one of two ways:

If connecting over HTTP, the client should make a normal HTTP/1 request but additionally set some headers that inform the server it wishes to upgrade to HTTP/2 if available. If the server supports HTTP/2 (without encryption), it will respond with a 101 response (Switching protocols) and then start communicating over the connection in HTTP/2. If it does not support HTTP/2, the server effectively ignores the additional headers and processes the HTTP/1 request as normal.

If connecting over HTTPS, the protocol negotiation is handled by the TLS-ALPN extension, which causes the protocol to be decided during the TLS handshake.

HTTP/1.0

The HTTP protocol is based on a request/response paradigm.

A client establishes a connection with a server and sends a request to the server in the form of a request method, URI, and protocol version, followed by a MIME-like message containing request modifiers, client information, and possible body content.

The server responds with a status line, including the message's protocol version and a success or error code, followed by a MIME-like message containing server information, entity metainformation, and possible body content.

Message Types

HTTP messages consist of requests from client to server and responses from server to client.

HTTP-message = Simple-Request ; HTTP/0.9 messages

| Simple-Response

| Full-Request ; HTTP/1.0 messages

| Full-Response

Full-Request and Full-Response use the generic message format of RFC 822 [7] for transferring entities. Both messages may include optional header fields (also known as "headers") and an entity body. The entity body is separated from the headers by a null line (i.e., a line with nothing preceding the CRLF).

Full-Request = Request-Line

*( General-Header

| Request-Header

| Entity-Header )

CRLF

[ Entity-Body ]

Full-Response = Status-Line

*( General-Header

| Response-Header

| Entity-Header )

CRLF

[ Entity-Body ]

Request

A request message from a client to a server includes, within the first line of that message, the method to be applied to the resource, the identifier of the resource, and the protocol version in use.

There are two valid formats for an HTTP request:

Request = Simple-Request | Full-Request

Simple-Request = "GET" SP Request-URI CRLF

Full-Request = Request-Line

*( General-Header

| Request-Header

| Entity-Header )

CRLF

[ Entity-Body ]

If an HTTP/1.0 server receives a Simple-Request, it must respond with an HTTP/0.9 Simple-Response. An HTTP/1.0 client capable of receiving a Full-Response should never generate a Simple-Request.

Request-Line

It begins with a method token

The Method token indicates the method to be performed on the resource identified by the Request-URI. The method is case-sensitive.

Method = "GET"

| "HEAD"

| "POST"

| extension-method

extension-method = token

General-Header

There are a few header fields which have general applicability for both request and response messages, but which do not apply to the entity being transferred. These headers apply only to the message being transmitted.

General-Header = Date

| Pragma

Request-Header

The request header fields allow the client to pass additional information about the request, and about the client itself, to the server.

Request-Header = Authorization

| From

| If-Modified-Since

| Referer

| User-Agent

Entity-Header

Entity-Header fields define optional metainformation about the Entity-Body or, if no body is present, about the resource identified by the request.

Entity-Header = Allow

| Content-Encoding

| Content-Length

| Content-Type

| Expires

| Last-Modified

| extension-header

extension-header = HTTP-header

Entity-Body

The entity body (if any) sent with an HTTP request or response is in a format and encoding defined by the Entity-Header fields.

Entity-Body = *OCTET

Response

After receiving and interpreting a request message, a server responds in the form of an HTTP response message.

Response = Simple-Response | Full-Response

Simple-Response = [ Entity-Body ]

Full-Response = Status-Line

*( General-Header

| Response-Header

| Entity-Header )

CRLF

[ Entity-Body ]

Status-Line

The first line of a Full-Response message is the Status-Line, consisting of the protocol version followed by a numeric status code and its associated textual phrase

Status-Code = "200" ; OK

| "201" ; Created

| "202" ; Accepted

| "204" ; No Content

| "301" ; Moved Permanently

| "302" ; Moved Temporarily

| "304" ; Not Modified

| "400" ; Bad Request

| "401" ; Unauthorized

| "403" ; Forbidden

| "404" ; Not Found

| "500" ; Internal Server Error

| "501" ; Not Implemented

| "502" ; Bad Gateway

| "503" ; Service Unavailable

| extension-code

extension-code = 3DIGIT

Reason-Phrase = *<TEXT, excluding CR, LF>

Response-Header

The response header fields allow the server to pass additional information about the response which cannot be placed in the Status-Line.

Response-Header = Location

| Server

| WWW-Authenticate

Header Fields

This section defines the syntax and semantics of all commonly used HTTP/1.0 header fields.

Header Field Definitions

Allow

Authorization

Content-Encoding

Content-Length

Content-Type

Date

Expires

From

If-Modified-Since

Last-Modified

Location

Pragma

Referer

Server

User-Agent

WWW-Authenticate

HTTP/2

The basic protocol unit in HTTP/2 is a frame (Section 4.1). Each frame type serves a different purpose. For example, HEADERS and DATA frames form the basis of HTTP requests and responses, other frame types like SETTINGS, WINDOW_UPDATE, and PUSH_PROMISE are used in support of other HTTP/2 features.

Multiplexing of requests is achieved by having each HTTP request/response exchange associated with its own stream.Streams are largely independent of each other, so a blocked or stalled request or response does not prevent progress on other streams.

Flow control and prioritization ensure that it is possible to efficiently use multiplexed streams. Flow control helps to ensure that only data that can be used by a receiver is transmitted. Prioritization ensures that limited resources can be directed to the most important streams first.

HTTP/2 adds a new interaction mode whereby a server can push responses to a client. Server push allows a server to speculatively send data to a client that the server anticipates the client will need, trading off some network usage against a potential latency gain. The server does this by synthesizing a request, which it sends as a PUSH_PROMISE frame. The server is then able to send a response to the synthetic request on a separate stream.

Because HTTP header fields used in a connection can contain large amounts of redundant data, frames that contain them are compressed. This has especially advantageous impact upon request sizes in the common case, allowing many requests to be compressed into one packet.

HTTP Frames

Once the HTTP/2 connection is established, endpoints can begin exchanging frames.

All frames begin with a fixed 9-octet header followed by a variable-length payload.

+-----------------------------------------------+

| Length (24) |

+---------------+---------------+---------------+

| Type (8) | Flags (8) |

+-+-------------+---------------+-------------------------------+

|R| Stream Identifier (31) |

+=+=============================================================+

| Frame Payload (0...) ...

+---------------------------------------------------------------+

Figure 1: Frame Layout

The fields of the frame header are defined as:

Length: The length of the frame payload expressed as an unsigned 24-bit integer. Values greater than 2^14 (16,384) MUST NOT be sent unless the receiver has set a larger value for SETTINGS_MAX_FRAME_SIZE.

The 9 octets of the frame header are not included in this value.

Type: The 8-bit type of the frame. The frame type determines the format and semantics of the frame. Implementations MUST ignore and discard any frame that has a type that is unknown.

Flags: An 8-bit field reserved for boolean flags specific to the frame type.

Flags are assigned semantics specific to the indicated frame type. Flags that have no defined semantics for a particular frame type MUST be ignored and MUST be left unset (0x0) when sending.

R: A reserved 1-bit field. The semantics of this bit are undefined, and the bit MUST remain unset (0x0) when sending and MUST be ignored when receiving.

Stream Identifier: A stream identifier expressed as an unsigned 31-bit integer. The value 0x0 is reserved for frames that are associated with the connection as a whole as opposed to an individual stream.

The structure and content of the frame payload is dependent entirely on the frame type.

Frame Definitions

DATA

Carries the data in a request or response. DATA frames (type=0x0) convey arbitrary, variable-length sequences of octets associated with a stream.

HEADERS

The HEADERS frame (type=0x1) is used to open a stream, and additionally carries a header block fragment. HEADERS frames can be sent on a stream in the "idle", "reserved (local)", "open", or "half-closed (remote)" state.

PRIORITY

The PRIORITY frame (type=0x2) specifies the sender-advised priority of a stream.

Stream Dependency: A 31-bit stream identifier for the stream that this stream depends on.

Weight: An unsigned 8-bit integer representing a priority weight for the stream. Add one to the value to obtain a weight between 1 and 256.

Priority is a new concept that HTTP/2 introduces to allow a client to give priority preferences to particular streams. Priority is non binding, and a server is free to ignore it completely.

The priority mechanism is expressed in terms of stream dependencies and weights. A stream can be given a dependency on another stream, which tells the server that it should allocate resources to the identified stream instead of the dependent stream (conceptually all streams are considered to depend on another stream, streams with no explicit dependency depend on the virtual stream 0).

According to the spec a server should only allocate resources to a dependent stream if all its dependencies (and their dependencies) are either closed or it is not possible to make progress on them.

RST_STREAM

The RST_STREAM frame (type=0x3) allows for immediate termination of a stream. RST_STREAM is sent to request cancellation of a stream or to indicate that an error condition has occurred.

SETTINGS

The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints communicate, such as preferences and constraints on peer behavior. The SETTINGS frame is also used to acknowledge the receipt of those parameters.

SETTINGS Format .....................................

Defined SETTINGS Parameters ........................

Settings Synchronization ...........................

The specification defines the following settings:

SETTINGS_HEADER_TABLE_SIZE

The maximum allowed size of the HPACK header table. Defaults to 4,096.

SETTINGS_ENABLE_PUSH

A setting that is sent from the client to the server, if this is enabled then the server is allowed to push responses to the client, default to true.

SETTINGS_MAX_CONCURRENT_STREAMS

The maximum number of concurrent streams that can be opened, basically this corresponds to the number of requests that can be active at the same time. By default this is unlimited.

SETTINGS_INITIAL_WINDOW_SIZE

The initial window size that is used for flow control. Defaults to 65,535.

SETTINGS_MAX_FRAME_SIZE

The maximum allowed frame size that the remote endpoint is prepared to accept. Defaults to 16,384.

SETTINGS_MAX_HEADER_LIST_SIZE

This setting advises the remote endpoint of the maximum size of the header list the remote endpoint will accept. The default value is unlimited.

PUSH_PROMISE

The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in advance of streams the sender intends to initiate. The PUSH_PROMISE frame includes the unsigned 31-bit identifier of the stream the endpoint plans to create along with a set of headers that provide additional context for the stream.

Server Push

First introduced in the SPDY protocol, server push allows a server to send unsolicited request+response pairs to a client. Generally this will be used to immediately begin sending resources that a server expects a client based on the current request. For example if a client requests /index.html, and the server knows that /index.html contains a reference to /logo.png the server might decide to immediately push logo.png rather than waiting for the client to request it.

HTTP/2 allows a server to pre-emptively send (or "push") responses (along with corresponding "promised" requests) to a client in association with a previous client-initiated request. This can be useful when the server knows the client will need to have those responses available in order to fully process the response to the original request.

A client can request that server push be disabled, though this is negotiated for each hop independently. The SETTINGS_ENABLE_PUSH setting can be set to 0 to indicate that server push is disabled.

PING

The PING frame (type=0x6) is a mechanism for measuring a minimal round-trip time from the sender, as well as determining whether an idle connection is still functional. PING frames can be sent from any endpoint.

GOAWAY

The GOAWAY frame (type=0x7) is used to initiate shutdown of a connection or to signal serious error conditions. GOAWAY allows an endpoint to gracefully stop accepting new streams while still finishing processing of previously established streams. This enables administrative actions, like server maintenance.

WINDOW_UPDATE

The WINDOW_UPDATE frame (type=0x8) is used to implement flow control. Flow control operates at two levels: on each individual stream and on the entire connection.

The Flow-Control Window ............................

Initial Flow-Control Window Size ...................

Reducing the Stream Window Size ....................

CONTINUATION

The CONTINUATION frame (type=0x9) is used to continue a sequence of header block fragments. Any number of CONTINUATION frames can be sent, as long as the preceding frame is on the same stream and is a HEADERS, PUSH_PROMISE, or CONTINUATION frame without the END_HEADERS flag set.

Features

Request and Response Multiplexing

With HTTP/1.x, if the client wants to make multiple parallel requests to improve performance, then multiple TCP connections must be used; see “Using Multiple TCP Connections”. This behavior is a direct consequence of the HTTP/1.x delivery model, which ensures that only one response can be delivered at a time (response queuing) per connection. Worse, this also results in head-of-line blocking and inefficient use of the underlying TCP connection.

The new binary framing layer in HTTP/2 removes these limitations, and enables full request and response multiplexing, by allowing the client and server to break down an HTTP message into independent frames, interleave them, and then reassemble them on the other end.

The snapshot captures multiple streams in flight within the same connection: the client is transmitting a DATA frame (stream 5) to the server, while the server is transmitting an interleaved sequence of frames to the client for streams 1 and 3. As a result, there are three parallel streams in flight!

The ability to break down an HTTP message into independent frames, interleave them, and then reassemble them on the other end is the single most important enhancement of HTTP/2. In fact, it introduces a ripple effect of numerous performance benefits across the entire stack of all web technologies, enabling us to:

Interleave multiple requests in parallel without blocking on any one

Interleave multiple responses in parallel without blocking on any one

Use a single connection to deliver multiple requests and responses in parallel

Remove unnecessary HTTP/1.x workarounds (see “Optimizing for HTTP/1.x”), such as concatenated files, image sprites, and domain sharding

Deliver lower page load times by eliminating unnecessary latency and improving utilization of available network capacity

And much more…

The new binary framing layer in HTTP/2 resolves the head-of-line blocking problem found in HTTP/1.x and eliminates the need for multiple connections to enable parallel processing and delivery of requests and responses. As a result, this makes our applications faster, simpler, and cheaper to deploy.

Binary Protocol

With all data sent over the connection being packed into frames, HTTP/2 has become a binary protocol. While this should be a big boost for machine processing, it will make it harder to debug requests over the wire. Tools like Telnet, just won’t cut it anymore.

While this may sound like a disadvantage of the protocol, increasing machine readability should not only help increase processing performance, but also will also help improve security. The text-based nature of HTTP/1 has been blamed for a few security issues in the past, ranging from Response Splitting to simply the complexity of knowing when a message ends.

Some tools have already announced support for the new HTTP/2 protocol, such as wireshark, and others are likely to follow. In reality, disruption for web developers will be likely be minimal.

Encryption

An interesting point, is that HTTP/2 was originally designed as an encryption only protocol. However, an outcry caused later revisions to support an optional plain-text version in addition to the encrypted form. But despite the removal of the encryption-only requirement, some browser vendors have said they will only implement the encrypted version of the protocol. At the time of writing, Firefox, Chrome and Internet Explorer all only have support for HTTP/2 when over TLS.

One side effect of the potential increase in encryption usage on the internet, is that it will make it impossible for ISPs to cache large common files more locally to users. Not only would this cause increased global network usage, but it could also cause increased load times for users, something the protocol was trying to reduce.

To combat this, a new concept called ‘Explicit Trusted Proxy’ was proposed, which is essentially a node along the connection which is allowed to decrypt and re-encrypt your traffic, for caching purposes. This has obviously caused a further outcry over privacy concerns, and while it currently does not have a resolution it looks unlikely the proposal will be adopted in its current state.

Stream Prioritization

Once an HTTP message can be split into many individual frames, and we allow for frames from multiple streams to be multiplexed, the order in which the frames are interleaved and delivered both by the client and server becomes a critical performance consideration. To facilitate this, the HTTP/2 standard allows each stream to have an associated weight and dependency:

· Each stream may be assigned an integer weight between 1 and 256

· Each stream may be given an explicit dependency on another stream

The combination of stream dependencies and weights allows the client to construct and communicate a "prioritization tree" (Figure 12-4) that expresses how it would prefer to receive the responses. In turn, the server can use this information to prioritize stream processing by controlling the allocation of CPU, memory, and other resources, and once the response data is available, allocation of bandwidth to ensure optimal delivery of high-priority responses to the client.

A stream dependency within HTTP/2 is declared by referencing the unique identifier of another stream as its parent; if omitted the stream is said to be dependent on the "root stream". Declaring a stream dependency indicates that, if possible, the parent stream should be allocated resources ahead of its dependencies - e.g. please process and deliver response D before response C.

Streams that share the same parent (i.e., sibling streams) should be allocated resources in proportion to their weight. For example, if stream A has a weight of 12 and its one sibling B has a weight of 4, then to determine the proportion of the resources that each of these streams should receive:

1. Sum all the weights: 4+12=164+12=16

2. Divide each stream weight by the total weight: A=12/16A=12/16, B=4/16B=4/16

Thus, stream A should receive three-quarters and stream B should receive one-quarter of available resources; stream B should receive one-third of the resources allocated to stream A. Let’s work through a few more hands-on examples. From left to right:

1. Neither stream A nor B specify a parent dependency and are said to be dependent on the implicit "root stream"; A has a weight of 12, and B has a weight of 4. Thus, based on proportional weights: stream B should receive one-third of the resources allocated to stream A.

2. D is dependent on the root stream; C is dependent on D. Thus, D should receive full allocation of resources ahead of C. The weights are inconsequential because C’s dependency communicates a stronger preference.

3. D should receive full allocation of resources ahead of C; C should receive full allocation of resources ahead of A and B; stream B should receive one-third of the resources allocated to stream A.

4. D should receive full allocation of resources ahead of E and C; E and C should receive equal allocation ahead of A and B; A and B should receive proportional allocation based on their weights.

As the above examples illustrate, the combination of stream dependencies and weights provides an expressive language for resource prioritization, which is a critical feature for improving browsing performance where we have many resource types with different dependencies and weights. Even better, the HTTP/2 protocol also allows the client to update these preferences at any point, which enables further optimizations in the browser - e.g. we can change dependencies and reallocate weights in response to user interaction and other signals.

Stream dependencies and weights express a transport preference, not a requirement, and as such do not guarantee a particular processing or transmission order. That is, the client cannot force the server to process the stream in particular order using stream prioritization. While this may seem counter-intuitive, it is, in fact, the desired behavior: we do not want to block the server from making progress on a lower priority resource if a higher priority resource is blocked.

Browser Request Prioritization and HTTP/2

Not all resources have equal priority when rendering a page in the browser: the HTML document itself is critical to construct the DOM; the CSS is required to construct the CSSOM; both DOM and CSSOM construction can be blocked on JavaScript resources (see “DOM, CSSOM, and JavaScript”); and remaining resources, such as images, are often fetched with lower priority.

To accelerate the load time of the page, all modern browsers prioritize requests based on type of asset, their location on the page, and even learned priority from previous visits—e.g., if the rendering was blocked on a certain asset in a previous visit, then the same asset may be prioritized higher in the future.

With HTTP/1.x, the browser has limited ability to leverage above priority data: the protocol does not support multiplexing, and there is no way to communicate request priority to the server. Instead, it must rely on the use of parallel connections, which enables limited parallelism of up to six requests per origin. As a result, requests are queued on the client until a connection is available, which adds unnecessary network latency. In theory, “HTTP Pipelining” tried to partially address this problem, but in practice it has failed to gain adoption.

HTTP/2 resolves these inefficiencies: request queuing and head-of-line blocking is eliminated because the browser can dispatch all requests the moment they are discovered, and the browser can communicate its stream prioritization preference via stream dependencies and weights, allowing the server to further optimize response delivery.

Packet Loss, high-RTT Links, and HTTP/2 Performance

Wait, I hear you say, we listed the benefits of using one TCP connection per origin but aren’t there some potential downsides? Yes, there are.

We have eliminated head-of-line blocking from HTTP, but there is still head-of-line blocking at the TCP level (see “Head-of-Line Blocking”).

Effects of bandwidth-delay product may limit connection throughput if TCP window scaling is disabled.

When packet loss occurs, the TCP congestion window size is reduced (see “Congestion Avoidance”), which reduces the maximum throughput of the entire connection.

Each of the items in this list may adversely affect both the throughput and latency performance of an HTTP/2 connection. However, despite these limitations, the move to multiple connections would result in its own performance tradeoffs:

Less effective header compression due to distinct compression contexts

Less effective request prioritization due to distinct TCP streams

Less effective utilization of each TCP stream and higher likelihood of congestion due to more competing flows

Increased resource overhead due to more TCP flows

The above pros and cons are not an exhaustive list, and it is always possible to construct specific scenarios where either one or more connections may prove to be beneficial. However, the experimental evidence of deploying HTTP/2 in the wild showed that a single connection is the preferred deployment strategy:

In tests so far, the negative effects of head-of-line blocking (especially in the presence of packet loss) is outweighed by the benefits of compression and prioritization.

-- Hypertext Transfer Protocol version 2 Draft 2

As with all performance optimization processes, the moment you remove one performance bottleneck, you unlock the next one. In the case of HTTP/2, TCP may be it. Which is why, once again, a well-tuned TCP stack on the server is such a critical optimization criteria for HTTP/2.

There is ongoing research to address these concerns and to improve TCP performance in general: TCP Fast Open, Proportional Rate Reduction, increased initial congestion window, and more. Having said that, it is important to acknowledge that HTTP/2, like its predecessors, does not mandate the use of TCP. Other transports, such as UDP, are not outside the realm of possibility as we look into the future.

HPACK

HTTP/2 introduces a form of header compression called HPACK. HPACK allows for very efficient header compression, without being vulnerable to compression related attacks such as CRIME. HPACK provides the following:

· The ability to encode large headers using a fixed Huffman encoding

· The ability to encode commonly used headers as a variable length integer, rather than re-sending the whole header each time

All headers sent via HTTP/2 (in HEADERS, CONTINUATION and PUSH_PROMISE frames) are sent in the HPACK format.

HPACK works by having both endpoints maintain a copy of a header table (the dynamic table). When an endpoint sends a header to the remote endpoint it can instruct the remote endpoint to store it in its dynamic table. If the endpoint needs to send the same header again it can just send its index in the dynamic table, instead of sending the whole header. The size of the dynamic table is limited to 4k by default, however larger or smaller limits can be set using a SETTINGS frame.

As many requests and responses will contain the same headers, this technique is very effective, as after the first request most headers will be represented as an integer index into the dynamic or static table.

HPACK also defines a static table which is a pre defined table of commonly used headers, so HPACK will provide some compression even before the dynamic table is populated.

HPACK also allows header names and values to be encoded via a fixed Huffman encoding. Because this encoding uses a fixed encoding table, it is not vulnerable to compression based attacks such as CRIME.

Pcaps

How-To capture decrypted HTTP2 packet using wire-shark is listed at blogs.

HTTP

HTTP2

SPDY

References

a. HTTP/2 RFC7540

b. HPACK - Header Compression for HTTP/2 - RFC7541

c. HTTP packetlife

d. SPDY wikipedia

e. HTTP2 explained more

f. HTTP2 depth overview

g. HTTP/1 specification

h. CWS HTTP2 Support

i. Introducing http2

j. Understanding SPDY

k. HTTP2 Quick Look

l. HTTP2 look

m. HTTP2 is here

n. Negotiating HTTP2