RFC 7230
Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
RFC 7230 ๐ Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
okay bestie, let's get into it ๐ this is RFC 7230, and it's part 1 of 20, so grab a snack ๐
- Number and title: RFC 7230, "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing" ๐ฆ
- Authors: R. Fielding, Ed. (Adobe) and J. Reschke, Ed. (greenbytes) ๐ซถ
- Category: Standards Track, which means it's an official Internet standard โจ
- Date: June 2014
- ISSN: 2070-1721
- Obsoletes: RFC 2145 and RFC 2616, so those older versions are retired ๐
- Updates: RFC 2817 and RFC 2818 ๐ฅ
Abstract โจ
okay so HTTP is a stateless application-level protocol ๐ It's built for distributed, collaborative, hypertext information systems, which is the whole reason the web works ๐ This doc gives you an overview of the HTTP architecture and its terminology, defines the "http" and "https" Uniform Resource Identifier (URI) schemes, lays out the HTTP/1.1 message syntax and parsing requirements, and talks about the security concerns implementers need to care about ๐
Status of This Memo ๐
this one is an Internet Standards Track document ๐
it's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community ๐ซถ It got public review and was approved for publication by the Internet Engineering Steering Group (IESG) โ If you want to know more about how Internet Standards work, check Section 2 of RFC 5741 ๐ง
for the current status, any errata, or to send feedback, go to http://www.rfc-editor.org/info/rfc7230 ๐
Copyright Notice ๐ธ
copyright (c) 2014 IETF Trust and the persons identified as the document authors, all rights reserved ๐
this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they were on the date it was published ๐ Please actually read those, because they spell out your rights and restrictions ๐ซ Code components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, same as the Simplified BSD License says ๐
heads up, this doc might include material from IETF Documents or IETF Contributions published before November 10, 2008 ๐ญ The people who control the copyright on some of that stuff may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process ๐ So unless you get a proper license from them, this document may not be modified outside the IETF Standards Process, and derivative works may not be created outside it either. The exceptions are formatting it for publication as an RFC or translating it into languages other than English ๐
Table of Contents ๐ง
here's the whole map, copied exactly so you can find your way around โจ
1. Introduction ....................................................5
1.1. Requirements Notation ......................................6
1.2. Syntax Notation ............................................6
2. Architecture ....................................................6
2.1. Client/Server Messaging ....................................7
2.2. Implementation Diversity ...................................8
2.3. Intermediaries .............................................9
2.4. Caches ....................................................11
2.5. Conformance and Error Handling ............................12
2.6. Protocol Versioning .......................................13
2.7. Uniform Resource Identifiers ..............................16
2.7.1. http URI Scheme ....................................17
2.7.2. https URI Scheme ...................................18
2.7.3. http and https URI Normalization and Comparison ....19
3. Message Format .................................................19
3.1. Start Line ................................................20
3.1.1. Request Line .......................................21
3.1.2. Status Line ........................................22
3.2. Header Fields .............................................22
3.2.1. Field Extensibility ................................23
3.2.2. Field Order ........................................23
3.2.3. Whitespace .........................................24
3.2.4. Field Parsing ......................................25
3.2.5. Field Limits .......................................26
3.2.6. Field Value Components .............................27
3.3. Message Body ..............................................28
3.3.1. Transfer-Encoding ..................................28
3.3.2. Content-Length .....................................30
3.3.3. Message Body Length ................................32
3.4. Handling Incomplete Messages ..............................34
3.5. Message Parsing Robustness ................................34
4. Transfer Codings ...............................................35
4.1. Chunked Transfer Coding ...................................36
4.1.1. Chunk Extensions ...................................36
4.1.2. Chunked Trailer Part ...............................37
4.1.3. Decoding Chunked ...................................38
4.2. Compression Codings .......................................38
4.2.1. Compress Coding ....................................38
4.2.2. Deflate Coding .....................................38
4.2.3. Gzip Coding ........................................39
4.3. TE ........................................................39
4.4. Trailer ...................................................40
5. Message Routing ................................................40
5.1. Identifying a Target Resource .............................40
5.2. Connecting Inbound ........................................41
5.3. Request Target ............................................41
5.3.1. origin-form ........................................42
5.3.2. absolute-form ......................................42
5.3.3. authority-form .....................................43
5.3.4. asterisk-form ......................................43
5.4. Host ......................................................44
5.5. Effective Request URI .....................................45
5.6. Associating a Response to a Request .......................46
5.7. Message Forwarding ........................................47
5.7.1. Via ................................................47
5.7.2. Transformations ....................................49
6. Connection Management ..........................................50
6.1. Connection ................................................51
6.2. Establishment .............................................52
6.3. Persistence ...............................................52
6.3.1. Retrying Requests ..................................53
6.3.2. Pipelining .........................................54
6.4. Concurrency ...............................................55
6.5. Failures and Timeouts .....................................55
6.6. Tear-down .................................................56
6.7. Upgrade ...................................................57
7. ABNF List Extension: #rule .....................................59
8. IANA Considerations ............................................61
8.1. Header Field Registration .................................61
8.2. URI Scheme Registration ...................................62
8.3. Internet Media Type Registration ..........................62
8.3.1. Internet Media Type message/http ...................62
8.3.2. Internet Media Type application/http ...............63
8.4. Transfer Coding Registry ..................................64
8.4.1. Procedure ..........................................65
8.4.2. Registration .......................................65
8.5. Content Coding Registration ...............................66
8.6. Upgrade Token Registry ....................................66
8.6.1. Procedure ..........................................66
8.6.2. Upgrade Token Registration .........................67
9. Security Considerations ........................................67
9.1. Establishing Authority ....................................67
9.2. Risks of Intermediaries ...................................68
9.3. Attacks via Protocol Element Length .......................69
9.4. Response Splitting ........................................69
9.5. Request Smuggling .........................................70
9.6. Message Integrity .........................................70
9.7. Message Confidentiality ...................................71
9.8. Privacy of Server Log Information .........................71
10. Acknowledgments ...............................................72
11. References ....................................................74
11.1. Normative References .....................................74
11.2. Informative References ...................................75
Appendix A. HTTP Version History ..................................78
A.1. Changes from HTTP/1.0 ....................................78
A.1.1. Multihomed Web Servers ............................78
A.1.2. Keep-Alive Connections ............................79
A.1.3. Introduction of Transfer-Encoding .................79
A.2. Changes from RFC 2616 ....................................80
Appendix B. Collected ABNF ........................................82
Index .............................................................85
okay that's the front matter and the map ๐บ๏ธโจ Part 2 picks up with the actual good stuff, starting at Section 1 ๐ฆ See you there, bestie ๐
1. Introduction ๐
Okay bestie, so the Hypertext Transfer Protocol (HTTP) is a stateless, application-level request/response protocol. It uses extensible semantics and self-descriptive message payloads so you can interact with network-based hypertext information systems in super flexible ways ๐ฆ. This document is the first in a series that together make up the HTTP/1.1 specification:
- "Message Syntax and Routing" (this document) โจ
- "Semantics and Content" [RFC7231]
- "Conditional Requests" [RFC7232]
- "Range Requests" [RFC7233]
- "Caching" [RFC7234]
- "Authentication" [RFC7235]
This HTTP/1.1 specification obsoletes RFC 2616 and RFC 2145 (on HTTP versioning) ๐๏ธ. It also updates the use of CONNECT to establish a tunnel, which was previously defined in RFC 2817, and it defines the "https" URI scheme that was only described informally in RFC 2818 ๐.
HTTP is a generic interface protocol for information systems ๐ธ. It's built to hide the messy details of how a service is implemented by giving clients a uniform interface that doesn't depend on what kind of resource they're asking for. Servers don't need to know each client's purpose either. An HTTP request can be looked at on its own, instead of being tied to one specific type of client or a fixed sequence of application steps. The result is a protocol that works in tons of different contexts and whose implementations can evolve independently over time ๐ง.
HTTP is also designed to be an intermediation protocol, meaning it can translate communication to and from non-HTTP information systems ๐. HTTP proxies and gateways can open up access to other information services by translating their different protocols into a hypertext format. Clients can then view and manipulate those services the same way they would any HTTP service ๐ .
One consequence of all this flexibility is that the protocol can't be defined in terms of what happens behind the interface ๐. Instead, we only define the syntax of communication, the intent of received communication, and the behavior that recipients are expected to show. If you look at a communication on its own, successful actions ought to show up as matching changes to the observable interface provided by servers. But since multiple clients might act in parallel, and maybe even at cross-purposes, we can't require those changes to be observable beyond the scope of a single response ๐.
This document describes the architectural elements used or referred to in HTTP โจ. It defines the "http" and "https" URI schemes, describes overall network operation and connection management, and defines HTTP message framing and forwarding requirements ๐ฆ. Our goal is to define every mechanism needed for HTTP message handling that doesn't depend on message semantics. That gives us the complete set of requirements for message parsers and message-forwarding intermediaries, which is honestly iconic ๐.
1.1. Requirements Notation
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] ๐.
Conformance criteria and considerations about error handling are defined in Section 2.5 ๐.
1.2. Syntax Notation
This specification uses the Augmented Backus-Naur Form (ABNF) notation of [RFC5234]. It comes with a list extension, defined in Section 7, that lets you define comma-separated lists compactly using a '#' operator. It works kind of like how the '*' operator shows repetition ๐ง. Appendix B shows the collected grammar with all the list operators expanded into standard ABNF notation.
The following core rules are included by reference, as defined in [RFC5234], Appendix B.1 ๐:
- ALPHA (letters)
- CR (carriage return)
- CRLF (CR LF)
- CTL (controls)
- DIGIT (decimal 0-9)
- DQUOTE (double quote)
- HEXDIG (hexadecimal 0-9/A-F/a-f)
- HTAB (horizontal tab)
- LF (line feed)
- OCTET (any 8-bit sequence of data)
- SP (space)
- VCHAR (any visible [USASCII] character)
By convention, ABNF rule names prefixed with "obs-" denote "obsolete" grammar rules that stick around for historical reasons ๐ฐ๏ธ.
2. Architecture ๐๏ธ
HTTP was created for the World Wide Web (WWW) architecture, and it has evolved over time to support the scalability needs of a worldwide hypertext system ๐. A lot of that architecture is reflected in the terminology and syntax productions used to define HTTP, so it's all connected ๐.
2.1. Client/Server Messaging
HTTP is a stateless request/response protocol. It works by exchanging messages (Section 3) across a reliable transport- or session-layer "connection" (Section 6) ๐จ. An HTTP "client" is a program that establishes a connection to a server so it can send one or more HTTP requests. An HTTP "server" is a program that accepts connections so it can service HTTP requests by sending HTTP responses ๐ค.
The terms "client" and "server" only refer to the roles these programs play for a particular connection. The same program might be a client on some connections and a server on others ๐. The term "user agent" refers to any of the various client programs that initiate a request, including (but not limited to) browsers, spiders (web-based robots), command-line tools, custom applications, and mobile apps ๐ฑ. The term "origin server" refers to the program that can originate authoritative responses for a given target resource ๐. The terms "sender" and "recipient" refer to any implementation that sends or receives a given message, respectively ๐.
HTTP relies on the Uniform Resource Identifier (URI) standard [RFC3986] to indicate the target resource (Section 5.1) and the relationships between resources ๐. Messages are passed in a format similar to what's used for Internet mail [RFC5322] and the Multipurpose Internet Mail Extensions (MIME) [RFC2045]. (See Appendix A of [RFC7231] for the differences between HTTP and MIME messages.) ๐
Most HTTP communication is a retrieval request (GET) for a representation of some resource identified by a URI ๐ฅฐ. In the simplest case, this might happen over a single bidirectional connection (===) between the user agent (UA) and the origin server (O) ๐ฆ:
request >
UA ======================================= O
< response
A client sends an HTTP request to a server in the form of a request message. That message begins with a request-line that includes a method, a URI, and the protocol version (Section 3.1.1). It's followed by header fields containing request modifiers, client information, and representation metadata (Section 3.2). Then comes an empty line to mark the end of the header section, and finally a message body holding the payload body, if there is one (Section 3.3) ๐.
A server responds to a client's request by sending one or more HTTP response messages. Each one begins with a status line that includes the protocol version, a success or error code, and a textual reason phrase (Section 3.1.2) ๐ฆ. That might be followed by header fields containing server information, resource metadata, and representation metadata (Section 3.2). Then there's an empty line to indicate the end of the header section, and finally a message body with the payload body, if any (Section 3.3) ๐.
A connection might be used for multiple request/response exchanges, as defined in Section 6.3 ๐.
Here's a typical message exchange for a GET request (Section 4.3.1 of [RFC7231]) on the URI "http://www.example.com/hello.txt" ๐ง:
Client request:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
Server response:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
Hello World! My payload includes a trailing CRLF.
2.2. Implementation Diversity
When you're designing HTTP, it's really easy to fall into the trap of thinking every user agent is a general-purpose browser and every origin server is a big public website ๐. That's not how it works in practice! Common HTTP user agents include household appliances, stereos, scales, firmware update scripts, command-line programs, mobile apps, and communication devices in a whole multitude of shapes and sizes ๐. Common HTTP origin servers are just as wild, like home automation units, configurable networking components, office machines, autonomous robots, news feeds, traffic cameras, ad selectors, and video-delivery platforms ๐ฅโจ.
The term "user agent" doesn't mean a human is directly interacting with the software at the time of a request ๐ค. In lots of cases, a user agent is installed or configured to run in the background and save its results for later inspection, or save only the subset of results that might be interesting or erroneous ๐พ. Spiders, for example, are usually given a start URI and configured to follow certain behavior while crawling the Web as a hypertext graph ๐ธ๏ธ.
The implementation diversity of HTTP means not every user agent can make interactive suggestions to its user or give adequate warnings about security or privacy concerns ๐ฌ. In the few cases where this specification requires reporting errors to the user, it's acceptable for that reporting to only be observable in an error console or log file ๐ชต. Likewise, requirements that an automated action be confirmed by the user before proceeding might be met through advance configuration choices, run-time options, or simply avoiding the unsafe action in the first place. Confirmation doesn't imply any specific user interface or any interruption of normal processing if the user has already made that choice ๐.
2.3. Intermediaries โจ
okay so HTTP lets you bounce a request through a whole chain of connections, bestie ๐ฆ there are three common middle-person types: proxy, gateway, and tunnel. sometimes one intermediary is a total shapeshifter and acts as an origin server, proxy, gateway, or tunnel depending on each request ๐
> > > >
UA =========== A =========== B =========== C =========== O
< < < <
in the figure above there are three intermediaries (A, B, and C) sitting between the user agent and the origin server ๐ธ a request or response that goes the whole way crosses four separate connections. some HTTP options only apply to the connection with the nearest non-tunnel neighbor, some only to the two endpoints of the chain, and some to every connection along the way ๐ the diagram looks linear, but everyone can be juggling several conversations at once. like, B might be getting requests from loads of clients other than A and forwarding stuff to servers other than C, all while it's handling A's request ๐ญ and later requests might take a totally different path, often because of dynamic config for load balancing ๐ง
the terms "upstream" and "downstream" describe directional requirements based on the message flow: all messages flow from upstream to downstream ๐ the terms "inbound" and "outbound" describe directional requirements based on the request route. "inbound" means toward the origin server, and "outbound" means toward the user agent ๐
a "proxy" is a message-forwarding agent that the client picks, usually through local configuration rules, to receive requests for some type(s) of absolute URI and try to satisfy them by translating through the HTTP interface โจ some translations are minimal, like proxy requests for "http" URIs, while other requests might need translating to and from totally different application-level protocols ๐ proxies are often used to route an organization's HTTP requests through one common intermediary for security, annotation services, or shared caching ๐ซถ some proxies even apply transformations to selected messages or payloads while they're being forwarded, as described in Section 5.7.2 ๐
a "gateway" (a.k.a. "reverse proxy") is an intermediary that acts as an origin server for the outbound connection, but translates received requests and forwards them inbound to another server or servers ๐ gateways are often used to wrap up legacy or untrusted information services, to boost server performance through "accelerator" caching, and to enable partitioning or load balancing of HTTP services across multiple machines ๐
all HTTP requirements that apply to an origin server also apply to the outbound communication of a gateway ๐ a gateway talks to inbound servers using any protocol it wants, including private extensions to HTTP that are outside the scope of this specification ๐ฆ however, an HTTP-to-HTTP gateway that wants to interoperate with third-party HTTP servers ought to conform to user agent requirements on the gateway's inbound connection ๐ธ
a "tunnel" acts as a blind relay between two connections without changing the messages ๐ง once it's active, a tunnel isn't considered a party to the HTTP communication, even though it might have been started by an HTTP request ๐ญ a tunnel stops existing when both ends of the relayed connection are closed ๐ tunnels are used to extend a virtual connection through an intermediary, like when Transport Layer Security (TLS, [RFC5246]) is used to set up confidential communication through a shared firewall proxy ๐ฅ
the categories above only cover intermediaries that act as participants in the HTTP communication. there are also intermediaries that work at lower layers of the network protocol stack, filtering or redirecting HTTP traffic without the knowledge or permission of the message senders ๐ network intermediaries are indistinguishable (at a protocol level) from a man-in-the-middle attack, and they often introduce security flaws or interoperability problems by mistakenly violating HTTP semantics ๐
network intermediaries can look exactly like a man-in-the-middle attack at the protocol level, so watch out for the security flaws and interoperability chaos they can cause ๐ญ
for example, an "interception proxy" [RFC3040] (also commonly known as a "transparent proxy" [RFC1919] or "captive portal") is different from an HTTP proxy because the client doesn't select it ๐ instead, an interception proxy filters or redirects outgoing TCP port 80 packets (and occasionally other common port traffic) ๐ interception proxies are commonly found at public network access points, where they enforce account subscription before you can use non-local Internet services, and inside corporate firewalls to enforce network usage policies ๐ผ
HTTP is defined as a stateless protocol, which means each request message can be understood in isolation ๐ธ loads of implementations rely on HTTP's stateless design to reuse proxied connections or dynamically load balance requests across multiple servers ๐ so, a server MUST NOT assume that two requests on the same connection come from the same user agent unless the connection is secured and specific to that agent ๐ฅ some non-standard HTTP extensions (e.g., [RFC4559]) have been known to break this rule, which caused security and interoperability problems ๐ญ
2.4. Caches ๐
a "cache" is a local store of previous response messages, plus the subsystem that controls how those messages are stored, retrieved, and deleted ๐ caches store cacheable responses to cut down response time and network bandwidth use on future, equivalent requests โจ any client or server MAY employ a cache ๐ซถ though a cache can't be used by a server while that server is acting as a tunnel ๐
the effect of a cache is that the request/response chain gets shorter if one of the participants along the chain has a cached response that fits the request ๐ฆ here's what that looks like if B has a cached copy of an earlier response from O (via C) for a request that UA or A hasn't cached ๐
> >
UA =========== A =========== B - - - - - - C - - - - - - O
< <
a response is "cacheable" if a cache is allowed to store a copy of it for answering later requests ๐ even when a response is cacheable, the client or the origin server might add extra constraints on when that cached response can be used for a particular request ๐ the HTTP requirements for cache behavior and cacheable responses are defined in Section 2 of [RFC7234] ๐ง
there's a huge variety of cache architectures and configurations out there across the World Wide Web and inside big organizations ๐ธ these include national hierarchies of proxy caches to save transoceanic bandwidth, collaborative systems that broadcast or multicast cache entries, archives of pre-fetched cache entries for offline or high-latency environments, and so on ๐ฅ
2.5. Conformance and Error Handling ๐
this spec sets conformance criteria based on the role a participant plays in HTTP communication ๐ so HTTP requirements land on senders, recipients, clients, servers, user agents, intermediaries, origin servers, proxies, gateways, or caches, depending on which behavior the requirement is limiting ๐ซถ extra (social) requirements land on implementations, resource owners, and protocol element registrations when they reach beyond a single communication ๐
the verb "generate" is used instead of "send" when a requirement is distinguishing between creating a protocol element and just forwarding a received one downstream ๐ฆ
an implementation counts as conformant if it complies with all the requirements tied to the roles it plays in HTTP โจ
conformance covers both the syntax and the semantics of protocol elements ๐ a sender MUST NOT generate protocol elements that convey a meaning the sender knows to be false ๐ a sender MUST NOT generate protocol elements that don't match the grammar defined by the corresponding ABNF rules ๐ within a given message, a sender MUST NOT generate protocol elements or syntax alternatives that only participants in other roles are allowed to generate (aka a role the sender doesn't have for that message) ๐ญ
when a received protocol element gets parsed, the recipient MUST be able to parse any value of reasonable length that applies to the recipient's role and matches the grammar defined by the corresponding ABNF rules ๐ง but note that some received protocol elements might never get parsed ๐ธ for example, an intermediary forwarding a message might parse a header field into generic field-name and field-value components, and then forward it without parsing inside the field-value ๐
HTTP doesn't have specific length limits for many of its protocol elements, because what's appropriate varies a lot depending on the deployment context and purpose of the implementation ๐ so interoperability between senders and recipients depends on shared expectations about what counts as a reasonable length for each protocol element ๐ also, what people commonly consider reasonable for some protocol elements has changed over the last two decades of HTTP use, and it's expected to keep changing ๐
at a minimum, a recipient MUST be able to parse and process protocol element lengths that are at least as long as the values it generates for those same protocol elements in other messages ๐ฅ for example, an origin server that publishes very long URI references to its own resources needs to be able to parse and process those same references when they arrive as a request target ๐ซถ
a recipient MUST interpret a received protocol element according to the semantics this specification defines for it, including extensions to this specification, unless the recipient has determined (through experience or configuration) that the sender incorrectly implements what those semantics imply ๐ for example, an origin server might disregard the contents of a received Accept-Encoding header field if inspecting the User-Agent header field shows a specific implementation version that's known to fail on receipt of certain content codings ๐
unless noted otherwise, a recipient MAY attempt to recover a usable protocol element from an invalid construct ๐ฆ HTTP doesn't define specific error handling mechanisms except where they have a direct impact on security, since different applications of the protocol need different error handling strategies ๐ for example, a Web browser might want to transparently recover from a response where the Location header field doesn't parse according to the ABNF, whereas a systems control client might consider any form of error recovery to be dangerous ๐
2.6. Protocol Versioning ๐
okay so HTTP numbers its versions as "<major>.<minor>", kind of like a little score card ๐ This spec defines version "1.1" โจ The protocol version as a whole shows the sender's conformance with the set of requirements in that version's matching spec of HTTP. It's giving receipts ๐งพ
The version of an HTTP message is shown by an HTTP-version field in the first line of the message. HTTP-version is case-sensitive ๐
HTTP-version = HTTP-name "/" DIGIT "." DIGIT
HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive
The HTTP version number is two decimal digits separated by a "." (period or decimal point). The first digit ("major version") tells you the HTTP messaging syntax, and the second digit ("minor version") tells you the highest minor version within that major version that the sender is conformant with and able to understand for future communication. The minor version advertises the sender's communication capabilities even when the sender is only using a backwards-compatible subset of the protocol ๐ฆ That way the recipient knows more advanced features can be used in response (by servers) or in future requests (by clients) ๐ซถ
When an HTTP/1.1 message is sent to an HTTP/1.0 recipient [RFC1945] or a recipient whose version is unknown, the HTTP/1.1 message is constructed so that it can be interpreted as a valid HTTP/1.0 message if all of the newer features are ignored ๐ธ This specification puts recipient-version requirements on some new features, so a conformant sender only uses compatible features until it has determined, through configuration or the receipt of a message, that the recipient supports HTTP/1.1. Careful, bestie ๐
The interpretation of a header field does not change between minor versions of the same major HTTP version, though the default behavior of a recipient when that field is missing can change. Unless specified otherwise, header fields defined in HTTP/1.1 are defined for all versions of HTTP/1.x. In particular, the Host and Connection header fields ought to be implemented by all HTTP/1.x implementations, whether or not they advertise conformance with HTTP/1.1 ๐
New header fields can be introduced without changing the protocol version if their defined semantics let recipients that don't recognize them safely ignore them โจ Header field extensibility is discussed in Section 3.2.1.
Intermediaries that process HTTP messages (i.e., all intermediaries other than those acting as tunnels) MUST send their own HTTP-version in forwarded messages. In other words, they are not allowed to blindly forward the first line of an HTTP message without making sure that the protocol version in that message matches a version the intermediary is conformant with for both receiving and sending messages ๐ญ Forwarding a message without rewriting the HTTP-version might cause communication errors when downstream recipients use the message sender's version to decide which features are safe to use for later communication with that sender. Not the vibe ๐
A client SHOULD send a request version equal to the highest version to which the client is conformant and whose major version is no higher than the highest version supported by the server, if this is known. A client MUST NOT send a version to which it is not conformant ๐ฅ
A client MAY send a lower request version if it is known that the server incorrectly implements the HTTP specification, but only after the client has attempted at least one normal request and determined, from the response status code or header fields (e.g., Server), that the server improperly handles higher request versions ๐ง
A server SHOULD send a response version equal to the highest version to which the server is conformant that has a major version less than or equal to the one received in the request. A server MUST NOT send a version to which it is not conformant. A server can send a 505 (HTTP Version Not Supported) response if it wishes, for any reason, to refuse service of the client's major protocol version ๐ โโ๏ธ
A server MAY send an HTTP/1.0 response to a request if it is known or suspected that the client incorrectly implements the HTTP specification and is incapable of correctly processing later version responses. That happens when a client fails to parse the version number correctly, or when an intermediary is known to blindly forward the HTTP-version even though it doesn't conform to the given minor version of the protocol ๐ Such protocol downgrades SHOULD NOT be performed unless they're triggered by specific client attributes, such as when one or more of the request header fields (e.g., User-Agent) uniquely match the values sent by a client known to be in error ๐
The vibe check here: downgrades are the exception, not the main character moment. Only do them when the evidence is airtight ๐
The big idea of HTTP's versioning design is that the major number only goes up if an incompatible message syntax is introduced, and the minor number only goes up when changes to the protocol add to the message semantics or imply additional capabilities of the sender ๐ However, the minor version was not incremented for the changes introduced between [RFC2068] and [RFC2616], and this revision has specifically avoided any such changes to the protocol. Oop ๐ฌ
When an HTTP message arrives with a major version number that the recipient implements, but a higher minor version number than the recipient implements, the recipient SHOULD process the message as if it were in the highest minor version within that major version to which the recipient is conformant. A recipient can assume that a message with a higher minor version, when sent to a recipient that has not yet indicated support for that higher version, is sufficiently backwards-compatible to be safely processed by any implementation of the same major version ๐ฆ
2.7. Uniform Resource Identifiers โจ
Uniform Resource Identifiers (URIs) [RFC3986] are used throughout HTTP as the way to identify resources (Section 2 of [RFC7231]). URI references are used to target requests, indicate redirects, and define relationships ๐
The definitions of "URI-reference", "absolute-URI", "relative-part", "scheme", "authority", "port", "host", "path-abempty", "segment", "query", and "fragment" are adopted from the URI generic syntax ๐ An "absolute-path" rule is defined for protocol elements that can contain a non-empty path component. (This rule is a little different from the path-abempty rule of RFC 3986, which allows an empty path to be used in references, and from the path-absolute rule, which doesn't allow paths that begin with "//".) A "partial-URI" rule is defined for protocol elements that can contain a relative URI but not a fragment component ๐งฉ
URI-reference = <URI-reference, see [RFC3986], Section 4.1>
absolute-URI = <absolute-URI, see [RFC3986], Section 4.3>
relative-part = <relative-part, see [RFC3986], Section 4.2>
scheme = <scheme, see [RFC3986], Section 3.1>
authority = <authority, see [RFC3986], Section 3.2>
uri-host = <host, see [RFC3986], Section 3.2.2>
port = <port, see [RFC3986], Section 3.2.3>
path-abempty = <path-abempty, see [RFC3986], Section 3.3>
segment = <segment, see [RFC3986], Section 3.3>
query = <query, see [RFC3986], Section 3.4>
fragment = <fragment, see [RFC3986], Section 3.5>
absolute-path = 1*( "/" segment )
partial-URI = relative-part [ "?" query ]
Each protocol element in HTTP that allows a URI reference will say, in its ABNF production, whether it allows any form of reference (URI-reference), only a URI in absolute form (absolute-URI), only the path and optional query components, or some combination of the above ๐ซถ Unless otherwise indicated, URI references are parsed relative to the effective request URI (Section 5.5) ๐
2.7.1. http URI Scheme โจ
okay so the "http" URI scheme is officially defined for minting identifiers ๐ฆ based on the hierarchical namespace run by a potential HTTP origin server that's listening for TCP ([RFC0793]) connections on a given port. ngl it's a whole vibe ๐
http-URI = "http:" "//" authority path-abempty [ "?" query ]
[ "#" fragment ]
The origin server for an "http" URI is the authority component ๐, which has a host identifier plus an optional TCP port ([RFC3986], Section 3.2.2). The path and the optional query together act as an identifier for a potential target resource inside that origin server's name space ๐ธ. The optional fragment lets you identify a secondary resource indirectly, no matter the URI scheme, as defined in Section 3.5 of [RFC3986] ๐ง
A sender MUST NOT generate an "http" URI with an empty host identifier ๐. A recipient that processes such a URI reference MUST reject it as invalid ๐.
If the host identifier is an IP address, the origin server is whatever listener (if any) is on that TCP port at that IP address ๐. If the host is a registered name, that name is an indirect identifier you feed into a name resolution service, like DNS, to find an address for the origin server โจ. If the port subcomponent is empty or not given, TCP port 80 (the reserved port for WWW services) is the default ๐.
Note that having a URI with a given authority component does NOT mean there's always an HTTP server listening on that host and port ๐. Anyone can mint a URI, bestie. What the authority component decides is who has the right to answer authoritatively to requests targeting the identified resource ๐. The delegated nature of registered names and IP addresses creates a federated namespace based on control over the indicated host and port, whether or not an HTTP server is actually there ๐. See Section 9.1 for security considerations related to establishing authority ๐ญ.
When an "http" URI is used in a context that calls for access to the indicated resource, a client MAY attempt access ๐ฆ. It does this by resolving the host to an IP address, establishing a TCP connection to that address on the indicated port, and sending an HTTP request message (Section 3) containing the URI's identifying data (Section 5) to the server ๐. If the server answers that request with a non-interim HTTP response message, as described in Section 6 of [RFC7231], then that response counts as an authoritative answer to the client's request ๐ซถ.
Although HTTP doesn't care which transport protocol it runs on, the "http" scheme is specific to TCP-based services ๐งต, because the name delegation process depends on TCP for establishing authority. An HTTP service built on some other underlying connection protocol would presumably be identified with a different URI scheme ๐ท, just like the "https" scheme (below) is used for resources that need an end-to-end secured connection ๐. Other protocols might also be used to provide access to "http" identified resources -- it's only the authoritative interface that is specific to TCP ๐.
The generic URI syntax for authority also includes a deprecated userinfo subcomponent ([RFC3986], Section 3.2.1) for putting user authentication info in the URI ๐ โโ๏ธ. Some implementations use the userinfo component for internal config of authentication info, like in command invocation options, config files, or bookmark lists ๐, even though that usage might expose a user identifier or password ๐ฌ. A sender MUST NOT generate the userinfo subcomponent (and its "@" delimiter) when an "http" URI reference is generated within a message as a request target or header field value ๐ซ. Before using an "http" URI reference received from an untrusted source, a recipient SHOULD parse for userinfo and treat its presence as an error ๐จ, because it's likely being used to obscure the authority for the sake of phishing attacks ๐ฃ.
2.7.2. https URI Scheme ๐
the "https" URI scheme is defined for minting identifiers based on the hierarchical namespace run by a potential HTTP origin server listening on a given TCP port for TLS-secured connections ([RFC5246]) ๐ง.
All of the requirements listed above for the "http" scheme are also requirements for "https" ๐, except that TCP port 443 is the default if the port subcomponent is empty or not given, AND the user agent MUST ensure its connection to the origin server is secured with strong encryption, end-to-end, before sending the first HTTP request ๐ก๏ธโจ.
https-URI = "https:" "//" authority path-abempty [ "?" query ]
[ "#" fragment ]
Note that the "https" scheme depends on both TLS and TCP for establishing authority ๐. Resources available through "https" have no shared identity with the "http" scheme, even if their identifiers show the same authority (the same host listening on the same TCP port) ๐ฏ. They're distinct namespaces and are considered distinct origin servers ๐ฆ. However, an HTTP extension defined to apply to entire host domains, like the Cookie protocol [RFC6265], can let information set by one service affect communication with other services within a matching group of host domains ๐ช.
The process for authoritative access to an "https" identified resource is defined in [RFC2818] ๐.
2.7.3. http and https URI Normalization and Comparison ๐
Since the "http" and "https" schemes conform to the generic URI syntax, these URIs get normalized and compared using the algorithm defined in Section 6 of [RFC3986], with the defaults described above for each scheme ๐.
If the port is equal to the default port for a scheme, the normal form is to leave out the port subcomponent ๐ธ. When it's not being used in absolute form as the request target of an OPTIONS request, an empty path component is equivalent to an absolute path of "/", so the normal form is to give a path of "/" instead ๐ก. The scheme and host are case-insensitive and normally written in lowercase ๐ค, and all other components are compared case-sensitively ๐. Characters other than those in the "reserved" set are equivalent to their percent-encoded octets, and the normal form is to not encode them (see Sections 2.1 and 2.2 of [RFC3986]) ๐ง .
For example, these three URIs are equivalent ๐:
http://example.com:80/~smith/home.html
http://EXAMPLE.com/%7Esmith/home.html
http://EXAMPLE.com:/%7esmith/home.html
3. Message Format ๐ฎ
All HTTP/1.1 messages are made of a start-line, followed by a sequence of octets in a format similar to the Internet Message Format [RFC5322] ๐: zero or more header fields (collectively called the "headers" or the "header section"), an empty line marking the end of the header section, and an optional message body ๐ซง.
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
The normal way to parse an HTTP message goes like this ๐งฉ: read the start-line into a structure, read each header field into a hash table by field name until you hit the empty line, and then use that parsed data to figure out whether a message body is expected ๐. If a message body has been indicated, it's read as a stream until either an amount of octets equal to the message body length has been read or the connection is closed ๐.
A recipient MUST parse an HTTP message as a sequence of octets in an encoding that's a superset of US-ASCII [USASCII] ๐ค. Parsing an HTTP message as a stream of Unicode characters, without caring about the specific encoding, creates security vulnerabilities ๐จ, because string processing libraries handle invalid multibyte character sequences containing the octet LF (%x0A) in different ways ๐ต. String-based parsers can only be safely used within protocol elements after the element has been pulled out of the message, like inside a header field-value after message parsing has split up the individual fields ๐ซถ.
An HTTP message can be parsed as a stream for incremental processing or for forwarding downstream ๐โโ๏ธ. However, recipients cannot rely on getting partial messages incrementally, because some implementations buffer or delay forwarding for the sake of network efficiency, security checks, or payload transformations ๐ข.
A sender MUST NOT send whitespace between the start-line and the first header field ๐ซ. A recipient that gets whitespace between the start-line and the first header field MUST either reject the message as invalid OR consume each whitespace-preceded line without processing it further (basically, ignore the entire line, along with any subsequent lines preceded by whitespace, until a properly formed header field arrives or the header section ends) ๐ โโ๏ธ.
The presence of that whitespace in a request might be an attempt to trick a server into ignoring that field, or into processing the line after it as a new request ๐. Either of those could be a security vulnerability if other implementations in the request chain interpret the same message differently ๐. Likewise, that whitespace in a response might get ignored by some clients, or make others stop parsing altogether ๐.
3.1. Start Line ๐
An HTTP message can be either a request from client to server or a response from server to client ๐ฌ. Syntactically, the two types differ only in the start-line, which is either a request-line (for requests) or a status-line (for responses) โจ, and in the algorithm for working out the length of the message body (Section 3.3) ๐.
In theory, a client could receive requests and a server could receive responses, telling them apart by their different start-line formats ๐ค. But in practice, servers are implemented to only expect a request (a response is interpreted as an unknown or invalid request method) ๐, and clients are implemented to only expect a response ๐ซถ.
start-line = request-line / status-line
3.1.1. Request Line โจ
okay so a request-line starts with a method token, then a single space (SP), then the request-target, another single space (SP), then the protocol version, and it ends with CRLF ๐
request-line = method SP request-target SP HTTP-version CRLF
The method token tells the target resource what request method to perform. The request method is case-sensitive ๐
method = token
The request methods defined by this specification can be found in Section 4 of [RFC7231], along with info about the HTTP method registry and considerations for defining new methods ๐ง
The request-target is what identifies the target resource the request should be applied to, as defined in Section 5.3 ๐ฏ
Recipients usually split the request-line into its parts by splitting on whitespace (see Section 3.5), since no whitespace is allowed in those three components. Unfortunately, some user agents don't properly encode or exclude whitespace found in hypertext references, so those disallowed characters end up in a request-target ๐ญ
Recipients of an invalid request-line SHOULD respond with either a 400 (Bad Request) error or a 301 (Moved Permanently) redirect with the request-target properly encoded. A recipient SHOULD NOT try to autocorrect and then process the request without a redirect, since the invalid request-line might be deliberately crafted to sneak past security filters along the request chain. This is a big deal, bestie ๐จ
HTTP does not place a predefined limit on the length of a request-line, as described in Section 2.5. A server that receives a method longer than any that it implements SHOULD respond with a 501 (Not Implemented) status code. A server that receives a request-target longer than any URI it wishes to parse MUST respond with a 414 (URI Too Long) status code (see Section 6.5.12 of [RFC7231]) ๐ฆ
Various ad hoc limitations on request-line length show up in practice. It is RECOMMENDED that all HTTP senders and recipients support, at a minimum, request-line lengths of 8000 octets โจ
3.1.2. Status Line
The first line of a response message is the status-line ๐ธ It's made of the protocol version, a space (SP), the status code, another space, a possibly empty textual phrase describing the status code, and then it ends with CRLF.
status-line = HTTP-version SP status-code SP reason-phrase CRLF
The status-code is a 3-digit integer that describes the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message gets interpreted based on the semantics defined for that status code. See Section 6 of [RFC7231] for info about the semantics of status codes, including the classes of status code (indicated by the first digit), the status codes defined by this specification, considerations for defining new status codes, and the IANA registry ๐ฅ
status-code = 3DIGIT
The reason-phrase exists for the sole purpose of giving a textual description of the numeric status code. It's mostly out of respect for older Internet application protocols that were used a lot with interactive text clients ๐ A client SHOULD ignore the reason-phrase content.
reason-phrase = *( HTAB / SP / VCHAR / obs-text )
3.2. Header Fields ๐
Each header field is a case-insensitive field name, followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace. Main character energy ๐
header-field = field-name ":" OWS field-value OWS
field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text
obs-fold = CRLF 1*( SP / HTAB )
; obsolete line folding
; see Section 3.2.4
The field-name token labels the field-value as having the semantics defined by that header field. For example, the Date header field is defined in Section 7.1.1.2 of [RFC7231] as containing the origination timestamp for the message it appears in ๐๏ธ
3.2.1. Field Extensibility
Header fields are fully extensible ๐ There's no limit on introducing new field names (each one presumably defines new semantics), and no limit on how many header fields a message can use. Existing fields are defined in each part of this specification and in lots of other specifications outside this document set.
New header fields can be defined so that, once a recipient understands them, they might override or enhance how previously defined header fields are interpreted, define preconditions on request evaluation, or refine the meaning of responses. Iconic ๐ฆ
A proxy MUST forward unrecognized header fields unless the field-name is listed in the Connection header field (Section 6.1) or the proxy is specifically configured to block, or otherwise transform, such fields. Other recipients SHOULD ignore unrecognized header fields. These requirements let HTTP's functionality get enhanced without needing a prior update to deployed intermediaries ๐ซถ
All defined header fields ought to be registered with IANA in the "Message Headers" registry, as described in Section 8.3 of [RFC7231] ๐
3.2.2. Field Order
The order that header fields with different field names are received in doesn't matter. However, it's good practice to send header fields that contain control data first, like Host on requests and Date on responses, so implementations can decide when not to handle a message as early as possible โฑ๏ธ A server MUST NOT apply a request to the target resource until the entire request header section is received, since later header fields might include conditionals, authentication credentials, or deliberately misleading duplicate header fields that would impact request processing. Sneaky header fields are not it ๐ค
A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below) ๐ซ
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each later field value to the combined field value in order, separated by a comma. The order that header fields with the same field name are received in is therefore significant to how the combined field value gets interpreted, so a proxy MUST NOT change the order of these field values when forwarding a message ๐ง
Note: In practice, the "Set-Cookie" header field ([RFC6265]) often appears multiple times in a response message and does not use the list syntax, which breaks the above requirements on multiple header fields with the same name. Since it can't be combined into a single field-value, recipients ought to handle "Set-Cookie" as a special case while processing header fields. (See Appendix A.2.3 of [Kri2001] for details.) ๐ช
3.2.3. Whitespace
This specification uses three rules to denote the use of linear whitespace: OWS (optional whitespace), RWS (required whitespace), and BWS ("bad" whitespace) ๐ท
The OWS rule is used where zero or more linear whitespace octets might appear. For protocol elements where optional whitespace is preferred to improve readability, a sender SHOULD generate the optional whitespace as a single SP. Otherwise, a sender SHOULD NOT generate optional whitespace, except as needed to white out invalid or unwanted protocol elements during in-place message filtering โจ
The RWS rule is used when at least one linear whitespace octet is required to separate field tokens. A sender SHOULD generate RWS as a single SP ๐
The BWS rule is used where the grammar allows optional whitespace only for historical reasons. A sender MUST NOT generate BWS in messages. A recipient MUST parse for such bad whitespace and remove it before interpreting the protocol element. Bad whitespace? Get it out of here ๐ โโ๏ธ
OWS = *( SP / HTAB )
; optional whitespace
RWS = 1*( SP / HTAB )
; required whitespace
BWS = OWS
; "bad" whitespace
3.2.4. Field Parsing ๐
okay so the parser is totally generic ๐ง it doesn't care what the field name is. the contents of a field value don't get parsed until a later stage, usually after the whole header section has been processed. that's why this spec doesn't use ABNF to define each "Field-Name: Field Value" pair like the older editions did. instead, every registered field name gets its own ABNF rule that describes the valid grammar for its field values, once a generic field parser has pulled the field-value out of the header section. ๐
No whitespace is allowed between the header field-name and the colon. bestie this one is serious ๐ญ different software handling that whitespace differently has caused security holes in request routing and response handling before. so a server MUST reject any received request message that contains whitespace between a header field-name and colon, with a response code of 400 (Bad Request). and a proxy MUST remove any such whitespace from a response message before forwarding it downstream. ๐ฅ
A field value might be preceded and/or followed by optional whitespace (OWS). a single SP before the field-value is preferred, since it's just easier for humans to read โจ the field value itself doesn't include any leading or trailing whitespace. OWS before the first non-whitespace octet of the field value, or after the last one, ought to be excluded by parsers when they pull the field value out of a header field. ๐ฆ
Historically, HTTP header field values could be stretched over multiple lines by starting each extra line with at least one space or horizontal tab (obs-fold). this spec deprecates that line folding, except inside the message/http media type (Section 8.3.1). so a sender MUST NOT generate a message that includes line folding (meaning any field-value that matches the obs-fold rule) unless the message is meant to be packaged within the message/http media type. no folding for you, sis ๐ โโ๏ธ
a server that gets an obs-fold in a request message that is NOT inside a message/http container has two options. it can reject the message with a 400 (Bad Request), ideally with a representation explaining that obsolete line folding is unacceptable. or it can replace each received obs-fold with one or more SP octets before interpreting the field value or forwarding the message downstream. ๐
a proxy or gateway that gets an obs-fold in a response message that is NOT inside a message/http container also has two options. it can discard the message and replace it with a 502 (Bad Gateway) response, ideally with a representation explaining that unacceptable line folding was received. or it can replace each received obs-fold with one or more SP octets before interpreting the field value or forwarding the message downstream. ๐ธ
a user agent that gets an obs-fold in a response message that is NOT inside a message/http container MUST replace each received obs-fold with one or more SP octets before interpreting the field value. no exceptions, babe ๐
Historically, HTTP allowed field content with text in the ISO-8859-1 charset [ISO-8859-1], and it only supported other charsets through [RFC2047] encoding. in practice, most HTTP header field values only use a subset of the US-ASCII charset [USASCII]. so newly defined header fields SHOULD limit their field values to US-ASCII octets. and a recipient SHOULD treat other octets in field content (obs-text) as opaque data. it's giving clean, simple vibes ๐ง
3.2.5. Field Limits ๐
HTTP doesn't set a predefined limit on the length of each header field, or on the length of the header section as a whole, as described in Section 2.5. in the wild you'll see ad hoc limits on individual header field lengths, and they often depend on the specific field semantics. it's a lot, ngl ๐
A server that receives a request header field, or a set of fields, that's larger than it wants to process MUST respond with an appropriate 4xx (Client Error) status code. ignoring those header fields would make the server more vulnerable to request smuggling attacks (Section 9.5). so don't just quietly ignore them, bestie ๐ซ
A client MAY discard or truncate received header fields that are larger than the client wants to process, but only if the field semantics are such that the dropped value(s) can be safely ignored without changing the message framing or response semantics. ๐ซถ
3.2.6. Field Value Components ๐
Most HTTP header field values are built from common syntax components (token, quoted-string, and comment), separated by whitespace or specific delimiting characters. the delimiters are picked from the set of US-ASCII visual characters that aren't allowed in a token, which is DQUOTE and "(),/:;<=>?@[\]{}". ๐ฆ
token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/ "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/ DIGIT / ALPHA
; any VCHAR, except delimiters
a string of text gets parsed as a single value if it's wrapped in double-quote marks. the quoted-string rules are right here, and they're super specific ๐
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
obs-text = %x80-FF
comments can go inside some HTTP header fields, wrapped in parentheses. but comments are only allowed in fields that have "comment" as part of their field value definition, so check the field before you go adding them ๐
comment = "(" *( ctext / quoted-pair / comment ) ")"
ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
the backslash octet ("") works as a single-octet quoting mechanism inside quoted-string and comment constructs. recipients that process the value of a quoted-string MUST handle a quoted-pair as if it were replaced by the octet following the backslash. that's the main character move right there ๐
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
a sender SHOULD NOT generate a quoted-pair in a quoted-string, except where it's necessary to quote DQUOTE and backslash octets that show up inside that string. and a sender SHOULD NOT generate a quoted-pair in a comment, except where it's necessary to quote parentheses ("(" and ")") and backslash octets that show up inside that comment. only escape when you actually need to, periodt โจ
3.3. Message Body ๐
The message body (if there is one) of an HTTP message carries the payload body of that request or response. the message body is identical to the payload body unless a transfer coding has been applied, as described in Section 3.3.1. ๐ง
message-body = *OCTET
the rules for when a message body is allowed differ between requests and responses, so pay attention ๐
The presence of a message body in a request is signaled by a Content-Length or Transfer-Encoding header field. request message framing is independent of method semantics, even if the method doesn't define any use for a message body. so the headers tell the story, not the method ๐
The presence of a message body in a response depends on both the request method it's responding to and the response status code (Section 3.1.2). responses to the HEAD request method (Section 4.3.2 of [RFC7231]) never include a message body. the associated response header fields (like Transfer-Encoding, Content-Length, etc.), if they're there, only show what their values would have been if the request method had been GET (Section 4.3.1 of [RFC7231]). 2xx (Successful) responses to a CONNECT request method (Section 4.3.6 of [RFC7231]) switch to tunnel mode instead of having a message body. all 1xx (Informational), 204 (No Content), and 304 (Not Modified) responses don't include a message body. every other response does include one, although the body might be zero length. ๐ธ
3.3.1. Transfer-Encoding ๐ฆ
The Transfer-Encoding header field lists the transfer coding names that match the sequence of transfer codings that have been (or will be) applied to the payload body to form the message body. transfer codings are defined in Section 4. ๐ง
Transfer-Encoding = 1#transfer-coding
Transfer-Encoding is like the Content-Transfer-Encoding field of MIME, which was designed to make binary data safe to send over a 7-bit transport service ([RFC2045], Section 6). but safe transport means something different for an 8bit-clean transfer protocol. in HTTP's case, Transfer-Encoding is mainly there to accurately delimit a dynamically generated payload, and to tell apart the payload encodings that only exist for transport efficiency or security from the ones that are actually characteristics of the selected resource. it's all about the framing, babe ๐
A recipient MUST be able to parse the chunked transfer coding (Section 4.1), because it plays a crucial role in framing messages when the payload body size isn't known in advance. a sender MUST NOT apply chunked more than once to a message body, so chunking an already chunked message is a no-go ๐ โโ๏ธ if any transfer coding other than chunked gets applied to a request payload body, the sender MUST apply chunked as the final transfer coding so the message is framed properly. if any transfer coding other than chunked gets applied to a response payload body, the sender MUST either apply chunked as the final transfer coding or terminate the message by closing the connection. ๐ฅ
For example,
Transfer-Encoding: gzip, chunked
indicates that the payload body was compressed using the gzip coding, and then chunked using the chunked coding while forming the message body. โจ
Unlike Content-Encoding (Section 3.1.2.1 of [RFC7231]), Transfer-Encoding is a property of the message, not of the representation. any recipient along the request/response chain MUST NOT be stopped from decoding the received transfer coding(s) or applying additional transfer coding(s) to the message body, assuming the corresponding changes are made to the Transfer-Encoding field-value. wait, correction: the original says any recipient MAY do this, so the chain can keep things flexible ๐ additional information about the encoding parameters can be provided by other header fields that this specification doesn't define.
Transfer-Encoding MAY be sent in a response to a HEAD request, or in a 304 (Not Modified) response (Section 4.1 of [RFC7232]) to a GET request. neither of those includes a message body, and the header says the origin server would have applied a transfer coding to the message body if the request had been an unconditional GET. that indication isn't required, though, because any recipient on the response chain (including the origin server) can remove transfer codings when they aren't needed. ๐
A server MUST NOT send a Transfer-Encoding header field in any response with a status code of 1xx (Informational) or 204 (No Content). a server MUST NOT send a Transfer-Encoding header field in any 2xx (Successful) response to a CONNECT request (Section 4.3.6 of [RFC7231]). ๐ โโ๏ธ
Transfer-Encoding was added in HTTP/1.1. it's generally assumed that implementations advertising only HTTP/1.0 support won't understand how to process a transfer-encoded payload. so a client MUST NOT send a request containing Transfer-Encoding unless it knows the server will handle HTTP/1.1 (or later) requests. that knowledge might come from specific user configuration, or from remembering the version of a prior received response. and a server MUST NOT send a response containing Transfer-Encoding unless the corresponding request indicates HTTP/1.1 (or later). ๐ง
A server that receives a request message with a transfer coding it doesn't understand SHOULD respond with 501 (Not Implemented). ๐ซถ
3.3.2. Content-Length ๐โจ
okay so when a message does not have a Transfer-Encoding header field, a Content-Length header field can tell everyone the anticipated size, as a decimal number of octets, for a potential payload body ๐. For messages that actually include a payload body, the Content-Length field-value gives the framing info needed to figure out where the body (and the whole message) ends ๐ฆ. For messages without a payload body, Content-Length shows the size of the selected representation (Section 3 of [RFC7231]) ๐ .
Content-Length = 1*DIGIT
Here's an example, iykyk:
Content-Length: 3495
๐ซ A sender MUST NOT send a Content-Length header field in any message that contains a Transfer-Encoding header field. Not even a little bit, bestie ๐.
A user agent SHOULD send a Content-Length in a request message when no Transfer-Encoding is sent and the request method defines a meaning for an enclosed payload body ๐. For example, Content-Length is normally sent in a POST request even when the value is 0 (indicating an empty payload body) ๐ง. A user agent SHOULD NOT send a Content-Length header field when the request message has no payload body and the method semantics don't expect one ๐.
A server MAY send a Content-Length header field in a response to a HEAD request (Section 4.3.2 of [RFC7231]) โจ. But a server MUST NOT send Content-Length in such a response unless its field-value equals the decimal number of octets that would have been sent in the payload body of a response if the same request had used the GET method ๐ธ.
A server MAY send a Content-Length header field in a 304 (Not Modified) response to a conditional GET request (Section 4.1 of [RFC7232]) ๐ฆ. Again, a server MUST NOT send Content-Length in such a response unless its field-value equals the decimal number of octets that would have been sent in the payload body of a 200 (OK) response to the same request ๐.
A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational) or 204 (No Content) ๐ซ. A server MUST NOT send a Content-Length header field in any 2xx (Successful) response to a CONNECT request (Section 4.3.6 of [RFC7231]) either ๐ .
Outside of those cases, and with no Transfer-Encoding in play, an origin server SHOULD send a Content-Length header field when the payload body size is known before the complete header section is sent ๐. This lets downstream recipients measure transfer progress, know when a received message is complete, and potentially reuse the connection for more requests โญ.
Any Content-Length field value greater than or equal to zero is valid ๐ซถ. There's no predefined limit on payload length, so a recipient MUST anticipate potentially large decimal numerals and prevent parsing errors caused by integer conversion overflows (Section 9.3) ๐ญ๐ฅ.
If a message comes in with multiple Content-Length header fields whose field-values are the same decimal value, or a single Content-Length header field whose value is a list of identical decimal values (like Content-Length: 42, 42), that's a sign that duplicate Content-Length header fields were generated or combined by an upstream message processor ๐. In that case the recipient MUST either reject the message as invalid, or replace the duplicated field-values with a single valid Content-Length field containing that decimal value, before determining the message body length or forwarding the message ๐.
Note: HTTP's use of Content-Length for message framing is very different from the same field's use in MIME, where it's an optional field used only within the "message/external-body" media-type. Don't mix them up, bestie! ๐
3.3.3. Message Body Length ๐งฎ๐
The length of a message body is determined by one of the following (in order of precedence) ๐:
- Any response to a HEAD request, and any response with a 1xx (Informational), 204 (No Content), or 304 (Not Modified) status code, is always terminated by the first empty line after the header fields, regardless of which header fields are present in the message. So it can't contain a message body, ever ๐ โโ๏ธ.
- Any 2xx (Successful) response to a CONNECT request implies that the connection becomes a tunnel right after the empty line that ends the header fields ๐. A client MUST ignore any Content-Length or Transfer-Encoding header fields received in such a message ๐.
- If a Transfer-Encoding header field is present and the chunked transfer coding (Section 4.1) is the final encoding, the message body length is determined by reading and decoding the chunked data until the transfer coding says the data is complete ๐งฉ.
If a Transfer-Encoding header field is present in a response and the chunked transfer coding is not the final encoding, the message body length is determined by reading the connection until the server closes it ๐. If a Transfer-Encoding header field is present in a request and the chunked transfer coding is not the final encoding, the message body length can't be determined reliably. The server MUST respond with the 400 (Bad Request) status code and then close the connection ๐ฑ.
If a message comes in with both a Transfer-Encoding and a Content-Length header field, the Transfer-Encoding overrides the Content-Length ๐ฆ. A message like that might be an attempt at request smuggling (Section 9.5) or response splitting (Section 9.4), so it ought to be handled as an error ๐จ. A sender MUST remove the received Content-Length field before forwarding such a message downstream ๐งน.
- If a message is received without Transfer-Encoding and with either multiple Content-Length header fields having differing field-values, or a single Content-Length header field having an invalid value, then the message framing is invalid. The recipient MUST treat it as an unrecoverable error ๐. If this is a request message, the server MUST respond with a 400 (Bad Request) status code and then close the connection ๐ โโ๏ธ. If this is a response message received by a proxy, the proxy MUST close the connection to the server, discard the received response, and send a 502 (Bad Gateway) response to the client ๐. If this is a response message received by a user agent, the user agent MUST close the connection to the server and discard the received response ๐๏ธ.
- If a valid Content-Length header field is present without Transfer-Encoding, its decimal value defines the expected message body length in octets ๐. If the sender closes the connection, or the recipient times out, before that many octets arrive, the recipient MUST consider the message incomplete and close the connection ๐ฅ.
- If this is a request message and none of the above apply, the message body length is zero, meaning no message body is present ๐ซง.
- Otherwise, this is a response message without a declared message body length, so its body length is determined by the number of octets received before the server closes the connection ๐.
Since there's no way to tell a successfully completed, close-delimited message apart from a partially received one that got cut off by a network failure, a server SHOULD generate encoding or length-delimited messages whenever it's possible ๐. The close-delimiting feature exists mainly for backwards compatibility with HTTP/1.0 ๐ฐ๏ธ.
A server MAY reject a request that has a message body but no Content-Length, by responding with 411 (Length Required) ๐ .
Unless a transfer coding other than chunked has been applied, a client that sends a request with a message body SHOULD use a valid Content-Length header field when the body length is known in advance, instead of the chunked transfer coding ๐. The reason is that some existing services respond to chunked with a 411 (Length Required) status code, even though they understand the chunked transfer coding ๐ฅฒ. This is usually because those services are built on a gateway that needs a content-length before it's called, and the server can't or won't buffer the entire request before processing it ๐๏ธ.
A user agent that sends a request with a message body MUST send a valid Content-Length header field if it doesn't know the server will handle HTTP/1.1 (or later) requests ๐. That knowledge can come from specific user configuration, or from remembering the version of a prior received response ๐ง .
If the final response to the last request on a connection has been completely received and there's still extra data to read, a user agent MAY discard the remaining data, or try to work out whether that data belongs to the prior response body (which could happen if the prior message's Content-Length value was incorrect) ๐. A client MUST NOT process, cache, or forward such extra data as a separate response, because that behaviour would be vulnerable to cache poisoning โ ๏ธ๐ซ.
3.4. Handling Incomplete Messages ๐งฉ๐ฅบ
A server that receives an incomplete request message, usually because of a canceled request or a triggered timeout exception, MAY send an error response before closing the connection ๐ฎ.
A client that receives an incomplete response message, which can happen when a connection closes early or when decoding a supposedly chunked transfer coding fails, MUST record the message as incomplete ๐. Cache requirements for incomplete responses are defined in Section 3 of [RFC7234] ๐พ.
If a response ends in the middle of the header section (before the empty line is received), and the status code might rely on header fields to convey the full meaning of the response, then the client can't assume that meaning got across ๐ต. The client might need to repeat the request to figure out what to do next ๐.
A message body that uses the chunked transfer coding is incomplete if the zero-sized chunk that ends the encoding hasn't been received ๐งธ. A message with a valid Content-Length is incomplete if the body received (in octets) is smaller than the value given by Content-Length ๐. A response with neither chunked transfer coding nor Content-Length is ended by the connection closing, so it's considered complete no matter how many body octets arrived, as long as the header section came through intact ๐โจ.
3.5. Message Parsing Robustness โจ
Okay so, older HTTP/1.0 user agents might send an extra CRLF after a POST request ๐ as a workaround for some early server apps that couldn't read message body content that wasn't ended by a line-ending. An HTTP/1.1 user agent MUST NOT preface or follow a request with an extra CRLF. If you want the request body to end with a line-ending, then the user agent MUST count the terminating CRLF octets as part of the message body length.
For the sake of robustness ๐ , a server that is expecting to receive and parse a request-line SHOULD ignore at least one empty line (CRLF) received prior to the request-line.
Although the line terminator for the start-line and header fields is the sequence CRLF, a recipient MAY recognize a single LF as a line terminator and ignore any preceding CR.
Although the request-line and status-line grammar rules require that each of the component elements be separated by a single SP octet, recipients MAY instead parse on whitespace-delimited word boundaries and, aside from the CRLF terminator, treat any form of whitespace as the SP separator while ignoring preceding or trailing whitespace. Such whitespace includes one or more of the following octets: SP, HTAB, VT (%x0B), FF (%x0C), or bare CR. However, lenient parsing can lead to security vulnerabilities if there are multiple recipients of the message and each has its own unique interpretation of robustness (see Section 9.5). Be careful with this one, bestie ๐ฅบ
When a server listening only for HTTP request messages, or processing what appears from the start-line to be an HTTP request message, receives a sequence of octets that does not match the HTTP-message grammar aside from the robustness exceptions listed above, the server SHOULD respond with a 400 (Bad Request) response. ๐ซ
4. Transfer Codings โจ
Transfer coding names are used to indicate an encoding transformation that has been, can be, or might need to be applied to a payload body in order to ensure "safe transport" through the network. This is different from a content coding, because a transfer coding is a property of the message rather than a property of the representation that is being transferred. ๐ฆ
transfer-coding = "chunked" ; Section 4.1
/ "compress" ; Section 4.2.1
/ "deflate" ; Section 4.2.2
/ "gzip" ; Section 4.2.3
/ transfer-extension
transfer-extension = token *( OWS ";" OWS transfer-parameter )
Parameters come in the form of a name or name=value pair. ๐
transfer-parameter = token BWS "=" BWS ( token / quoted-string )
All transfer-coding names are case-insensitive and ought to be registered within the HTTP Transfer Coding registry, as defined in Section 8.4. They are used in the TE (Section 4.3) and Transfer-Encoding (Section 3.3.1) header fields. ๐ธ
4.1. Chunked Transfer Coding
The chunked transfer coding wraps the payload body so it can be sent as a series of chunks, each with its own size indicator, followed by an OPTIONAL trailer containing header fields. This is so good ๐ญ because chunked lets content streams of unknown size get sent as a sequence of length-delimited buffers. The sender gets to keep the connection persistent, and the recipient knows exactly when it has received the entire message. ๐ฅ
chunked-body = *chunk
last-chunk
trailer-part
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
chunk-size = 1*HEXDIG
last-chunk = 1*("0") [ chunk-ext ] CRLF
chunk-data = 1*OCTET ; a sequence of chunk-size octets
The chunk-size field is a string of hex digits that tells you the size of the chunk-data in octets. The chunked transfer coding is complete once a chunk with a chunk-size of zero is received, possibly followed by a trailer, and finally terminated by an empty line. โจ
A recipient MUST be able to parse and decode the chunked transfer coding. ๐
4.1.1. Chunk Extensions
The chunked encoding lets each chunk include zero or more chunk extensions, placed right after the chunk-size. They're for supplying per-chunk metadata (like a signature or hash), mid-message control information, or randomization of message body size. Iconic ๐
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string
The chunked encoding is specific to each connection and is likely to be removed or recoded by each recipient (including intermediaries) before any higher-level application would have a chance to inspect the extensions. So, use of chunk extensions is generally limited to specialized HTTP services such as "long polling" (where client and server can have shared expectations regarding the use of chunk extensions) or for padding within an end-to-end secured connection. Not me being the one who has to explain this ๐
A recipient MUST ignore unrecognized chunk extensions. A server ought to limit the total length of chunk extensions received in a request to an amount reasonable for the services provided, in the same way that it applies length limitations and timeouts for other parts of a message. If that amount is exceeded, it should generate an appropriate 4xx (Client Error) response. ๐ โโ๏ธ
4.1.2. Chunked Trailer Part
A trailer lets the sender add extra fields at the end of a chunked message to supply metadata that might be dynamically generated while the message body is being sent, like a message integrity check, digital signature, or post-processing status. Trailer fields are identical to header fields, except they get sent in a chunked trailer instead of the message's header section. ๐ง
trailer-part = *( header-field CRLF )
A sender MUST NOT generate a trailer that contains a field necessary for message framing (e.g., Transfer-Encoding and Content-Length), routing (e.g., Host), request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]), authentication (e.g., see [RFC7235] and [RFC6265]), response control data (e.g., see Section 7.1 of [RFC7231]), or determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer). Absolutely do not put those in a trailer, babe ๐ซ
When a chunked message containing a non-empty trailer is received, the recipient MAY process the fields (aside from those forbidden above) as if they were appended to the message's header section. A recipient MUST ignore (or consider as an error) any fields that are forbidden to be sent in a trailer, since processing them as if they were present in the header section might bypass external security filters. This part is seriously important ๐ฑ because skipping it could let a field sneak past security filters!
Unless the request includes a TE header field indicating "trailers" is acceptable, as described in Section 4.3, a server SHOULD NOT generate trailer fields that it believes are necessary for the user agent to receive. Without a TE containing "trailers", the server ought to assume that the trailer fields might be silently discarded along the path to the user agent. This requirement lets intermediaries forward a de-chunked message to an HTTP/1.0 recipient without buffering the entire response. Clever, right? ๐ง โจ
4.1.3. Decoding Chunked
A process for decoding the chunked transfer coding can be represented in pseudo-code like this: ๐
length := 0
read chunk-size, chunk-ext (if any), and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to decoded-body
length := length + chunk-size
read chunk-size, chunk-ext (if any), and CRLF
}
read trailer field
while (trailer field is not empty) {
if (trailer field is allowed to be sent in a trailer) {
append trailer field to existing header fields
}
read trailer-field
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
Remove Trailer from existing header fields
4.2. Compression Codings
The codings defined below can be used to compress the payload of a message. Compression era ๐๏ธ
4.2.1. Compress Coding
The "compress" coding is an adaptive Lempel-Ziv-Welch (LZW) coding [Welch] that is commonly produced by the UNIX file compression program "compress". A recipient SHOULD consider "x-compress" to be equivalent to "compress". ๐ฆ
4.2.2. Deflate Coding
The "deflate" coding is a "zlib" data format [RFC1950] containing a "deflate" compressed data stream [RFC1951] that uses a combination of the Lempel-Ziv (LZ77) compression algorithm and Huffman coding. ๐
Note: Some non-conformant implementations send the "deflate" compressed data without the zlib wrapper.
4.2.3. Gzip Coding
The "gzip" coding is an LZ77 coding with a 32-bit Cyclic Redundancy Check (CRC) that is commonly produced by the gzip file compression program [RFC1952]. A recipient SHOULD consider "x-gzip" to be equivalent to "gzip". ๐
4.3. TE
The "TE" header field in a request tells you which transfer codings, besides chunked, the client is willing to accept in the response, and whether or not the client is willing to accept trailer fields in a chunked transfer coding. ๐
The TE field-value is a comma-separated list of transfer coding names, each allowing for optional parameters (as described in Section 4), and/or the keyword "trailers". A client MUST NOT send the chunked transfer coding name in TE; chunked is always acceptable for HTTP/1.1 recipients. ๐ โโ๏ธ
TE = #t-codings
t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
t-ranking = OWS ";" OWS "q=" rank
rank = ( "0" [ "." 0*3DIGIT ] )
/ ( "1" [ "." 0*3("0") ] )
Here are three examples of TE use: ๐ฆ
TE: deflate
TE:
TE: trailers, deflate;q=0.5
The presence of the keyword "trailers" means the client is willing to accept trailer fields in a chunked transfer coding, as defined in Section 4.1.2, on behalf of itself and any downstream clients. For requests from an intermediary, this implies that either: (a) all downstream clients are willing to accept trailer fields in the forwarded response; or, (b) the intermediary will attempt to buffer the response on behalf of downstream recipients. Note that HTTP/1.1 does not define any means to limit the size of a chunked response such that an intermediary can be assured of buffering the entire response. ๐ง
When multiple transfer codings are acceptable, the client MAY rank the codings by preference using a case-insensitive "q" parameter (similar to the qvalues used in content negotiation fields, Section 5.3.1 of [RFC7231]). The rank value is a real number in the range 0 through 1, where 0.001 is the least preferred and 1 is the most preferred; a value of 0 means "not acceptable". ๐ฅ
If the TE field-value is empty or if no TE field is present, the only acceptable transfer coding is chunked. A message with no transfer coding is always acceptable. ๐
Since the TE header field only applies to the immediate connection, a sender of TE MUST also send a "TE" connection option within the Connection header field (Section 6.1) in order to prevent the TE field from being forwarded by intermediaries that do not support its semantics. Don't forget this, or the whole thing falls apart ๐ โจ
4.4. Trailer
Okay so, when a message uses the chunked transfer coding and the sender wants to attach metadata as trailer fields at the end, the sender SHOULD send a Trailer header field before the message body. ๐ That tells the recipient which fields are coming in the trailers, so it can get ready before it starts processing the body. This is super useful if the message is streaming and the recipient wants to run an integrity check on the fly ๐งโจ
Trailer = 1#field-name
5. Message Routing ๐ฆ
Okay, so each client decides where an HTTP request gets routed, based on the target resource, its proxy configuration, and whether it sets up a new inbound connection or reuses one ๐ The response then takes the same connection chain back to the client, bestie ๐ซถ
5.1. Identifying a Target Resource ๐ธ
HTTP is literally everywhere, from big general-purpose computers all the way down to home appliances ๐ Sometimes a client's communication options are hard-coded into its config. But most HTTP clients rely on the same resource identification and configuration tricks that regular web browsers use, which is so iconic ๐
A user agent starts HTTP communication for some purpose. That purpose is a mix of request semantics, defined in [RFC7231], and a target resource to apply those semantics to. A URI reference (Section 2.7) is usually used as the identifier for the "target resource". The user agent resolves it to its absolute form to get the "target URI". The target URI leaves off the reference's fragment component, if there is one, because fragment identifiers are reserved for client-side processing ([RFC3986], Section 3.5) ๐ง not the server's job, periodt ๐
5.2. Connecting Inbound ๐ฅ
Once the target URI is set, a client has to figure out whether it even needs a network request to get the semantics it wants. If it does, it also needs to know where that request is headed ๐บ๏ธ
If the client has a cache [RFC7234] and the cache can satisfy the request, the request usually goes there first. Cache first, no cap ๐
If the cache can't satisfy it, a typical client checks its config to see if a proxy should be used. Proxy config is up to the implementation ๐ but it's often based on URI prefix matching, selective authority matching, or both. The proxy itself is usually identified by an "http" or "https" URI. If a proxy applies, the client connects inbound by setting up (or reusing) a connection to that proxy ๐ง
If no proxy applies, a typical client calls a handler routine, usually specific to the target URI's scheme, to connect directly to an authority for the target resource. How that works depends on the target URI scheme and its own specification. It's kind of like how this spec defines origin server access for the "http" (Section 2.7.1) and "https" (Section 2.7.2) schemes โจ
HTTP connection management rules live in Section 6, so go check there ๐ซง
5.3. Request Target ๐
Once an inbound connection exists, the client sends an HTTP request message (Section 3) with a request-target derived from the target URI. There are four distinct request-target formats. Which one you use depends on the method being requested and whether the request is going to a proxy ๐
request-target = origin-form
/ absolute-form
/ authority-form
/ asterisk-form
5.3.1. origin-form ๐ท
The origin-form is the most common request-target, and it's the one you'll see the most, iykyk ๐ญ
origin-form = absolute-path [ "?" query ]
When a client makes a request directly to an origin server, the rule is different for CONNECT and server-wide OPTIONS requests (more on those below). For everything else, the client MUST send only the absolute path and query components of the target URI as the request-target. If the target URI's path is empty, the client MUST send "/" as the path in the origin-form request-target. And it also sends a Host header field, defined in Section 5.4 ๐
For example, say a client wants a representation of the resource at
http://www.example.org/where?q=now
It goes straight to the origin server. It opens (or reuses) a TCP connection to port 80 of the host "www.example.org" and sends these lines:
GET /where?q=now HTTP/1.1
Host: www.example.org
Then it sends the rest of the request message ๐งโจ
5.3.2. absolute-form ๐ฆ
When a client makes a request to a proxy, the CONNECT and server-wide OPTIONS requests are the exception again. For everything else, the client MUST send the target URI in absolute-form as the request-target ๐
absolute-form = absolute-URI
The proxy is asked to either serve the request from a valid cache, if it can, or make the same request for the client. It can forward it to the next inbound proxy or directly to the origin server named in the request-target. The rules for that kind of "forwarding" are in Section 5.7 ๐ฅ
Here's an example absolute-form request-line:
GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1
Some future version of HTTP is planning to use absolute-form for all requests. To make that transition easier, a server MUST accept the absolute-form in requests. HTTP/1.1 clients will only send it to proxies though, so don't panic about that ๐
5.3.3. authority-form ๐ธ
The authority-form is only used for CONNECT requests (Section 4.3.6 of [RFC7231]) ๐
authority-form = authority
When a client makes a CONNECT request to set up a tunnel through one or more proxies, it MUST send only the target URI's authority component as the request-target. That means no userinfo and no "@" delimiter. For example:
CONNECT www.example.com:80 HTTP/1.1
5.3.4. asterisk-form ๐
The asterisk-form is only used for a server-wide OPTIONS request (Section 4.3.7 of [RFC7231]) ๐ง
asterisk-form = "*"
Sometimes a client wants OPTIONS for the whole server, not one specific resource on it. In that case, the client MUST send only "*" (%x2A) as the request-target. For example:
OPTIONS * HTTP/1.1
Now here's the twist ๐ If a proxy gets an OPTIONS request with an absolute-form request-target, and the URI has an empty path and no query component, then the last proxy on the request chain MUST send a request-target of "*" when it forwards the request to the origin server. Main character energy for that last proxy โจ
For example, this request:
OPTIONS http://www.example.org:8001 HTTP/1.1
gets forwarded by the final proxy as:
OPTIONS * HTTP/1.1
Host: www.example.org:8001
after it connects to port 8001 of the host "www.example.org" ๐ซถ
5.4. Host ๐
The "Host" header field in a request tells the origin server the host and port from the target URI. That's how the server can tell resources apart when it's serving requests for lots of host names on one IP address ๐
Host = uri-host [ ":" port ] ; Section 2.7.1
A client MUST send a Host header field in all HTTP/1.1 request messages. If the target URI has an authority component, the client MUST send a field-value for Host that matches that authority component exactly, leaving out any userinfo subcomponent and its "@" delimiter (Section 2.7.1). If the authority component is missing or undefined for the target URI, the client MUST send a Host header field with an empty field-value ๐
Host field-value is super critical for handling a request, so a user agent SHOULD put Host as the first header field right after the request-line ๐ฅ
For example, a GET request to the origin server for <http://www.example.org/pub/WWW/> starts like this:
GET /pub/WWW/ HTTP/1.1
Host: www.example.org
A client MUST send a Host header field in an HTTP/1.1 request even if the request-target is in absolute-form. This lets the Host info get forwarded through ancient HTTP/1.0 proxies that might not have implemented Host ๐ they're giving vintage ๐
When a proxy gets a request with an absolute-form request-target, the proxy MUST ignore any received Host header field and replace it with the host info from the request-target. A proxy that forwards such a request MUST generate a new Host field-value based on the received request-target, and it can't just forward the Host value it got ๐ง
Host is basically an application-level routing mechanism, so it's a favourite target for malware trying to poison a shared cache or redirect a request somewhere it shouldn't go ๐ญ An interception proxy is extra vulnerable if it uses the Host field-value to redirect requests to internal servers, or as a cache key in a shared cache, without first checking that the intercepted connection really targets a valid IP address for that host. Please don't skip that check, bestie ๐จ
A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field. It also MUST respond with 400 to any request message that contains more than one Host header field, or a Host header field with an invalid field-value ๐
5.5. Effective Request URI โจ
Okay so the request-target usually only has part of the user agent's target URI ๐งฉ, which means the server has to put the full picture back together to service the request properly ๐ . That reconstruction uses the server's local configuration plus the info in the request-target, the Host header field, and the connection context ๐.
For a user agent, the effective request URI is the target URI ๐ฆ.
If the request-target is in absolute-form, the effective request URI is literally the same as the request-target โจ. Otherwise, it gets built in four steps:
- Scheme: If the server's configuration (or outbound gateway) gives a fixed URI scheme, that scheme gets used ๐. Otherwise, if the request came in over a TLS-secured TCP connection, the scheme is
https. If not, it'shttp. - Authority: This one has a whole chain of checks ๐ซถ
- If the server's configuration (or outbound gateway) gives a fixed URI authority component, that authority is used.
- If not, and the request-target is in authority-form, the authority component is the same as the request-target.
- If not, and a Host header field is supplied with a non-empty field-value, the authority component is the same as the Host field-value.
- Otherwise, the authority component is the default name configured for the server. Then, if the connection's incoming TCP port number is different from the default port for the effective request URI's scheme, a colon (
:) and the incoming port number (in decimal form) get tacked onto the end ๐.
- Path and query: If the request-target is in authority-form or asterisk-form, the combined path and query component is empty ๐. Otherwise, it's the same as the request-target.
- Put it together: Once everything is figured out, you can combine the pieces into absolute-URI form by sticking together the scheme,
://, the authority, and the combined path and query component ๐ง.
Here are two examples, because examples are everything ๐ธ.
Example 1: this message received over an insecure TCP connection
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.example.org:8080
has an effective request URI of
http://www.example.org:8080/pub/WWW/TheProject.html
Example 2: this message received over a TLS-secured TCP connection
OPTIONS * HTTP/1.1
Host: www.example.org
has an effective request URI of
https://www.example.org
Quick heads up for HTTP/1.0 requests that don't have a Host header field ๐. Recipients of those might need to use heuristics (for example, looking at the URI path for something unique to a particular host) to guess the effective request URI's authority component. It's giving detective energy ๐ต๏ธโโ๏ธโจ.
Once the effective request URI is built, an origin server needs to decide whether or not to provide service for that URI over the connection the request came in on ๐ก๏ธ. The request might have been misdirected, deliberately or by accident, so the info in the received request-target or Host header field doesn't match the host or port the connection was made to. If the connection is from a trusted gateway, that mismatch might be expected ๐ค. Otherwise, it might be someone trying to bypass security filters, trick the server into delivering non-public content, or poison a cache ๐. See Section 9 for security considerations regarding message routing. Please read that section, it's serious ๐ญ.
5.6. Associating a Response to a Request ๐๏ธ
HTTP doesn't include a request identifier for linking a request message to its matching response message or messages ๐. So instead, it depends on responses arriving in the same order the requests were sent on that connection. More than one response per request only happens when one or more informational responses (1xx, see Section 6.2 of [RFC7231]) come before the final response to that same request ๐ฌ.
A client that has more than one outstanding request on a connection MUST maintain a list of those outstanding requests in the order they were sent ๐. It MUST associate each response message received on that connection with the highest-ordered request that hasn't received a final (non-1xx) response yet ๐ซก.
5.7. Message Forwarding ๐
As we covered in Section 2.3, intermediaries can have all kinds of roles when it comes to processing HTTP requests and responses ๐ง . Some are there to improve performance or availability ๐. Others handle access control or filter content ๐ง. An HTTP stream is kind of like a pipe-and-filter setup, so there's no inherent limit on how much an intermediary can enhance (or interfere with) either direction of the stream ๐.
An intermediary that isn't acting as a tunnel MUST implement the Connection header field, as specified in Section 6.1 ๐, and it has to exclude fields from being forwarded if they're only meant for the incoming connection ๐ โโ๏ธ.
An intermediary MUST NOT forward a message to itself unless it's protected from an infinite request loop ๐. Generally, an intermediary ought to recognize its own server names (including any aliases, local variations, or literal IP addresses) and respond to those requests directly ๐.
5.7.1. Via ๐งญ
The "Via" header field shows the intermediate protocols and recipients between the user agent and the server (on requests), or between the origin server and the client (on responses) ๐บ๏ธ. It's basically the HTTP version of the "Received" header field in email (Section 3.6.7 of [RFC5322]) ๐. Via can be used for tracking message forwards, avoiding request loops, and figuring out the protocol capabilities of senders along the request/response chain ๐ธ๏ธ.
Here's the grammar, no cap:
Via = 1#( received-protocol RWS received-by [ RWS comment ] )
received-protocol = [ protocol-name "/" ] protocol-version
; see Section 6.7
received-by = ( uri-host [ ":" port ] ) / pseudonym
pseudonym = token
Each Via field value stands for one proxy or gateway that forwarded the message ๐. Every intermediary tacks on its own info about how it received the message, so the whole list ends up in the order of the forwarding recipients ๐.
A proxy MUST send an appropriate Via header field, as described below, in each message it forwards ๐ฎ. An HTTP-to-HTTP gateway MUST send an appropriate Via header field in each inbound request message, and it MAY send a Via header field in forwarded response messages ๐.
For each intermediary, the received-protocol tells you the protocol and protocol version the upstream sender used ๐ท๏ธ. So the Via field value keeps a record of the advertised protocol capabilities of the request/response chain, and downstream recipients can still see it ๐๏ธ. That's useful for figuring out which backwards-incompatible features are safe to use in a response, or in a later request, as described in Section 2.6 โจ. For brevity, the protocol-name gets left out when the received protocol is HTTP ๐ซถ.
The received-by part is normally the host and optional port number of the recipient server or client that forwarded the message onward ๐ก. But if the real host is sensitive info, a sender MAY replace it with a pseudonym ๐ซฃ. If no port is given, a recipient MAY read that as meaning it came in on the default TCP port for the received-protocol, if there is one ๐.
A sender MAY generate comments in the Via header field to identify the software of each recipient, kind of like the User-Agent and Server header fields ๐ค. But all comments in the Via field are optional, and a recipient MAY remove them before forwarding the message ๐งน.
Let's do an example, because I'm obsessed with them ๐ฅน. A request message gets sent from an HTTP/1.0 user agent to an internal proxy code-named "fred". Fred uses HTTP/1.1 to forward the request to a public proxy at p.example.net, which then finishes the job by forwarding it to the origin server at www.example.com. The request that www.example.com receives would have this Via header field:
Via: 1.0 fred, 1.1 p.example.net
An intermediary that's used as a portal through a network firewall SHOULD NOT forward the names and ports of hosts inside the firewall region, unless it's explicitly enabled to do so ๐งฑ. If it isn't enabled, that intermediary SHOULD replace each received-by host of any host behind the firewall with an appropriate pseudonym for that host ๐ญ.
An intermediary MAY combine an ordered subsequence of Via header field entries into one entry, as long as the entries have identical received-protocol values ๐งฉ. For example,
Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
could be collapsed to
Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
A sender SHOULD NOT combine multiple entries unless they're all under the same organizational control and the hosts have already been replaced by pseudonyms ๐ซข. And a sender MUST NOT combine entries that have different received-protocol values ๐ซ. Don't mix those up, bestie ๐ ๐.
5.7.2. Transformations ๐
okay so some intermediaries can actually transform messages and their payloads ๐ซฃ like, a proxy might convert between image formats to save cache space or to cut traffic on a slow link. ngl that's so clever. BUT it can go badly when the payload matters a lot, like medical imaging or scientific data analysis, especially when integrity checks or digital signatures are used to prove the payload is exactly identical to the original. ๐ญ one changed byte and the whole thing is cooked.
An HTTP-to-HTTP proxy is called a "transforming proxy" if it is designed or configured to modify messages in a semantically meaningful way (i.e., modifications, beyond those required by normal HTTP processing, that change the message in a way that would be significant to the original sender or potentially significant to downstream recipients). For example, a transforming proxy might be acting as a shared annotation server (modifying responses to include references to a local annotation database), a malware filter, a format transcoder, or a privacy filter. Such transformations are presumed to be desired by whichever client (or client organization) selected the proxy. ๐ง
If a proxy receives a request-target with a host name that is not a fully qualified domain name, it MAY add its own domain to the host name it received when forwarding the request. A proxy MUST NOT change the host name if the request-target contains a fully qualified domain name. ๐
A proxy MUST NOT modify the "absolute-path" and "query" parts of the received request-target when forwarding it to the next inbound server, except as noted above to replace an empty path with "/" or "*". no touching the path or query, bestie ๐ โโ๏ธ
A proxy MAY modify the message body through application or removal of a transfer coding (Section 4).
A proxy MUST NOT transform the payload (Section 3.3 of [RFC7231]) of a message that contains a no-transform cache-control directive (Section 5.2 of [RFC7234]). ๐
A proxy MAY transform the payload of a message that does not contain a no-transform cache-control directive. A proxy that transforms a payload MUST add a Warning header field with the warn-code of 214 ("Transformation Applied") if one is not already in the message (see Section 5.5 of [RFC7234]). A proxy that transforms the payload of a 200 (OK) response can further inform downstream recipients that a transformation has been applied by changing the response status code to 203 (Non-Authoritative Information) (Section 6.3.4 of [RFC7231]). โจ that's the transparency glow-up we love to see
A proxy SHOULD NOT modify header fields that provide information about the endpoints of the communication chain, the resource state, or the selected representation (other than the payload) unless the field's definition specifically allows such modification or the modification is deemed necessary for privacy or security. ๐ซถ
6. Connection Management ๐ธ
HTTP messaging is independent of the underlying transport- or session-layer connection protocol(s). HTTP only presumes a reliable transport with in-order delivery of requests and the corresponding in-order delivery of responses. The mapping of HTTP request and response structures onto the data units of an underlying transport protocol is outside the scope of this specification. it's not HTTP's job to babysit TCP segments, obviously ๐
As described in Section 5.2, the specific connection protocols to be used for an HTTP interaction are determined by client configuration and the target URI. For example, the "http" URI scheme (Section 2.7.1) indicates a default connection of TCP over IP, with a default TCP port of 80, but the client might be configured to use a proxy via some other connection, port, or protocol. ๐ฆ
HTTP implementations are expected to engage in connection management, which includes maintaining the state of current connections, establishing a new connection or reusing an existing connection, processing messages received on a connection, detecting connection failures, and closing each connection. Most clients maintain multiple connections in parallel, including more than one connection per server endpoint. Most servers are designed to maintain thousands of concurrent connections, while controlling request queues to enable fair use and detect denial-of-service attacks. the servers are literally juggling thousands of connections and still being fair?? iconic ๐
6.1. Connection ๐
The "Connection" header field allows the sender to indicate desired control options for the current connection. In order to avoid confusing downstream recipients, a proxy or gateway MUST remove or replace any received connection options before forwarding the message.
When a header field aside from Connection is used to supply control information for or about the current connection, the sender MUST list the corresponding field-name within the Connection header field. A proxy or gateway MUST parse a received Connection header field before a message is forwarded and, for each connection-option in this field, remove any header field(s) from the message with the same name as the connection-option, and then remove the Connection header field itself (or replace it with the intermediary's own connection options for the forwarded message).
Hence, the Connection header field provides a declarative way of distinguishing header fields that are only intended for the immediate recipient ("hop-by-hop") from those fields that are intended for all recipients on the chain ("end-to-end"), enabling the message to be self-descriptive and allowing future connection-specific extensions to be deployed without fear that they will be blindly forwarded by older intermediaries. ๐ง the Connection header is basically a little label saying "this one's just for us, don't pass it on"
The Connection header field's value has the following grammar:
Connection = 1#connection-option
connection-option = token
Connection options are case-insensitive. ๐
A sender MUST NOT send a connection option corresponding to a header field that is intended for all recipients of the payload. For example, Cache-Control is never appropriate as a connection option (Section 5.2 of [RFC7234]). ๐ซ
The connection options do not always correspond to a header field present in the message, since a connection-specific header field might not be needed if there are no parameters associated with a connection option. In contrast, a connection-specific header field that is received without a corresponding connection option usually indicates that the field has been improperly forwarded by an intermediary and ought to be ignored by the recipient. so if you see a random hop-by-hop header with no matching option, it's sus and should be ignored ๐
When defining new connection options, specification authors ought to survey existing header field names and ensure that the new connection option does not share the same name as an already deployed header field. Defining a new connection option essentially reserves that potential field-name for carrying additional information related to the connection option, since it would be unwise for senders to use that field-name for anything else. ๐ name collisions are not the vibe
The "close" connection option is defined for a sender to signal that this connection will be closed after completion of the response. For example,
Connection: close
in either the request or the response header fields indicates that the sender is going to close the connection after the current request/response is complete (Section 6.6). ๐ bye bye connection
A client that does not support persistent connections MUST send the "close" connection option in every request message.
A server that does not support persistent connections MUST send the "close" connection option in every response message that does not have a 1xx (Informational) status code. ๐ซก
6.2. Establishment ๐งโโ๏ธ
It is beyond the scope of this specification to describe how connections are established via various transport- or session-layer protocols. Each connection applies to only one transport link. not my department, sweetie ๐
6.3. Persistence ๐
HTTP/1.1 defaults to the use of "persistent connections", allowing multiple requests and responses to be carried over a single connection. The "close" connection option is used to signal that a connection will not persist after the current request/response. HTTP implementations SHOULD support persistent connections. stay-alive era, obviously โจ
A recipient determines whether a connection is persistent or not based on the most recently received message's protocol version and Connection header field (if any):
- If the "close" connection option is present, the connection will not persist after the current response; else,
- If the received protocol is HTTP/1.1 (or later), the connection will persist after the current response; else,
- If the received protocol is HTTP/1.0, the "keep-alive" connection option is present, the recipient is not a proxy, and the recipient wishes to honor the HTTP/1.0 "keep-alive" mechanism, the connection will persist after the current response; otherwise,
- The connection will close after the current response.
A client MAY send additional requests on a persistent connection until it sends or receives a "close" connection option or receives an HTTP/1.0 response without a "keep-alive" connection option. ๐
In order to remain persistent, all messages on a connection need to have a self-defined message length (i.e., one not defined by closure of the connection), as described in Section 3.3. A server MUST read the entire request message body or close the connection after sending its response, since otherwise the remaining data on a persistent connection would be misinterpreted as the next request. Likewise, a client MUST read the entire response message body if it intends to reuse the same connection for a subsequent request. ๐ฑ leftover bytes would get read as a whole new request, chaos
A proxy server MUST NOT maintain a persistent connection with an HTTP/1.0 client (see Section 19.7.1 of [RFC2068] for information and discussion of the problems with the Keep-Alive header field implemented by many HTTP/1.0 clients). ๐
See Appendix A.1.2 for more information on backwards compatibility with HTTP/1.0 clients. ๐
6.3.1. Retrying Requests ๐
Connections can be closed at any time, with or without intention. Implementations ought to anticipate the need to recover from asynchronous close events. expect the unexpected, that's the whole mindset ๐ซ
When an inbound connection is closed prematurely, a client MAY open a new connection and automatically retransmit an aborted sequence of requests if all of those requests have idempotent methods (Section 4.2.2 of [RFC7231]). A proxy MUST NOT automatically retry non-idempotent requests.
A user agent MUST NOT automatically retry a request with a non-idempotent method unless it has some means to know that the request semantics are actually idempotent, regardless of the method, or some means to detect that the original request was never applied. For example, a user agent that knows (through design or configuration) that a POST request to a given resource is safe can repeat that request automatically. Likewise, a user agent designed specifically to operate on a version control repository might be able to recover from partial failure conditions by checking the target resource revision(s) after a failed connection, reverting or fixing any changes that were partially applied, and then automatically retrying the requests that failed. ๐ ๏ธ retrying a POST without knowing it's safe is how you double-charge someone, so be careful, babe
A client SHOULD NOT automatically retry a failed automatic retry. ๐ no retry spirals, we're not doing that
6.3.2. Pipelining ๐
okay bestie, so pipelining is when a client that does persistent connections sends a bunch of requests back to back without waiting for each response first ๐จ the client MAY do this. a server MAY process a batch of pipelined requests in parallel if they ALL have safe methods (Section 4.2.1 of [RFC7231]), but it MUST send the responses back in the same order the requests came in. no shuffling!! ๐
a client that pipelines SHOULD retry any unanswered requests if the connection closes before it gets all the responses back ๐ now here's the tea. when you retry pipelined requests after a failed connection (one the server didn't explicitly close in its last complete response), a client MUST NOT pipeline right after the connection is set up, because the first leftover request in the old pipeline might have caused an error response that can get lost AGAIN if you send multiple requests on a connection that got closed too early. this is the TCP reset problem from Section 6.6 and it is SO chaotic ๐ญ
idempotent methods (Section 4.2.2 of [RFC7231]) matter a lot for pipelining because they can be retried automatically after a connection failure โจ a user agent SHOULD NOT pipeline requests after a non-idempotent method until the final response status code for that method has arrived, unless the user agent has a way to detect and recover from partial failures in the pipelined sequence. that's the safety net, periodt ๐ง
an intermediary that receives pipelined requests MAY pipeline them again when it forwards them inbound, since it can count on the outbound user agent(s) to figure out which requests are safe to pipeline ๐ฆ if the inbound connection fails before a response comes back, the pipelining intermediary MAY try to retry the requests that haven't gotten a response yet, but ONLY if they all have idempotent methods. otherwise, the intermediary SHOULD forward any responses it already got and then close the matching outbound connection(s) so the outbound user agent(s) can recover on their own ๐ธ
6.4. Concurrency ๐
okay so a client ought to limit how many simultaneous open connections it keeps open to a given server. this one is giving self-control ๐ซถ
previous versions of HTTP set a specific number of connections as a ceiling, but that turned out to be impractical for lots of apps ๐ so this spec doesn't force a particular maximum number of connections. instead, it encourages clients to be conservative when they open multiple connections. be chill, bestie ๐
why do clients open multiple connections anyway? to dodge the "head-of-line blocking" problem, where one request that takes a ton of server-side processing and/or has a huge payload blocks all the requests behind it on the same connection ๐ง but every connection eats up server resources, and using a bunch of them can cause some messy side effects on congested networks. so the vibe is balance โ๏ธ
also, a server might reject traffic it considers abusive or like a denial-of-service attack, such as an excessive number of open connections from a single client ๐จ
6.5. Failures and Timeouts โฐ
servers usually have some timeout value after which they stop keeping an inactive connection open ๐ค proxy servers might set this to a higher value, since the client will probably be making more connections through the same proxy. the use of persistent connections doesn't put any requirements on the length (or even the existence) of this timeout for either the client or the server ๐คทโโ๏ธ
a client or server that wants to time out SHOULD issue a graceful close on the connection ๐ implementations SHOULD constantly keep an eye on open connections for a received closure signal and respond to it as appropriate, because closing both sides of a connection promptly lets the system reclaim its resources โจ
a client, server, or proxy MAY close the transport connection at any time ๐ for example, a client might start sending a new request at the same moment the server decides to close the "idle" connection. from the server's point of view, the connection is closing while it's idle, but from the client's point of view, a request is in progress. oof, timing is everything ๐ฌ
a server SHOULD sustain persistent connections when possible and let the underlying transport's flow-control mechanisms handle temporary overloads, instead of killing connections and hoping clients will retry. that last technique can make network congestion even worse ๐ฆ
a client sending a message body SHOULD keep watching the network connection for an error response while it's transmitting the request ๐ if the client sees a response saying the server doesn't want the message body and is closing the connection, the client SHOULD immediately stop sending the body and close its side of the connection. bye bye ๐๐
6.6. Tear-down ๐ซถ
the Connection header field (Section 6.1) gives you a "close" connection option, and a sender SHOULD send it when it wants to close the connection after the current request/response pair ๐
a client that sends a "close" connection option MUST NOT send any more requests on that connection (after the one containing "close"), and it MUST close the connection after reading the final response message for that request. clean exit, no drama ๐ชโจ
a server that gets a "close" connection option MUST initiate a close of the connection (see below) after it sends the final response to the request that had "close" in it. the server SHOULD send a "close" connection option in its final response on that connection. and the server MUST NOT process any more requests that come in on that connection. rules are rules, bestie ๐
a server that sends a "close" connection option MUST initiate a close of the connection (see below) after it sends the response containing "close". the server MUST NOT process any further requests received on that connection ๐
a client that receives a "close" connection option MUST stop sending requests on that connection and close it after reading the response message that had "close" in it. if any extra pipelined requests were already sent on the connection, the client SHOULD NOT assume the server will process them ๐ฅฒ
now, the scary part ๐ฑ if a server does an immediate close of a TCP connection, there's a big risk the client won't be able to read the last HTTP response. if the server gets more data from the client on a fully closed connection (like another request the client sent before it saw the server's response), the server's TCP stack will send a reset packet to the client. and unfortunately, that reset packet might wipe out the client's unacknowledged input buffers before the client's HTTP parser can read and interpret them ๐
so to avoid the TCP reset problem, servers usually close connections in stages ๐ first, the server does a half-close by closing only the write side of the read/write connection. then it keeps reading from the connection until the client closes its side too, or until the server is reasonably sure its own TCP stack has received the client's acknowledgement of the packet(s) holding the server's last response. finally, the server fully closes the connection. slow and steady wins the race ๐ข๐
it is unknown whether the reset problem is exclusive to TCP or whether it might also show up in other transport connection protocols ๐ค
6.7. Upgrade ๐
okay so Upgrade is basically a cute little invite ๐ for switching from HTTP/1.1 over to some other protocol on the same connection. A client MAY send a list of protocols in the Upgrade header field of a request, in order of descending preference, asking the server to switch to one or more of them before the final response is sent. A server MAY ignore a received Upgrade header field if it wants to keep using the current protocol on that connection. Upgrade can't be used to insist on a protocol change, so it's always the server's call ๐ซถ
Upgrade = 1#protocol
protocol = protocol-name ["/" protocol-version]
protocol-name = token
protocol-version = token
A server that sends a 101 (Switching Protocols) response MUST send an Upgrade header field to say which new protocol(s) the connection is switching to. If multiple protocol layers are being switched, the sender MUST list the protocols in layer-ascending order ๐ช A server MUST NOT switch to a protocol that the client didn't indicate in the Upgrade header field of the corresponding request โ A server MAY choose to ignore the client's order of preference and pick the new protocol(s) based on other factors, such as the nature of the request or the current load on the server ๐ง
A server that sends a 426 (Upgrade Required) response MUST send an Upgrade header field to indicate the acceptable protocols, in order of descending preference ๐
A server MAY send an Upgrade header field in any other response too, to advertise that it supports upgrading to the listed protocols, in order of descending preference, when that's appropriate for a future request ๐
Here's a hypothetical example sent by a client:
GET /hello.txt HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
The capabilities and nature of the application-level communication after the protocol change depend entirely on the new protocol(s) that get chosen. But right after sending the 101 (Switching Protocols) response, the server is expected to keep answering the original request as if it had received its equivalent inside the new protocol. The server still has an outstanding request to satisfy after the switch, and it's expected to do that without the request having to be sent again ๐
So say an Upgrade header field shows up in a GET request and the server decides to switch. It first replies with a 101 (Switching Protocols) message in HTTP/1.1, and then immediately follows that with the new protocol's version of a response to a GET on the target resource ๐ This lets a connection be upgraded to protocols with the same semantics as HTTP without paying the latency cost of an extra round trip โก A server MUST NOT switch protocols unless the semantics of the received message can be honored by the new protocol. An OPTIONS request can be honored by any protocol ๐
Here's an example response to that hypothetical request:
HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: HTTP/2.0
[... data stream switches to HTTP/2.0 with an appropriate response
(as defined by new protocol) to the "GET /hello.txt" request ...]
When Upgrade is sent, the sender MUST also send a Connection header field (Section 6.1) that contains an "upgrade" connection option. That's how we stop Upgrade from getting accidentally forwarded by intermediaries that might not implement the listed protocols ๐ก๏ธ A server MUST ignore an Upgrade header field that is received in an HTTP/1.0 request ๐ โโ๏ธ
A client can't start using an upgraded protocol on the connection until it has completely sent the request message. (It can't switch protocols halfway through a message, bestie ๐ญ) If a server receives both an Upgrade and an Expect header field with the "100-continue" expectation (Section 5.1.1 of [RFC7231]), the server MUST send a 100 (Continue) response before sending a 101 (Switching Protocols) response โจ
The Upgrade header field only applies to switching protocols on top of the existing connection. It can't be used to switch the underlying connection (transport) protocol, and it can't be used to move the existing communication to a different connection. For those jobs, a 3xx (Redirection) response is the better tool (Section 6.4 of [RFC7231]) ๐ง
This specification only defines the protocol name "HTTP" for use by the family of Hypertext Transfer Protocols, as defined by the HTTP version rules of Section 2.6 and future updates to this specification. Additional tokens ought to be registered with IANA using the registration procedure defined in Section 8.6 ๐
7. ABNF List Extension: #rule โจ
A #rule extension to the ABNF rules of [RFC5234] makes the definitions of some header field values way easier to read ๐
A construct "#" is defined, similar to "*", for writing comma-delimited lists of elements. The full form is "<n>#<m>element", which means at least <n> and at most <m> elements, each separated by a single comma (",") and optional whitespace (OWS) ๐
In any production that uses the list construct, a sender MUST NOT generate empty list elements. In other words, a sender MUST generate lists that satisfy the following syntax:
1#element => element *( OWS "," OWS element )
and:
#element => [ 1#element ]
and, for n >= 1 and m > 1:
<n>#<m>element => element <n-1>*<m-1>( OWS "," OWS element )
For compatibility with legacy list rules, a recipient MUST parse and ignore a reasonable number of empty list elements. That's enough to handle common sender mistakes that merge values, but not so many that they could be abused as a denial-of-service mechanism ๐ In other words, a recipient MUST accept lists that satisfy the following syntax:
#element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
Empty elements don't count toward the number of elements present ๐ซง For example, given these ABNF productions:
example-list = 1#example-list-elmt
example-list-elmt = token ; see Section 3.2.6
Then the following are valid values for example-list (the double quotes aren't part of the value, they're just there for delimitation):
"foo,bar"
"foo ,bar,"
"foo , ,bar,charlie "
On the flip side, these values would be invalid, since the example-list production needs at least one non-empty element ๐
""
","
", ,"
Appendix B shows the collected ABNF for recipients after the list constructs have been expanded ๐
8. IANA Considerations ๐ธ
8.1. Header Field Registration
HTTP header fields are registered within the "Message Headers" registry, which is maintained at <http://www.iana.org/assignments/message-headers/>.
This document defines the following HTTP header fields, so the "Permanent Message Header Field Names" registry has been updated to match (see [BCP90]) ๐
+-------------------+----------+----------+---------------+
| Header Field Name | Protocol | Status | Reference |
+-------------------+----------+----------+---------------+
| Connection | http | standard | Section 6.1 |
| Content-Length | http | standard | Section 3.3.2 |
| Host | http | standard | Section 5.4 |
| TE | http | standard | Section 4.3 |
| Trailer | http | standard | Section 4.4 |
| Transfer-Encoding | http | standard | Section 3.3.1 |
| Upgrade | http | standard | Section 6.7 |
| Via | http | standard | Section 5.7.1 |
+-------------------+----------+----------+---------------+
Furthermore, the header field-name "Close" has been registered as "reserved". Using that name as an HTTP header field might conflict with the "close" connection option of the Connection header field (Section 6.1), so it's off-limits ๐ โโ๏ธ
+-------------------+----------+----------+-------------+
| Header Field Name | Protocol | Status | Reference |
+-------------------+----------+----------+-------------+
| Close | http | reserved | Section 8.1 |
+-------------------+----------+----------+-------------+
The change controller is: "IETF (iesg@ietf.org) - Internet Engineering Task Force" ๐ฆ
8.2. URI Scheme Registration
IANA maintains the registry of URI Schemes [BCP115] at <http://www.iana.org/assignments/uri-schemes/> ๐
This document defines the following URI schemes, so the "Permanent URI Schemes" registry has been updated to match ๐
+------------+------------------------------------+---------------+
| URI Scheme | Description | Reference |
+------------+------------------------------------+---------------+
| http | Hypertext Transfer Protocol | Section 2.7.1 |
| https | Hypertext Transfer Protocol Secure | Section 2.7.2 |
+------------+------------------------------------+---------------+
8.3. Internet Media Type Registration
IANA maintains the registry of Internet media types [BCP13] at <http://www.iana.org/assignments/media-types> ๐
This document serves as the specification for the Internet media types "message/http" and "application/http". The following has been registered with IANA โจ
8.3.1. Internet Media Type message/http
The message/http type can be used to enclose a single HTTP request or response message, as long as it follows the MIME restrictions for all "message" types regarding line length and encodings ๐ฉ
Type name: message
Subtype name: http
Required parameters: N/A
Optional parameters: version, msgtype
version: The HTTP-version number of the enclosed message (e.g., "1.1"). If it isn't present, the version can be figured out from the first line of the body.msgtype: The message type, which is either "request" or "response". If it isn't present, the type can be figured out from the first line of the body.
Encoding considerations: only "7bit", "8bit", or "binary" are
permitted
Security considerations: see Section 9
Interoperability considerations: N/A
Published specification: This specification (see Section 8.3.1).
Applications that use this media type: N/A
Fragment identifier considerations: N/A
Additional information:
Magic number(s): N/A
Deprecated alias names for this type: N/A
File extension(s): N/A
Macintosh file type code(s): N/A
Person and email address to contact for further information:
See Authors' Addresses section.
Intended usage: COMMON
Restrictions on usage: N/A
Author: See Authors' Addresses section.
Change controller: IESG
8.3.2. Internet Media Type application/http ๐
okay so application/http is the media type you reach for when you want to wrap up a pipeline of one or more HTTP request or response messages ๐ (and they can't be intermixed, no mixing!! ๐
โโ๏ธ)
- Type name:
application๐ - Subtype name:
httpโจ - Required parameters: N/A
- Optional parameters:
version,msgtype๐ฆversion: the HTTP-version number of the enclosed messages (like "1.1" ๐ธ). If it isn't there, you can figure out the version from the first line of the body ๐งmsgtype: the message type, which is either "request" or "response" ๐ . If it isn't there, the type can be figured out from the first line of the body too ๐
- Encoding considerations: HTTP messages enclosed by this type are in "binary" format ๐ฅ. You need an appropriate
Content-Transfer-Encodingwhen they get sent over email ๐ง, it's not optional bestie ๐ญ - Security considerations: see Section 9 ๐
- Interoperability considerations: N/A
- Published specification: This specification (see Section 8.3.2) ๐
- Applications that use this media type: N/A
- Fragment identifier considerations: N/A
- Additional information:
- Deprecated alias names for this type: N/A
- Magic number(s): N/A
- File extension(s): N/A
- Macintosh file type code(s): N/A
- Person and email address to contact for further information: See Authors' Addresses section ๐
- Intended usage: COMMON ๐
- Restrictions on usage: N/A
- Author: See Authors' Addresses section โ๏ธ
- Change controller: IESG ๐
8.4. Transfer Coding Registry ๐ง
the "HTTP Transfer Coding Registry" is where the namespace for transfer coding names lives ๐๏ธ. It's maintained at <http://www.iana.org/assignments/http-parameters> ๐
8.4.1. Procedure ๐
Registrations MUST include the following fields:
- Name
- Description
- Pointer to specification text
Names of transfer codings MUST NOT overlap with names of content codings (Section 3.1.2.1 of [RFC7231]) unless the encoding transformation is identical, as is the case for the compression codings defined in Section 4.2. no overlapping names, unless it's literally the same transformation, which is the case for the compression codings in Section 4.2 ๐ โโ๏ธโจ
Values to be added to this namespace require IETF Review (see Section 4.1 of [RFC5226]), and MUST conform to the purpose of transfer coding defined in this specification ๐. So it has to match what transfer coding is actually for, as defined in this spec ๐ฏ
Use of program names for the identification of encoding formats is not desirable and is discouraged for future encodings. so please don't name encodings after programs, it's giving "not desirable" and it's discouraged for the future ๐
8.4.2. Registration ๐ธ
The "HTTP Transfer Coding Registry" has been updated with the registrations below:
+------------+--------------------------------------+---------------+
| Name | Description | Reference |
+------------+--------------------------------------+---------------+
| chunked | Transfer in a series of chunks | Section 4.1 |
| compress | UNIX "compress" data format [Welch] | Section 4.2.1 |
| deflate | "deflate" compressed data | Section 4.2.2 |
| | ([RFC1951]) inside the "zlib" data | |
| | format ([RFC1950]) | |
| gzip | GZIP file format [RFC1952] | Section 4.2.3 |
| x-compress | Deprecated (alias for compress) | Section 4.2.1 |
| x-gzip | Deprecated (alias for gzip) | Section 4.2.3 |
+------------+--------------------------------------+---------------+
8.5. Content Coding Registration ๐
IANA maintains the "HTTP Content Coding Registry" at <http://www.iana.org/assignments/http-parameters> ๐ง
The "HTTP Content Coding Registry" has been updated with the registrations below:
+------------+--------------------------------------+---------------+
| Name | Description | Reference |
+------------+--------------------------------------+---------------+
| compress | UNIX "compress" data format [Welch] | Section 4.2.1 |
| deflate | "deflate" compressed data | Section 4.2.2 |
| | ([RFC1951]) inside the "zlib" data | |
| | format ([RFC1950]) | |
| gzip | GZIP file format [RFC1952] | Section 4.2.3 |
| x-compress | Deprecated (alias for compress) | Section 4.2.1 |
| x-gzip | Deprecated (alias for gzip) | Section 4.2.3 |
+------------+--------------------------------------+---------------+
8.6. Upgrade Token Registry ๐
The "Hypertext Transfer Protocol (HTTP) Upgrade Token Registry" defines the namespace for protocol-name tokens used to identify protocols in the Upgrade header field ๐ช. The registry is maintained at <http://www.iana.org/assignments/http-upgrade-tokens> ๐
8.6.1. Procedure ๐๏ธ
Each registered protocol name is associated with contact information and an optional set of specifications that details how the connection will be processed after it has been upgraded ๐ค.
Registrations happen on a "First Come First Served" basis (see Section 4.1 of [RFC5226]) and are subject to the following rules:
- A protocol-name token, once registered, stays registered forever. Forever. ๐
- The registration MUST name a responsible party for the registration.
- The registration MUST name a point of contact.
- The registration MAY name a set of specifications associated with that token. Such specifications need not be publicly available ๐
- The registration SHOULD name a set of expected "protocol-version" tokens associated with that token at the time of registration.
- The responsible party MAY change the registration at any time. The IANA will keep a record of all such changes, and make them available upon request ๐
- The IESG MAY reassign responsibility for a protocol token. This will normally only be used in the case when a responsible party cannot be contacted ๐ซถ
This registration procedure for HTTP Upgrade Tokens replaces that previously defined in Section 7.2 of [RFC2817] ๐
8.6.2. Upgrade Token Registration โจ
The "HTTP" entry in the upgrade token registry has been updated with the registration below:
+-------+----------------------+----------------------+-------------+
| Value | Description | Expected Version | Reference |
| | | Tokens | |
+-------+----------------------+----------------------+-------------+
| HTTP | Hypertext Transfer | any DIGIT.DIGIT | Section 2.6 |
| | Protocol | (e.g, "2.0") | |
+-------+----------------------+----------------------+-------------+
The responsible party is: "IETF (iesg@ietf.org) - Internet Engineering Task Force" ๐
9. Security Considerations ๐
this section is here to inform developers, information providers, and users about the known security stuff that matters for HTTP message syntax, parsing, and routing ๐จ. Security stuff about HTTP semantics and payloads is handled in [RFC7231], so go check there too ๐
9.1. Establishing Authority ๐ฐ
HTTP relies on the notion of an authoritative response: a response that has been determined by (or at the direction of) the authority identified within the target URI to be the most appropriate response for that request given the state of the target resource at the time of response message origination. Providing a response from a non-authoritative source, such as a shared cache, is often useful to improve performance and availability, but only to the extent that the source can be trusted or the distrusted response can be safely used. so basically, a random source being helpful is only ok if you can actually trust it ๐ฅบ
Unfortunately, establishing authority can be difficult. For example, phishing is an attack on the user's perception of authority, where that perception can be misled by presenting similar branding in hypertext, possibly aided by userinfo obfuscating the authority component (see Section 2.7.1). User agents can reduce the impact of phishing attacks by enabling users to easily inspect a target URI prior to making an action, by prominently distinguishing (or rejecting) userinfo when present, and by not sending stored credentials and cookies when the referring document is from an unknown or untrusted source. phishing is literally a vibe-based attack ๐ญ so clients should make URIs easy to check, make userinfo super visible (or reject it), and not send stored credentials or cookies to sketchy referrers ๐ซ๐ช
When a registered name is used in the authority component, the "http" URI scheme (Section 2.7.1) relies on the user's local name resolution service to determine where it can find authoritative responses. This means that any attack on a user's network host table, cached names, or name resolution libraries becomes an avenue for attack on establishing authority. Likewise, the user's choice of server for Domain Name Service (DNS), and the hierarchy of servers from which it obtains resolution results, could impact the authenticity of address mappings; DNS Security Extensions (DNSSEC, [RFC4033]) are one way to improve authenticity. so if someone messes with the name lookup stuff, they can mess with who you think you're talking to ๐. DNSSEC ([RFC4033]) is one way to make the mappings more trustworthy ๐
Furthermore, after an IP address is obtained, establishing authority for an "http" URI is vulnerable to attacks on Internet Protocol routing ๐ฃ๏ธ. even after you have the IP address, somebody can still mess with the routing ๐ฉ
The "https" scheme (Section 2.7.2) is intended to prevent (or at least reveal) many of these potential attacks on establishing authority, provided that the negotiated TLS connection is secured and the client properly verifies that the communicating server's identity matches the target URI's authority component (see [RFC2818]). Correctly implementing such verification can be difficult (see [Georgiev]). this is why "https" is the one that's meant to stop (or at least expose) a lot of these attacks ๐โจ, as long as the TLS connection is actually secured and the client properly checks that the server's identity matches the authority in the target URI ๐ง. The checking part is genuinely hard to get right, so see [Georgiev] ๐ฅน
9.2. Risks of Intermediaries ๐ซฃ
By their very nature, HTTP intermediaries are men-in-the-middle and, thus, represent an opportunity for man-in-the-middle attacks. Compromise of the systems on which the intermediaries run can result in serious security and privacy problems. Intermediaries might have access to security-related information, personal information about individual users and organizations, and proprietary information belonging to users and content providers. A compromised intermediary, or an intermediary implemented or configured without regard to security and privacy considerations, might be used in the commission of a wide range of potential attacks. intermediaries are literally men-in-the-middle by design, so they're a juicy target ๐ญ๐จ. if one gets compromised (or was built or set up without caring about security and privacy), it can be used for a whole bunch of attacks ๐
Intermediaries that contain a shared cache are especially vulnerable to cache poisoning attacks, as described in Section 8 of [RFC7234] ๐งช. shared caches are extra vulnerable to cache poisoning, so read Section 8 of [RFC7234] ๐ฏ
Implementers need to consider the privacy and security implications of their design and coding decisions, and of the configuration options they provide to operators (especially the default configuration). devs, think about privacy and security in your design, your code, AND the config options you hand to operators, especially the defaults ๐ซถ๐ฅ
Users need to be aware that intermediaries are no more trustworthy than the people who run them; HTTP itself cannot solve this problem. ๐ซ real talk: an intermediary is only as trustworthy as whoever runs it, and HTTP can't fix that for you ๐
9.3. Attacks via Protocol Element Length โจ
okay so HTTP is mostly text that gets split up by delimiters, which means parsers are super vulnerable to attacks where someone sends really long (or really slow) streams of data ๐ญ. It's especially risky when the implementation is waiting for a protocol element that has no predefined length. bestie, that's a whole danger zone ๐.
To keep things interoperable, specific recommendations are made for minimum size limits on request-line (Section 3.1.1) and header fields (Section 3.2). These are minimum recommendations, picked so they're doable even for implementations with limited resources ๐ง. It's expected that most implementations will choose substantially higher limits ๐ .
A server can reject a message that has a request-target that is too long (Section 6.5.12 of [RFC7231]) or a request payload that is too large (Section 6.5.11 of [RFC7231]). Extensions to HTTP have also defined additional status codes for capacity limits [RFC6585] ๐.
Recipients ought to carefully limit how far they process other protocol elements, including (but not limited to) request methods, response status phrases, header field-names, numeric values, and body chunks ๐ซถ. If they don't limit that processing, you can get buffer overflows, arithmetic overflows, or more vulnerability to denial-of-service attacks ๐ฑ. not it, lol.
9.4. Response Splitting ๐ฅ
Response splitting (a.k.a, CRLF injection) is a super common trick used in all sorts of attacks on Web usage ๐ธ๏ธ. It exploits the line-based nature of HTTP message framing, and the way requests get matched up with responses in order on persistent connections [Klein]. This technique can be especially damaging when the requests go through a shared cache ๐.
So here's how it goes down: servers (usually inside an application server) can have a vulnerability where an attacker sends encoded data inside some parameter of the request. That data gets decoded later and echoed into one of the response header fields. If the decoded data is crafted to look like the response has ended and a new one has started, the response has been split, and the stuff in the fake second response is totally controlled by the attacker ๐. The attacker can then make any other request on that same persistent connection and trick the recipients (including intermediaries) into thinking the second half of the split is the real answer to the second request. main character energy, but make it villainous ๐.
For example, a parameter in the request-target might get read by an application server and reused inside a redirect, so the same parameter ends up echoed in the Location header field of the response ๐ฆ. If the application decodes that parameter and doesn't properly encode it when it goes into the response field, the attacker can send encoded CRLF octets and other content that makes one single response look like two or more responses ๐ญ.
A common defense is to filter requests for data that looks like encoded CR and LF (e.g., "%0D" and "%0A"). But that only works if the application server is just doing URI decoding, and not more sneaky transformations like charset transcoding, XML entity translation, base64 decoding, sprintf reformatting, etc. ๐. A more effective mitigation is to stop anything other than the server's core protocol libraries from sending a CR or LF within the header section. In practice, that means limiting header field output to APIs that filter out bad octets, and not letting application servers write directly to the protocol stream ๐ก๏ธ.
9.5. Request Smuggling ๐
Request smuggling ([Linhart]) is a technique that exploits differences in how various recipients parse the protocol. It hides extra requests (which might otherwise be blocked or disabled by policy) inside an apparently harmless request ๐ป. Like response splitting, request smuggling can lead to a whole bunch of attacks on HTTP usage ๐ตโ๐ซ.
This specification introduces new requirements on request parsing, especially around message framing in Section 3.3.3, to reduce how effective request smuggling can be ๐ซถ. slay for security ๐ช.
9.6. Message Integrity ๐
HTTP doesn't define one specific mechanism for ensuring message integrity ๐. Instead, it relies on the error-detection ability of the underlying transport protocols, plus length or chunk-delimited framing to detect completeness. Extra integrity mechanisms, like hash functions or digital signatures applied to the content, can be added selectively to messages through extensible metadata header fields ๐. Historically, the lack of a single integrity mechanism was justified by how informal most HTTP communication was. But HTTP is now used so much as an information access mechanism that it's increasingly showing up in places where verifying message integrity is crucial ๐ฉบ.
User agents are encouraged to implement configurable ways of detecting and reporting integrity failures, so those can be turned on in environments where integrity really matters ๐ธ. For example, a browser being used to view medical history or drug interaction information needs to tell the user when the protocol detects that the information is incomplete, expired, or corrupted during transfer ๐ณ. Those mechanisms might be turned on selectively through user agent extensions, or when there's message integrity metadata in a response โจ.
at the very minimum, user agents ought to give some indication that lets a user tell a complete response message apart from an incomplete one (Section 3.4) whenever that verification is wanted ๐.
9.7. Message Confidentiality ๐
HTTP relies on the underlying transport protocols to provide message confidentiality when that's wanted ๐. HTTP was specifically designed to be independent of the transport protocol, so it can run over many different forms of encrypted connection ๐ฆ. Which transport gets picked is identified by the choice of URI scheme, or by user agent configuration.
The "https" scheme can be used to identify resources that need a confidential connection, as described in Section 2.7.2 ๐.
9.8. Privacy of Server Log Information ๐
A server is in a position to save personal data about a user's requests over time ๐. That could reveal their reading patterns or subjects of interest ๐. Log information gathered at an intermediary especially often contains a history of user agent interaction across a multitude of sites, and that can be traced back to individual users ๐ฌ.
HTTP log information is confidential in nature, and how it's handled is often constrained by laws and regulations โ๏ธ. Log information needs to be stored securely, and appropriate guidelines need to be followed when it's analyzed ๐. Anonymizing personal information within individual entries helps, but it's generally not enough to stop real log traces from being re-identified by correlating them with other access characteristics ๐ต๏ธโโ๏ธ. So access traces keyed to a specific client are unsafe to publish, even if the key is pseudonymous ๐ซ.
To minimize the risk of theft or accidental publication, log information ought to be purged of personally identifiable information ๐งน. That includes user identifiers, IP addresses, and user-provided query parameters. Do it as soon as that information is no longer needed to support operational needs for security, auditing, or fraud control โฐ.
10. Acknowledgments ๐ซถ
okay bestie, this is the thank-you page and it's giving community ๐ธ This edition of HTTP/1.1 is built on everything that went into RFC 1945, RFC 2068, RFC 2145, and RFC 2616. Big shoutout to the previous authors, editors, and Working Group Chairs who did so much of the heavy lifting: Tim Berners-Lee, Ari Luotonen, Roy T. Fielding, Henrik Frystyk Nielsen, Jim Gettys, Jeffrey C. Mogul, Larry Masinter, and Paul J. Leach. Mark Nottingham kept the whole effort on track as Working Group Chair ๐
Since 1999, a huge crowd of contributors has made HTTP better by reporting bugs, asking smart questions, drafting or reviewing text, and working through open issues. Every single one of them is iconic ๐ Here's the list:
Adam Barth, Adam Roach, Addison Phillips, Adrian Chadd, Adrian Cole, Adrien W. de Croy, Alan Ford, Alan Ruttenberg, Albert Lunde, Alek Storm, Alex Rousskov, Alexandre Morgaut, Alexey Melnikov, Alisha Smith, Amichai Rothman, Amit Klein, Amos Jeffries, Andreas Maier, Andreas Petersson, Andrei Popov, Anil Sharma, Anne van Kesteren, Anthony Bryan, Asbjorn Ulsberg, Ashok Kumar, Balachander Krishnamurthy, Barry Leiba, Ben Laurie, Benjamin Carlyle, Benjamin Niven-Jenkins, Benoit Claise, Bil Corry, Bill Burke, Bjoern Hoehrmann, Bob Scheifler, Boris Zbarsky, Brett Slatkin, Brian Kell, Brian McBarron, Brian Pane, Brian Raymor, Brian Smith, Bruce Perens, Bryce Nesbitt, Cameron Heavon-Jones, Carl Kugler, Carsten Bormann, Charles Fry, Chris Burdess, Chris Newman, Christian Huitema, Cyrus Daboo, Dale Robert Anderson, Dan Wing, Dan Winship, Daniel Stenberg, Darrel Miller, Dave Cridland, Dave Crocker, Dave Kristol, Dave Thaler, David Booth, David Singer, David W. Morris, Diwakar Shetty, Dmitry Kurochkin, Drummond Reed, Duane Wessels, Edward Lee, Eitan Adler, Eliot Lear, Emile Stephan, Eran Hammer-Lahav, Eric D. Williams, Eric J. Bowman, Eric Lawrence, Eric Rescorla, Erik Aronesty, EungJun Yi, Evan Prodromou, Felix Geisendoerfer, Florian Weimer, Frank Ellermann, Fred Akalin, Fred Bohle, Frederic Kayser, Gabor Molnar, Gabriel Montenegro, Geoffrey Sneddon, Gervase Markham, Gili Tzabari, Grahame Grieve, Greg Slepak, Greg Wilkins, Grzegorz Calkowski, Harald Tveit Alvestrand, Harry Halpin, Helge Hess, Henrik Nordstrom, Henry S. Thompson, Henry Story, Herbert van de Sompel, Herve Ruellan, Howard Melman, Hugo Haas, Ian Fette, Ian Hickson, Ido Safruti, Ilari Liusvaara, Ilya Grigorik, Ingo Struck, J. Ross Nicoll, James Cloos, James H. Manger, James Lacey, James M. Snell, Jamie Lokier, Jan Algermissen, Jari Arkko, Jeff Hodges (who came up with the term 'effective Request-URI'), Jeff Pinner, Jeff Walden, Jim Luther, Jitu Padhye, Joe D. Williams, Joe Gregorio, Joe Orton, Joel Jaeggli, John C. Klensin, John C. Mallery, John Cowan, John Kemp, John Panzer, John Schneider, John Stracke, John Sullivan, Jonas Sicking, Jonathan A. Rees, Jonathan Billington, Jonathan Moore, Jonathan Silvera, Jordi Ros, Joris Dobbelsteen, Josh Cohen, Julien Pierre, Jungshik Shin, Justin Chapweske, Justin Erenkrantz, Justin James, Kalvinder Singh, Karl Dubost, Kathleen Moriarty, Keith Hoffman, Keith Moore, Ken Murchison, Koen Holtman, Konstantin Voronkov, Kris Zyp, Leif Hedstrom, Lionel Morand, Lisa Dusseault, Maciej Stachowiak, Manu Sporny, Marc Schneider, Marc Slemko, Mark Baker, Mark Pauley, Mark Watson, Markus Isomaki, Markus Lanthaler, Martin J. Duerst, Martin Musatov, Martin Nilsson, Martin Thomson, Matt Lynch, Matthew Cox, Matthew Kerwin, Max Clark, Menachem Dodge, Meral Shirazipour, Michael Burrows, Michael Hausenblas, Michael Scharf, Michael Sweet, Michael Tuexen, Michael Welzl, Mike Amundsen, Mike Belshe, Mike Bishop, Mike Kelly, Mike Schinkel, Miles Sabin, Murray S. Kucherawy, Mykyta Yevstifeyev, Nathan Rixham, Nicholas Shanks, Nico Williams, Nicolas Alvarez, Nicolas Mailhot, Noah Slater, Osama Mazahir, Pablo Castro, Pat Hayes, Patrick R. McManus, Paul E. Jones, Paul Hoffman, Paul Marquess, Pete Resnick, Peter Lepeska, Peter Occil, Peter Saint-Andre, Peter Watkins, Phil Archer, Phil Hunt, Philippe Mougin, Phillip Hallam-Baker, Piotr Dobrogost, Poul-Henning Kamp, Preethi Natarajan, Rajeev Bector, Ray Polk, Reto Bachmann-Gmuer, Richard Barnes, Richard Cyganiak, Rob Trace, Robby Simpson, Robert Brewer, Robert Collins, Robert Mattson, Robert O'Callahan, Robert Olofsson, Robert Sayre, Robert Siemer, Robert de Wilde, Roberto Javier Godoy, Roberto Peon, Roland Zink, Ronny Widjaja, Ryan Hamilton, S. Mike Dierken, Salvatore Loreto, Sam Johnston, Sam Pullara, Sam Ruby, Saurabh Kulkarni, Scott Lawrence (who maintained the original issues list), Sean B. Palmer, Sean Turner, Sebastien Barnoud, Shane McCarron, Shigeki Ohtsu, Simon Yarde, Stefan Eissing, Stefan Tilkov, Stefanos Harhalakis, Stephane Bortzmeyer, Stephen Farrell, Stephen Kent, Stephen Ludin, Stuart Williams, Subbu Allamaraju, Subramanian Moonesamy, Susan Hares, Sylvain Hellegouarch, Tapan Divekar, Tatsuhiro Tsujikawa, Tatsuya Hayashi, Ted Hardie, Ted Lemon, Thomas Broyer, Thomas Fossati, Thomas Maslen, Thomas Nadeau, Thomas Nordin, Thomas Roessler, Tim Bray, Tim Morgan, Tim Olsen, Tom Zhou, Travis Snoozy, Tyler Close, Vincent Murphy, Wenbo Zhu, Werner Baumann, Wilbur Streett, Wilfredo Sanchez Vega, William A. Rowe Jr., William Chan, Willy Tarreau, Xiaoshu Wang, Yaron Goland, Yngve Nysaeter Pettersen, Yoav Nir, Yogesh Bang, Yuchung Cheng, Yutaka Oiwa, Yves Lafon (long-time member of the editor team), Zed A. Shaw, and Zhong Yu. ๐โจ
For acknowledgements from earlier revisions, see Section 16 of [RFC2616] ๐ง
11. References ๐
11.1. Normative References
These are the must-read docs ๐ Here they all are, exactly as written:
[RFC0793] Postel, J., "Transmission Control Protocol", STD 7,
RFC 793, September 1981.
[RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data
Format Specification version 3.3", RFC 1950, May 1996.
[RFC1951] Deutsch, P., "DEFLATE Compressed Data Format
Specification version 1.3", RFC 1951, May 1996.
[RFC1952] Deutsch, P., Gailly, J-L., Adler, M., Deutsch, L., and
G. Randers-Pehrson, "GZIP file format specification
version 4.3", RFC 1952, May 1996.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter,
"Uniform Resource Identifier (URI): Generic Syntax",
STD 66, RFC 3986, January 2005.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for
Syntax Specifications: ABNF", STD 68, RFC 5234,
January 2008.
[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
Transfer Protocol (HTTP/1.1): Semantics and Content",
RFC 7231, June 2014.
[RFC7232] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
Transfer Protocol (HTTP/1.1): Conditional Requests",
RFC 7232, June 2014.
[RFC7233] Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed.,
"Hypertext Transfer Protocol (HTTP/1.1): Range
Requests", RFC 7233, June 2014.
[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching",
RFC 7234, June 2014.
[RFC7235] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
Transfer Protocol (HTTP/1.1): Authentication",
RFC 7235, June 2014.
[USASCII] American National Standards Institute, "Coded Character
Set -- 7-bit American Standard Code for Information
Interchange", ANSI X3.4, 1986.
[Welch] Welch, T., "A Technique for High-Performance Data
Compression", IEEE Computer 17(6), June 1984.
11.2. Informative References ๐โจ
okay these are the bonus reads ๐ helpful background, not the stuff you need to implement ๐ bestie, here they all are:
[BCP115] Hansen, T., Hardie, T., and L. Masinter, "Guidelines and Registration Procedures for New URI Schemes", BCP 115, RFC 4395, February 2006.
[BCP13] Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, January 2013.
[BCP90] Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.
[Georgiev] Georgiev, M., Iyengar, S., Jana, S., Anubhai, R., Boneh, D., and V. Shmatikov, "The Most Dangerous Code in the World: Validating SSL Certificates in Non-browser Software", In Proceedings of the 2012 ACM Conference on Computer and Communications Security (CCS '12), pp. 38-49, October 2012, <http://doi.acm.org/10.1145/2382196.2382204>.
[ISO-8859-1] International Organization for Standardization, "Information technology -- 8-bit single-byte coded graphic character sets -- Part 1: Latin alphabet No. 1", ISO/IEC 8859-1:1998, 1998.
[Klein] Klein, A., "Divide and Conquer - HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics", March 2004, <http://packetstormsecurity.com/papers/general/whitepaper_httpresponse.pdf>.
[Kri2001] Kristol, D., "HTTP Cookies: Standards, Privacy, and Politics", ACM Transactions on Internet Technology 1(2), November 2001, <http://arxiv.org/abs/cs.SE/0105018>.
[Linhart] Linhart, C., Klein, A., Heled, R., and S. Orrin, "HTTP Request Smuggling", June 2005, <http://www.watchfire.com/news/whitepapers.aspx>.
[RFC1919] Chatel, M., "Classical versus Transparent IP Proxies", RFC 1919, March 1996.
[RFC1945] Berners-Lee, T., Fielding, R., and H. Nielsen, "Hypertext Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
[RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
[RFC2047] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, November 1996.
[RFC2068] Fielding, R., Gettys, J., Mogul, J., Nielsen, H., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2068, January 1997.
[RFC2145] Mogul, J., Fielding, R., Gettys, J., and H. Nielsen, "Use and Interpretation of HTTP Version Numbers", RFC 2145, May 1997.
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[RFC2817] Khare, R. and S. Lawrence, "Upgrading to TLS Within HTTP/1.1", RFC 2817, May 2000.
[RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
[RFC3040] Cooper, I., Melve, I., and G. Tomlinson, "Internet Web Replication and Caching Taxonomy", RFC 3040, January 2001.
[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, March 2005.
[RFC4559] Jaganathan, K., Zhu, L., and J. Brezak, "SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows", RFC 4559, June 2006.
[RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.
[RFC5322] Resnick, P., "Internet Message Format", RFC 5322, October 2008.
[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265, April 2011.
[RFC6585] Nottingham, M. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, April 2012.
Appendix A. HTTP Version History ๐ฐ๏ธ๐
HTTP has been around since 1990 ๐ธ the first version, later called HTTP/0.9, was a simple protocol for moving hypertext across the Internet. It only had one request method (GET) and no metadata at all ๐ฆ
HTTP/1.0, as defined by [RFC1945], leveled up ๐ฅ it added a bunch of request methods and MIME-like messaging, so metadata could finally be transferred and modifiers could be placed on the request/response semantics โจ but ngl, HTTP/1.0 didn't really think through hierarchical proxies, caching, the need for persistent connections, or name-based virtual hosts ๐ on top of that, a ton of incompletely implemented apps were calling themselves "HTTP/1.0", so two communicating apps needed a protocol version change to figure out each other's true capabilities ๐
HTTP/1.1 stays compatible with HTTP/1.0 by adding stricter requirements that make implementations reliable ๐ซถ it only adds features that a HTTP/1.0 recipient can safely ignore, or that get sent only when the other party is advertising conformance with HTTP/1.1 ๐
HTTP/1.1 was designed to make supporting older versions easy, bestie ๐ง a general-purpose HTTP/1.1 server ought to understand any valid HTTP/1.0 request, and respond with an HTTP/1.1 message that only uses features HTTP/1.0 clients understand (or can safely ignore) โจ and an HTTP/1.1 client can be expected to understand any valid HTTP/1.0 response ๐
Since HTTP/0.9 didn't support header fields in a request, there's no way for it to do name-based virtual hosts (picking a resource by looking at the Host header field) ๐ญ any server that does name-based virtual hosts ought to disable HTTP/0.9 support. Most requests that look like HTTP/0.9 are actually badly built HTTP/1.x requests, caused by a client not properly encoding the request-target ๐
A.1. Changes from HTTP/1.0 ๐
This section sums up the major differences between HTTP/1.0 and HTTP/1.1 ๐
A.1.1. Multihomed Web Servers ๐
The requirements that clients and servers support the Host header field (Section 5.4), report an error if it's missing from an HTTP/1.1 request, and accept absolute URIs (Section 5.3) are among the most important changes HTTP/1.1 brought in ๐ฅ
older HTTP/1.0 clients assumed one IP address per server ๐ฅบ there wasn't any other established way to tell which server a request was meant for besides the IP address it was sent to. The Host header field was introduced during HTTP/1.1 development, and even though most HTTP/1.0 browsers implemented it quickly, extra requirements were placed on all HTTP/1.1 requests so it would be fully adopted ๐
at the time of writing, most HTTP-based services depend on the Host header field to target requests, iconic โจ
A.1.2. Keep-Alive Connections ๐ฆ
in HTTP/1.0, the client sets up each connection before the request, and the server closes it after sending the response ๐ซ some implementations did the explicitly negotiated ("Keep-Alive") version of persistent connections described in Section 19.7.1 of [RFC2068] ๐
some clients and servers might want to stay compatible with those older approaches by negotiating for them with a Connection: keep-alive request header field ๐ but some experimental HTTP/1.0 persistent connection implementations are faulty ๐ฌ for example, if an HTTP/1.0 proxy server doesn't understand Connection, it'll wrongly forward that header field to the next inbound server, and that results in a hung connection ๐
one attempted fix was the Proxy-Connection header field, aimed right at proxies ๐ in practice that didn't work either, because proxies are often deployed in multiple layers, which brings back the exact same problem ๐ฉ
so clients are encouraged not to send the Proxy-Connection header field in any requests ๐ซถ
clients are also encouraged to think carefully before using Connection: keep-alive in requests ๐ง it can enable persistent connections with HTTP/1.0 servers, but clients using it will need to monitor the connection for "hung" requests (which indicate the client ought to stop sending the header field), and this mechanism ought not be used by clients at all when a proxy is being used ๐ซ
A.1.3. Introduction of Transfer-Encoding ๐
HTTP/1.1 introduces the Transfer-Encoding header field (Section 3.3.1) โจ transfer codings need to be decoded before an HTTP message gets forwarded over a MIME-compliant protocol ๐
A.2. Changes from RFC 2616 ๐
Okay bestie, here's the tea on everything that changed from RFC 2616 ๐ โจ HTTP's approach to error handling got explained properly (Section 2.5) ๐ง
The HTTP-version ABNF production is now case-sensitive, and version numbers are restricted to single digits, because implementations are known to handle multi-digit version numbers incorrectly ๐ (Section 2.6)
Userinfo (that's username and password) is now disallowed in HTTP and HTTPS URIs, because sending it over the wire is a security issue ๐ญ (Section 2.7.1)
The HTTPS URI scheme is now defined by this spec. It used to be defined in Section 2.4 of [RFC2818]. It also implies end-to-end security ๐ (Section 2.7.2)
HTTP messages can be buffered by implementations, and often are ๐ Even though it's sometimes available as a stream, HTTP is fundamentally a message-oriented protocol. Minimum supported sizes for various protocol elements have been suggested to improve interoperability ๐ (Section 3)
Invalid whitespace around field-names is now required to be rejected, because accepting it is a security vulnerability ๐จ The ABNF productions that define header fields now only list the field value ๐ (Section 3.2)
The rules about implicit linear whitespace between certain grammar productions have been removed. Now whitespace is only allowed where it's specifically defined in the ABNF โจ (Section 3.2.3)
Header fields that span multiple lines ("line folding") are deprecated, so it's giving "no longer the move" ๐ โโ๏ธ (Section 3.2.4)
The NUL octet is no longer allowed in comment and quoted-string text, and the handling of backslash-escaping in them has been clarified ๐ฆ The quoted-pair rule no longer allows escaping control characters other than HTAB. Non-US-ASCII content in header fields and the reason phrase has been obsoleted and made opaque (the TEXT rule was removed) ๐ (Section 3.2.6)
Bogus Content-Length header fields are now required to be handled as errors by recipients ๐ (Section 3.3.2)
The algorithm for determining the message body length has been clarified so that it indicates all of the special cases (for example, the ones driven by methods or status codes) that affect it. It also says that new protocol elements cannot define such special cases ๐ฅ CONNECT is a new special case in determining message body length ๐ซถ "multipart/byteranges" is no longer a way of determining message body length detection, so bye bye ๐ (Section 3.3.3)
The "identity" transfer coding token has been removed ๐ฅ (Sections 3.3 and 4)
Chunk length does not include the count of the octets in the chunk header and trailer. Line folding in chunk extensions is disallowed, and that's a hard no ๐ โโ๏ธ (Section 4.1)
The meaning of the "deflate" content coding has been clarified ๐ธ (Section 4.2.2)
The segment + query components of RFC 3986 are now used to define the request-target, instead of abs_path from RFC 1808. The asterisk-form of the request-target is only allowed with the OPTIONS method ๐ (Section 5.3)
The term "Effective Request URI" has been introduced ๐ฏ (Section 5.5)
Gateways do not need to generate Via header fields anymore. Freedom ๐ฆ (Section 5.7.1)
Exactly when "close" connection options have to be sent has been clarified. Also, "hop-by-hop" header fields are required to appear in the Connection header field. Just because they're defined as hop-by-hop in this specification doesn't exempt them, so no getting out of it bestie ๐ (Section 6.1)
The limit of two connections per server has been removed ๐ An idempotent sequence of requests is no longer required to be retried. The requirement to retry requests under certain circumstances, when the server prematurely closes the connection, has been removed. Some extraneous requirements about when servers are allowed to close connections prematurely have also been removed ๐งผ (Section 6.3)
The semantics of the Upgrade header field are now defined in responses other than 101. This was incorporated from [RFC2817]. The ordering in the field value is now significant, so order matters, periodt ๐ (Section 6.7)
Empty list elements in list productions (for example, a list header field containing ", ,") have been deprecated ๐ซ (Section 7)
Registration of Transfer Codings now requires IETF Review (Section 8.4). This specification also defines the Upgrade Token Registry, which was previously defined in Section 7.2 of [RFC2817] (Section 8.6) ๐๏ธ
The expectation to support HTTP/0.9 requests has been removed ๐ (Appendix A)
Issues with the Keep-Alive and Proxy-Connection header fields in requests are pointed out, and use of the latter is discouraged altogether ๐ (Appendix A.1.2)
Appendix B. Collected ABNF โจ
Okay, last but not least, here's the whole ABNF collection in one spot so you can find everything at a glance ๐ง๐
BWS = OWS
Connection = *( "," OWS ) connection-option *( OWS "," [ OWS
connection-option ] )
Content-Length = 1*DIGIT
HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body
]
HTTP-name = %x48.54.54.50 ; HTTP
HTTP-version = HTTP-name "/" DIGIT "." DIGIT
Host = uri-host [ ":" port ]
OWS = *( SP / HTAB )
RWS = 1*( SP / HTAB )
TE = [ ( "," / t-codings ) *( OWS "," [ OWS t-codings ] ) ]
Trailer = *( "," OWS ) field-name *( OWS "," [ OWS field-name ] )
Transfer-Encoding = *( "," OWS ) transfer-coding *( OWS "," [ OWS
transfer-coding ] )
URI-reference = <URI-reference, see [RFC3986], Section 4.1>
Upgrade = *( "," OWS ) protocol *( OWS "," [ OWS protocol ] )
Via = *( "," OWS ) ( received-protocol RWS received-by [ RWS comment
] ) *( OWS "," [ OWS ( received-protocol RWS received-by [ RWS
comment ] ) ] )
absolute-URI = <absolute-URI, see [RFC3986], Section 4.3>
absolute-form = absolute-URI
absolute-path = 1*( "/" segment )
asterisk-form = "*"
authority = <authority, see [RFC3986], Section 3.2>
authority-form = authority
chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
chunk-data = 1*OCTET
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string
chunk-size = 1*HEXDIG
chunked-body = *chunk last-chunk trailer-part CRLF
comment = "(" *( ctext / quoted-pair / comment ) ")"
connection-option = token
ctext = HTAB / SP / %x21-27 ; '!'-'''
/ %x2A-5B ; '*'-'['
/ %x5D-7E ; ']'-'~'
/ obs-text
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-name = token
field-value = *( field-content / obs-fold )
field-vchar = VCHAR / obs-text
fragment = <fragment, see [RFC3986], Section 3.5>
header-field = field-name ":" OWS field-value OWS
http-URI = "http://" authority path-abempty [ "?" query ] [ "#"
fragment ]
https-URI = "https://" authority path-abempty [ "?" query ] [ "#"
fragment ]
last-chunk = 1*"0" [ chunk-ext ] CRLF
message-body = *OCTET
method = token
obs-fold = CRLF 1*( SP / HTAB )
obs-text = %x80-FF
origin-form = absolute-path [ "?" query ]
partial-URI = relative-part [ "?" query ]
path-abempty = <path-abempty, see [RFC3986], Section 3.3>
port = <port, see [RFC3986], Section 3.2.3>
protocol = protocol-name [ "/" protocol-version ]
protocol-name = token
protocol-version = token
pseudonym = token
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'['
/ %x5D-7E ; ']'-'~'
/ obs-text
query = <query, see [RFC3986], Section 3.4>
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
rank = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )
reason-phrase = *( HTAB / SP / VCHAR / obs-text )
received-by = ( uri-host [ ":" port ] ) / pseudonym
received-protocol = [ protocol-name "/" ] protocol-version
relative-part = <relative-part, see [RFC3986], Section 4.2>
request-line = method SP request-target SP HTTP-version CRLF
request-target = origin-form / absolute-form / authority-form /
asterisk-form
scheme = <scheme, see [RFC3986], Section 3.1>
segment = <segment, see [RFC3986], Section 3.3>
start-line = request-line / status-line
status-code = 3DIGIT
status-line = HTTP-version SP status-code SP reason-phrase CRLF
t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
t-ranking = OWS ";" OWS "q=" rank
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
"^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
token = 1*tchar
trailer-part = *( header-field CRLF )
transfer-coding = "chunked" / "compress" / "deflate" / "gzip" /
transfer-extension
transfer-extension = token *( OWS ";" OWS transfer-parameter )
transfer-parameter = token BWS "=" BWS ( token / quoted-string )
uri-host = <host, see [RFC3986], Section 3.2.2>
Index ๐โจ
okay bestie, this is the cheat sheet! ๐ง every term, header, and grammar rule with the pages where it shows up, so you can jump straight to the good stuff. no cap, it's giving organized ๐
A
absolute-form (of request-target) 42
accelerator 10
application/http Media Type 63
asterisk-form (of request-target) 43
authoritative response 67
authority-form (of request-target) 42-43
B
browser 7
C
cache 11
cacheable 12
captive portal 11
chunked (Coding Format) 28, 32, 36
client 7
close 51, 56
compress (Coding Format) 38
connection 7
Connection header field 51, 56
Content-Length header field 30
D
deflate (Coding Format) 38
Delimiters 27
downstream 10
E
effective request URI 45
G
gateway 10
Grammar
absolute-form 42
absolute-path 16
absolute-URI 16
ALPHA 6
asterisk-form 41, 43
authority 16
authority-form 42-43
BWS 25
chunk 36
chunk-data 36
chunk-ext 36
chunk-ext-name 36
chunk-ext-val 36
chunk-size 36
chunked-body 36
comment 27
Connection 51
connection-option 51
Content-Length 30
CR 6
CRLF 6
ctext 27
CTL 6
DIGIT 6
DQUOTE 6
field-content 23
field-name 23, 40
field-value 23
field-vchar 23
fragment 16
header-field 23, 37
HEXDIG 6
Host 44
HTAB 6
HTTP-message 19
HTTP-name 14
http-URI 17
HTTP-version 14
https-URI 18
last-chunk 36
LF 6
message-body 28
method 21
obs-fold 23
obs-text 27
OCTET 6
origin-form 42
OWS 25
partial-URI 16
port 16
protocol-name 47
protocol-version 47
pseudonym 47
qdtext 27
query 16
quoted-pair 27
quoted-string 27
rank 39
reason-phrase 22
received-by 47
received-protocol 47
request-line 21
request-target 41
RWS 25
scheme 16
segment 16
SP 6
start-line 21
status-code 22
status-line 22
t-codings 39
t-ranking 39
tchar 27
TE 39
token 27
Trailer 40
trailer-part 37
transfer-coding 35
Transfer-Encoding 28
transfer-extension 35
transfer-parameter 35
Upgrade 57
uri-host 16
URI-reference 16
VCHAR 6
Via 47
gzip (Coding Format) 39
H
header field 19
header section 19
headers 19
Host header field 44
http URI scheme 17
https URI scheme 17
I
inbound 9
interception proxy 11
intermediary 9
M
Media Type
application/http 63
message/http 62
message 7
message/http Media Type 62
method 21
N
non-transforming proxy 49
O
origin server 7
origin-form (of request-target) 42
outbound 10
P
phishing 67
proxy 10
R
recipient 7
request 7
request-target 21
resource 16
response 7
reverse proxy 10
S
sender 7
server 7
spider 7
T
target resource 40
target URI 40
TE header field 39
Trailer header field 40
Transfer-Encoding header field 28
transforming proxy 49
transparent proxy 11
tunnel 10
U
Upgrade header field 57
upstream 9
URI scheme
http 17
https 17
user agent 7
V
Via header field 47
Authors' Addresses ๐๐
and last but not least, the people who wrote this whole thing! ๐ซถ here's who to thank (or message) about it ๐
Roy T. Fielding (editor)
Adobe Systems Incorporated
345 Park Ave
San Jose, CA 95110
USA
EMail: fielding@gbiv.com
URI: http://roy.gbiv.com/
Julian F. Reschke (editor)
greenbytes GmbH
Hafenweg 16
Muenster, NW 48155
Germany
EMail: julian.reschke@greenbytes.de
URI: http://greenbytes.de/tech/webdav/
that's the whole spec, bestie!! ๐โจ we really did it ๐ญ๐
๐ฆ where this page comes from
- ietf: rfc7230 2014-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms