HTTP/1 to HTTP/2 to HTTP/3

Sandeep Verma
20 min readNov 2, 2019

--

It’s not about being the best, it’s about being better than you were yesterday.

Introduction

HTTP or The Hypertext Transfer Protocol is an application protocol that allows the fetching of resources, such as HTML documents. The first stable version of HTTP/1.1 was released in 1997 by Internet Engineering Task Force. Since then it has become the defacto standard of communication on the Web. When version 1.1 was released, the Web used to be quite different than what it is today. Now billions of users connect to the internet from different devices(Tablets, mobiles, desktop, etc.). They have disparate network speeds and resource or content requirements. HTTP/1.1 works suboptimally for today’s requirement and it required a major overhaul. After 18 long years, HTTP/2 was released by IETF to cater to present web needs and improve upon HTTP/1 deficiencies. However, just over 4 years since it’s (HTTP/2) launch, the world is looking for HTTP/3, which improves upon HTTP/2’s demerits.

This Article is not going to dig deeper into how HTTP works. Rather it will present the reasons behind moving from HTTP/1 to HTTP/2 and now to HTTP/3.

Limitations of HTTP/1.1

Fig.1 HTTP Network stack | Source: InfoQ

HTTP/1.1 release in 1997 was standardized back in 1999 (By adding keepalives, upgrades, ranges, and host). As I said in the introduction, the web has changed a lot since 1997 and demands much more from HTTP. Not only we have resource-rich websites(with thousands or millions of images), we also have much faster internet than what we had in the ’90s. A user now expects faster web page load, better security of the data that they transmit and good web browsing experience even when on poor networks(2G). HTTP/1.1 clearly failed to stand up for the new web requirements. The following issues with HTTP/1.1 forced the internet community to look for better communication protocol.

Problems with HTTP/1.1 :

  • HTTP (HOL)Head of Line Blocking problem
  • Non-implementation of requests pipelining for request multiplexing
  • Opening of multiple TCP connections for requesting multiple resources
  • Textual nature of data transfer
  • Long HTTP headers
  • Numerous Workarounds to overcome above HTTP problems(Domain sharding, Spriting, etc.)
  • Slow web page loading speed

Most of the above problems boil down to slow communication or slower web due to the way HTTP/1 is implemented. Let’s dig deeper and try to understand how and why HTTP/1.1 is inefficient in handling today’s requirements.

HTTP Head of Line Blocking (HOL) problem

HTTP Head of Line blocking in HTTP/1 refers to issue where browser/client has to wait for the requests prior to it to complete before it can fire it off another. The HTTP head of line requests blocks the subsequent ones on a single TCP connection.

A simple analogy is a platform on a railways station. If the platform is occupied by a train, all the trains that are behind are blocked until this train departs. Obviously, blocked trains can occupy other free platforms, but what if all other platforms are also occupied. This is what actually browsers do to speed up page loads with HTTP/1. They open multiple TCP connections and route pending requests through those TCP connections, but there is a limit to the number of TCP connections that can be opened and currently, this is 6 for chrome and Mozilla firefox.

What if a page requires more than 6 resources(Images, Js files, Html files, CSS, etc.)to completely load a page? This will clearly slow down a page load on the modern browser as requests beyond connection limits are forced to wait. Following is an illustration of how a single TCP connection on HTTP/1.x blocks subsequent requests and push another request only when one ahead in the line completes. First DNS lookup gets completed, then Socket connection request/response is allowed to finish. Afterwards, an HTTP request is sent and then finally content comes back in response. Moving from left to right is the timeline(Total 351 ms spent to complete this cycle)

Fig. 2 HTTP Head of Line Blocking | Source: MeanStack

Non-implementation of HTTP request pipelining

HTTP/1.1 introduced the concept of pipelining concurrent requests to be sent over the wire before receiving responses. This way a single TCP connection would have been able to send multiple requests for resources and also would have received multiple responses accordingly.

Fig.3 HTTP/1 with pipelining | Source: tunetheweb.com

The initial HTML still needs to be requested separately, but once the browser saw it needed two images and it could request them both one after the other. This is shown in Figure 3, and it shaves off 100ms — or a third of the time in this simple, hypothetical example.

Pipelining must have brought huge improvements to HTTP/1.x performance but, for a number of reasons, it was difficult to implement, easy to break, and not well supported on either web browser or web server sides.

Multiple TCP connections for requesting multiple resources

Fig.4 Multiple TCP connections | Source Internet

A browser or client can open multiple parallel connections to speed up page loads. This seems to be a good solution for the HTTP Head of Line Blocking problem but as revealed earlier maximum number of connections that can be opened up is limited. Moreover, opening a TCP connection itself takes some time which can further add to latency. Yes, we can maintain a connection pool or can have connections that are persistent, but this workaround doesn’t scale well.

Further, having multiple simultaneous TCP connections aggravates problems with wireless networks which are more constrained in size and scope of network bandwidth as compared to a wired network. As bandwidth is quite limited in a wireless network, number, and size of TCP connections should be carefully managed otherwise this is going to further degrade the performance. This is the reason why latency is more of an issue on wireless networks than wired ones.

If an application opens up multiple simultaneous TCP connections, the size of each connection will be smaller as bandwidth is limited on the wireless network. This implies lower throughput through each connection, thus an increase in latency decreased speed of resources download through each connection and bad application performance.

Textual nature of data transfer

Fig.5 HTTP/1.1 Textual request | Source : Internet

HTTP/1 is a textual data protocol and is good in terms of readability, ease of reimplementing, and ease of debugging. However, Binary protocols(Used in HTTP/2 and HTTP/3)are more compact. Following are the reasons to prefer binary data protocol over textual data protocol :

  • Binary is more compact, so more efficient over the network.
  • The textual data protocol is more error-prone as it has many “helpers” to deal with whitespace, capitalization, line endings, etc. The more complexity, the more chance of errors.
  • Binary protocols are more secure, as security concerns associated with textual attacks, such as splitting, are no longer relevant.

Long HTTP headers(Absence of header compression and headers reusability)

Fig.6 HTTP Headers | Source: Internet

Each request and response cycle in HTTP/1 include many HTTP headers. The number and size of these headers can be sometimes really large(No header compression). Since HTTP/1.1 sends all headers over the wire even in subsequent requests(No reuse), this not only adds load on network bandwidth but also increases the latency(We will see how what HTTP/2 and HTTP/3 does to cater this issue)

Numerous Workarounds to overcome HTTP problems

In order to tackle problems of HTTP Head of Line Blocking and issues with multiple TCP connections, numerous workarounds came into the picture. Domain sharding and spriting are few of those.

Domain Sharding

When a user connects to a web page, browsers or clients open up multiple TCP connections to the host(Limited to max connection limit). Usually, all these resources are downloaded from the same domain. To overcome this limitation, web developers move some content to multiple subdomains(domain sharding). This way the number of a browser can connect with multiple servers(domains, subdomains) simultaneously by opening TCP connections. For example, to download images, it could be served by images.domain.com and js.domain.com can serve js scripts.

This workaround though helps in serving multiple concurrent requests but it adds to the complexity of development, deployment, maintenance and overall cost to applications.

CSS Spriting

CSS Sprites are a means of combining multiple images into a single image file for use on a website and it helps with performance. This reduces the overhead of having to fetch multiple images. For example, in the below figure the overall size of there different images is 14.38KB. If we put all the three images into a single file, then the overall size will be 16.1KB. So with sprite, we end up an additional size of 1.72KB larger than original combined sizes of three images. Creating a single files helps in faster loads as browser limits the number of concurrent requests a file can make and also opening a new TCP connection takes time(7 step SSL handshake)

Fig. 7 Images of countries and their sizes| Source: css-tricks.com

Slow web page loading speed

In HTTP/1.1 server only responds to the requests. It neither pushes contents on it's nor it prioritizes the content to be sent prior to others(A page can have some content of top priority which it needs to load first and then subsequently other resources). This along with HTTP Head of Line Blocking, large headers, limits to TCP connection and absence of request multiplexing cumulatively result in slow web page loads and suboptimal web application performance.

Moreover, HTTP/1.1 requires multiple expensive TLS handshakes for each connection. This further adds to latency and slowness of page load.

HTTP/2 reduces the amount of time the user sees between making a page request and when it is rendered. The original HTTP/2 draft was based on SPDY, a protocol previously developed by Google. If you are already familiar with SPDY, you will see many similarities in the HTTP/2 specification. Let’s explore what is HTTP/2 and how it overcomes the limitation of HTTP/1.1

HTTP/2

HTTP/2 enables a more efficient use of network resources and a reduced perception of latency by introducing header field compression and allowing multiple concurrent exchanges on the same connection… Specifically, it allows interleaving of request and response messages on the same connection and uses an efficient coding for HTTP header fields. It also allows prioritization of requests, letting more important requests complete more quickly, further improving performance.

The resulting protocol is more friendly to the network, because fewer TCP connections can be used in comparison to HTTP/1.x. This means less competition with other flows, and longer-lived connections, which in turn leads to better utilization of available network capacity. Finally, HTTP/2 also enables more efficient processing of messages through use of binary message framing.

Hypertext Transfer Protocol version 2, Draft 17

If you read through the above HTTP/2 draft statement, you can find the resolution of almost all limitations associated with HTTP/1 protocol. Before we jump into HTTP/2, we need to familiarize ourselves with different terms that are used in the world of HTTP/2.

HTTP/2 Terminologies

Stream: A bidirectional flow of bytes within an established TCP 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.

  • All communication is performed over a single TCP connection that can carry any number of bidirectional streams.
  • Each stream has a unique identifier and optional priority information that is used to carry bidirectional messages.
  • Each message is a logical HTTP message, such as a request, or response, which consists of one or more frames.
  • The frame is the smallest unit of communication that carries a specific type of data — e.g., HTTP headers, message payload, and so on. Frames from different streams may be interleaved and then reassembled via the embedded stream identifier in the header of each frame.

In short, HTTP/2 breaks down the HTTP protocol communication into an exchange of binary-encoded frames, which are then mapped to messages that belong to a particular stream, and all of which are multiplexed within a single TCP connection. This is the foundation that enables all other features and performance optimizations provided by the HTTP/2 protocol.

Frames -> Messages -> Streams -> A single TCP connection

Features of HTTP/2

  • It’s a binary protocol instead of textual, thus eliminating security concerns associated with the textual nature of HTTP1.x such as response splitting attacks
  • HTTP/2 is fully multiplexed
  • It used header compression HPACK to reduce the overhead size
  • It allows servers to “push” responses proactively into client caches instead of waiting for a new request for each resource
  • It reduces additional round trip times (RTT), making your website load faster without any optimization.
  • HTTP/2 supports response prioritization, flow control and effective handling of TLS
  • Low overhead in parsing data — a critical value proposition in HTTP/2 vs HTTP1.
  • Reduced network latency and improved throughput
  • Less prone to errors and lighter network footprint
  • It’s widely supported by browsers. As a basic internet technology, protocol HTTP/2 must be supported by the current version of your browser to work well

HTTP/2: Binary Protocol

All data in HTTP/2 is packed into frames, which is represented in binary, thus HTTP/2 is rightly called a binary protocol. This makes harder to debug request over the wire and would make Telnet useless.

But binary representation makes it machine-readable and results in increased performance and improved overall security. The text-based protocol (HTTP/1.x) is prone to Response Splitting and the complexity of finding out the end of the message. Moreover, Wireshark already has support to HTTP/2 and others are likely to follow. Thus the impact on web development due to HTTP/2 was quite minimal.

Fig. 8 HTTP/2 Binary Protocol | Source: Internet

Multiplexing and Streams

With HTTP/1.x client needs to open multiple TCP connections to send concurrent requests. Due to the HTTP head of line blocking, only one request or response can be in transit at a time through a single TCP connection.

The streams of HTTP/2 is a bi-directional sequence of frames that share a common identifier (a stream id). They remove the limitations of HTTP/1.x by allowing full request and response multiplexing. The client and Server break down the HTTP message into independent frames, interleaves them and then reassembles it at the other end. A single TCP connection can have hundreds of streams.

Fig. 9 HTTP Message broken down into frames (DATA and HEADERS frame) | Source: Internet
Fig. 10 HTTP/2 request and response multiplexing within a shared connection | Source: hpbn.co
Fig. 11 Streams and frames HTTP/2 | Source: Internet

The above figure has three parallel streams(stream 1, stream 3 and stream 5) in a single connection. While the client is transmitting a DATA frame to the server(Over stream 5) the server, on the other hand, is transmitting an interleaved sequence of frames to the client over stream 1 and stream 3.

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/responses in parallel without blocking on any one.

Moreover, a single TCP connection can deliver multiple requests/responses simultaneously. Furthermore, no more workarounds of HTTP/1.x like domain sharding or image spriting. Multiplexing also lower page load times by eliminating latencies due to expensive TLS handshake over multiple TCP connections. It also improves upon available network capacity which is quite important in wireless networks.

Header Compression

Each HTTP request/response requires a set of headers. In HTTP/1.x this is always sent as plain text and requires 500–800 bytes of overhead and some additions KB’s if it includes HTTP cookies. HTTP/2 compresses headers in each transfer using HPACK compression thus reducing the size of this overhead metadata and improves performance.

HPACK compression allows the individual values to be compressed when transferred, and the indexed list of previously transferred values allows us to encode duplicate values by transferring index values that can be used to efficiently look up and reconstruct the full header keys and values.

Reduced size of headers due to compression along encoding and caching, results in improved performance with HTTP/2

Fig. 12 HTTP/2 HPACK compression: Source Internet

Server Push

Another powerful new feature of HTTP/2 is the ability of the server to send multiple responses for a single client request. That is, in addition to the response to the original request, the server can push additional resources to the client without the client having to request each one explicitly.

Since a single connection is now kept open and used for all (bi-directional) communication, it also enables the server to push content to the client. This is achieved by the server sending a push promise frame to the client (on a new stream), which as the names suggest is a notification it is about to be sent a resource without requesting it.

Fig. 13 Sequence diagram of Request/Response in different HTTP protocols | Source : blog.scottlogic.com

This may also lead to additional optimizations, as the server has the best information about which resources are the most important, even more so than the client.

Stream prioritization

An HTTP/2 message consists of many individual frames(DATA, HEADER frames). These frames from multiple streams are interleaved(multiplexed). The order in which these frames are delivered is critical to app performance. For example, when a user requests for a home timeline on a social networking website like facebook, his last three posts should be rendered first and then his all other posts. This prioritization of content can be done HTTP/2.

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” that expresses how it would prefer to receive 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, the allocation of bandwidth to ensure optimal delivery of high-priority responses to the client. This way backend server of facebook can add the first three posts higher in prioritization tree, thus giving a rich user experience.

Flow Control

The server push indeed improves the performance of HTTP/2 but it can also lead to performance problems on the receiver end. If the receiver doesn’t want data from the server and server still pushes it, it will consume network bandwidth of the receiver and in case the receiver is under high load, the server push will further aggravate the problem.

For example, the client may have requested a large video stream with high priority, but the user has paused the video and the client now wants to pause or throttle its delivery from the server to avoid fetching and buffering unnecessary data. Alternatively, a proxy server may have a fast downstream and slow upstream connections and similarly wants to regulate how quickly the downstream delivers data to match the speed of upstream to control its resource usage; and so on.

Does this sound like TCP flow control? The above problem is effectively identical to TCP flow control and requires Flow control with HTTP/2 too.

HTTP/2 does not specify any particular algorithm for implementing flow control. Instead, it provides the simple building blocks and defers the implementation to the client and server, which can use it to implement custom strategies to regulate resource use and allocation, as well as implement new delivery capabilities that may help improve both the real and perceived performance

HTTP/2 support by browsers

Fig.14 HTTP/2 support by different browsers (Number indicate first supported version)| Source: Internet

Problems with HTTP/2

HTTP/2 makes better use of network bandwidth by sending multiple HTTP requests over the same connection. Thus allowing application process requests concurrently. This resolved the HTTP head-of-line problem of HTTP/1.x but HTTP/2 gave rise to another problem, TCP head-of-line blocking. Moreover, Stream reuse attack, HTTP/2 flow control security hazard are other known issues with HTTP/2.

TCP head-of-line blocking

With HTTP/2 you can maximize your throughput and bandwidth because TCP will work out the maximum speed it can go and all the parallel connections go at the fastest speed they can.

That’s great until there’s a hiccup in the network connection, like network congestion or moving from one cell to another on the mobile network and when a packet gets lost. “TCP guarantees that the order in which packets are sent is the order in which received by the app — so if you miss one, everything has to stop until that particular packet gets retransmitted. If you multiplex multiple requests onto a single TCP connection, then all those requests have to stop and wait even though the lost packet might affect only one of them.

This TCP head of line blocking problem is inherent to TCP and UDP fixes it by allowing the application to control the retransmission of packets. Ideally, a missing packet should have affected only the stream from which packet was lost, but instead, it blocks all other streams. This makes HTTP/2 highly unreliable and worse performant in poor network conditions.

Stream reuse attack

The Stream Multiplexing mechanism tunnels multiple sessions through a single HTTP/2 connection. The risk in this mechanism stems from the fact that the partition of the connection is purely logical, and as such can be used to manipulate the server or to send frames out of context. Stream Reuse on IIS HTTP/2 stream represents one request-response cycle and once closed, the stream identifier is not supposed to be used over the same connection. But this was vulnerability can be exploited to execute arbitrary code on IIS HTTP/2 stream

HTTP/2 flow control security hazard

RFC explicitly marked the flow control feature as a security hazard. The HTTP/2 window mechanism resembles the TCP window mechanisms that were the target of many attacks in the past, including zero-window and slow read attacks. When reducing or even resetting the inbound window size while asking for a large resource, the sender may keep the connection open for a long or even unlimited period, and consumes the server resources. Thus, it was reasonable to believe that the new implementation of this mechanism in HTTP/2 would suffer the same problems.

HTTP/3

HTTP/2 was a major overhaul from HTTP/1.x and it certainly improved the speed of the web. It has provided some great new features that cater to the need of the web that we have today. Yet it is not the silver bullet. HTTP/2 has its own set of problems and the biggest one was the TCP head-of-line blocking problem which made usage of HTTP/2 highly problematic in countries with poor networks.

HTTP/3 Protocol

HTTP/3 instead of using TCP, use Google’s QUIC protocol. HTTP/3 was initially known as HTTP-over-QUIC. HTTP/3 also includes TLS 1.3 encryption, so there’s no need for a separate HTTPS that bolts security onto the protocol, as there is today.

QUIC originally stood for “Quick UDP Internet Connections.” This protocol is designed to be faster with lower latency than TCP. QUIC offers less overhead when establishing a connection and quicker data transfers over the connection. Unlike TCP, an error like a piece of data that gets lost along the way won’t cause the connection to stop and wait for the problem to be fixed. QUIC will keep transferring other data while the issue is being resolved.

In fact, QUIC was added to Google Chrome back in 2013. Chrome uses it when communicating with Google services and some other websites like Facebook, and it’s available to Android applications. But QUIC isn’t a standard integrated into other web browsers. With HTTP/3 the technology is coming in a standard way to other browsers, too.

Fig. 15 Stacks of HTTP | Sources: Internet

HTTP/3 QUIC

QUIC is also designed to be very fast. By offering 0-RTT and 1-RTT (Round Trip Time) handshakes against the TCP 3-way handshakes, the transfer process of QUIC is very fast. QUIC is highly reliable, due to its support of the aforementioned additional streams, meaning that data transmission is assured with greater speed and accuracy. This reliability, combined with speed, offers superior congestion control and stream re-transmission. In fact, the main issue raised against HTTP/3 — the fact that it utilizes UDP, a relatively unreliable transport method — is largely negated by these facets.

Additionally, the fact that QUIC has been developed for implementation in the user space is also notable. This means that, unlike protocols built into the OS or firmware level, QUIC can iterate rather quickly and effectively without having to deal with the entrenchment of each protocol version. This is a big deal for such a large protocol, and in many ways should be considered a core feature in its own right.

HTTP/3 Feature comparison

Fig. 16 HTTP/2 vs HTTP/3 Feature comparison
Fig. 16 HTTP/3 comparison with HTTP/2

In summary: HTTP/3 is a newer, better, faster protocol. It’s a more modern solution that should deliver improved security and speed to the web.

HTTP Versions release timelines

  • HTTP 0.9 — Time Berners-Lee released the first documented version of HTTP in 1991. It consisted of a single line containing a GET method and the path of the requested document. The response was just as simple, returning a single hypertext document without headers or any other metadata.
  • HTTP 1.0 — Version 1.0 received official recognition in 1996, and coincided with the rapid evolution of the HTML specification, and the “web browser.”The main addition was “request headers” and “response headers.” Also, the new response headers allowed multiple file types, such as HTML, plain text, images, and more.
  • HTTP 1.1 — Version 1.1 was released in 1997 and became the Internet Standard. This version added many performance enhancements, such as keepalive connections, caching mechanisms, request pipelining, transfer encodings, and byte-range requests. This new version was better and removed many of the ambiguities found in HTTP/1.0.
  • HTTP 2.0 — Released in February 2015 by the Internet Engineering Task Force (IETF) focussed on improving the performance of HTTP. This article focuses on the major changes of this version in more detail.
  • HTTP 3 — The new HTTP/3, based on the QUIC protocol, is anticipated to be released in late 2019. I discuss HTTP/3 briefly at the end of this article.

Don’t forget to clap if you enjoyed reading this article!

References :

https://www.upwork.com/hiring/development/the-http2-protocol-its-pros-cons-and-how-to-start-using-it/

https://hpbn.co/http2

https://nordicapis.com/what-is-coming-in-http-3-quic/

--

--