RFC 2068

Hypertext Transfer Protocol -- HTTP/1.1

๐Ÿ“… published January 1997, from ietf

Part 1 of 33 ๐ŸŽ€

Title Block โœจ

Hypertext Transfer Protocol -- HTTP/1.1 ๐Ÿ’–

okay so this is RFC 2068 and it's giving standards-track royalty ๐Ÿ‘‘. It was written by R. Fielding (UC Irvine), J. Gettys, J. Mogul (DEC), H. Frystyk, and T. Berners-Lee (MIT/LCS), all for the Network Working Group, and it's dated January 1997. Its category is Standards Track. The original doesn't list anything it obsoletes or updates, so there's nothing to report there ๐Ÿซถ.


Status of this Memo ๐ŸŒธ

bestie, this one's basically a permission slip. It's an Internet standards track protocol for the Internet community, and the authors are literally asking everyone to discuss it and send suggestions for improvements ๐Ÿ’…. If you want the current standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š. And the memo can be distributed freely, no cap ๐Ÿฆ‹.

Abstract ๐Ÿงš

okay so HTTP is an application-level protocol for distributed, collaborative, hypermedia information systems ๐ŸŒˆ. It's generic, stateless, and object-oriented, and you can stretch it to handle other jobs like name servers and distributed object management systems just by extending its request methods ๐Ÿ”ฅ. A big highlight is the typing and negotiation of data representation, which means you can build systems without tying them to whatever data is moving through them โœจ.

HTTP has been powering the World-Wide Web global information initiative since 1990 ๐Ÿ’œ. This specification defines the version called "HTTP/1.1" ๐Ÿ’–.


Table of Contents ๐ŸŽ€

   1 Introduction.............................................7
    1.1 Purpose ..............................................7
    1.2 Requirements .........................................7
    1.3 Terminology ..........................................8
    1.4 Overall Operation ...................................11
   2 Notational Conventions and Generic Grammar..............13
    2.1 Augmented BNF .......................................13
    2.2 Basic Rules .........................................15
   3 Protocol Parameters.....................................17
    3.1 HTTP Version ........................................17
    3.2 Uniform Resource Identifiers ........................18
     3.2.1 General Syntax ...................................18
     3.2.2 http URL .........................................19
     3.2.3 URI Comparison ...................................20
    3.3 Date/Time Formats ...................................21
     3.3.1 Full Date ........................................21
     3.3.2 Delta Seconds ....................................22
    3.4 Character Sets ......................................22
    3.5 Content Codings .....................................23
    3.6 Transfer Codings ....................................24
    3.7 Media Types .........................................25
     3.7.1 Canonicalization and Text Defaults ...............26
     3.7.2 Multipart Types ..................................27
    3.8 Product Tokens ......................................28
    3.9 Quality Values ......................................28
    3.10 Language Tags ......................................28
    3.11 Entity Tags ........................................29
    3.12 Range Units ........................................30
   4 HTTP Message............................................30
    4.1 Message Types .......................................30
    4.2 Message Headers .....................................31
    4.3 Message Body ........................................32
    4.4 Message Length ......................................32
    4.5 General Header Fields ...............................34
   5 Request.................................................34
    5.1 Request-Line ........................................34
     5.1.1 Method ...........................................35
     5.1.2 Request-URI ......................................35
    5.2 The Resource Identified by a Request ................37
    5.3 Request Header Fields ...............................37
   6 Response................................................38
    6.1 Status-Line .........................................38
     6.1.1 Status Code and Reason Phrase ....................39
    6.2 Response Header Fields ..............................41
   7 Entity..................................................41
    7.1 Entity Header Fields ................................41
    7.2 Entity Body .........................................42
     7.2.1 Type .............................................42
     7.2.2 Length ...........................................43
   8 Connections.............................................43
    8.1 Persistent Connections ..............................43
     8.1.1 Purpose ..........................................43
     8.1.2 Overall Operation ................................44
     8.1.3 Proxy Servers ....................................45
     8.1.4 Practical Considerations .........................45
    8.2 Message Transmission Requirements ...................46
   9 Method Definitions......................................48
    9.1 Safe and Idempotent Methods .........................48

1. Introduction โœจ

1.1 Purpose

Okay so, HTTP is an application-level protocol for distributed, collaborative, hypermedia information systems ๐ŸŒธ It's been powering the World-Wide Web since 1990! The first version, HTTP/0.9, was a super simple protocol for raw data transfer across the Internet ๐Ÿฆ‹ Then HTTP/1.0, defined in RFC 1945 [6], level-upped things by letting messages look like MIME-like messages, with metainformation about the data being transferred and modifiers on the request/response semantics โœจ

But ngl, HTTP/1.0 didn't fully think through hierarchical proxies, caching, the need for persistent connections, and virtual hosts ๐Ÿ’€ On top of that, so many half-finished apps were calling themselves "HTTP/1.0" that a protocol version change was needed so two communicating apps could figure out each other's true capabilities ๐Ÿ™ˆ

This spec defines the protocol called "HTTP/1.1" ๐Ÿ’… It has more stringent requirements than HTTP/1.0 so its features actually get implemented reliably. Main character energy, honestly ๐Ÿ‘‘

Practical information systems need more than simple retrieval, like search, front-end update, and annotation. HTTP allows an open-ended set of methods that indicate the purpose of a request ๐Ÿงš It builds on the discipline of reference provided by the Uniform Resource Identifier (URI) [3][20], as a location (URL) [4] or name (URN) , for indicating the resource a method is applied to. Messages are passed in a format similar to Internet mail, as defined by the Multipurpose Internet Mail Extensions (MIME) ๐Ÿ“ฌ

HTTP is also used as a generic protocol for communication between user agents and proxies/gateways to other Internet systems, including those supported by the SMTP [16], NNTP [13], FTP [18], Gopher [2], and WAIS [10] protocols. So HTTP gives basic hypermedia access to resources from all kinds of diverse apps ๐ŸŒˆ


1.2 Requirements

Okay, this part is important, so listen up ๐ŸŽ€ This specification uses the same words as RFC 1123 [8] to define how significant each requirement is. Here they are:

MUST This word or the adjective "required" means that the item is an absolute requirement of the specification. No exceptions, bestie ๐Ÿšซ

SHOULD This word or the adjective "recommended" means there may be valid reasons in particular circumstances to ignore this item, but the full implications should be understood and the case carefully weighed before choosing a different course ๐Ÿค”

MAY This word or the adjective "optional" means this item is truly optional. One vendor may include the item because a particular marketplace requires it or because it enhances the product, for example. Another vendor may omit the same item, and that's valid too ๐Ÿ“

An implementation is not compliant if it fails to satisfy one or more of the MUST requirements for the protocols it implements. An implementation that satisfies all the MUST and all the SHOULD requirements for its protocols is said to be "unconditionally compliant" โœจ One that satisfies all the MUST requirements but not all the SHOULD requirements for its protocols is said to be "conditionally compliant." Both are valid, but one is clearly the flex ๐Ÿ’…


1.3 Terminology

This specification uses a bunch of terms for the roles played by participants in, and objects of, the HTTP communication. Let's go through them ๐Ÿ“–

connection A transport layer virtual circuit established between two programs for the purpose of communication ๐Ÿ”Œ

message The basic unit of HTTP communication. It's a structured sequence of octets matching the syntax defined in section 4 and transmitted via the connection ๐Ÿ“ฆ

request An HTTP request message, as defined in section 5 ๐Ÿ™‹โ€โ™€๏ธ

response An HTTP response message, as defined in section 6 ๐Ÿ’Œ

resource A network data object or service that can be identified by a URI, as defined in section 3.2. Resources may be available in multiple representations (e.g. multiple languages, data formats, size, resolutions) or vary in other ways ๐ŸŒธ

entity The information transferred as the payload of a request or response. An entity consists of metainformation in the form of entity-header fields and content in the form of an entity-body, as described in section 7 ๐ŸŽ

representation An entity included with a response that is subject to content negotiation, as described in section 12. There may exist multiple representations associated with a particular response status ๐Ÿชž

content negotiation The mechanism for selecting the appropriate representation when servicing a request, as described in section 12. The representation of entities in any response can be negotiated, including error responses. Yes, even the errors ๐Ÿ˜ญ

variant A resource may have one, or more than one, representation(s) associated with it at any given instant. Each of these representations is termed a variant.' Use of the term variant' does not necessarily imply that the resource is subject to content negotiation ๐Ÿฆ‹

client A program that establishes connections for the purpose of sending requests ๐Ÿ“ค

user agent The client which initiates a request. These are often browsers, editors, spiders (web-traversing robots), or other end user tools ๐Ÿ•ธ๏ธ

server An application program that accepts connections in order to service requests by sending back responses. Any given program may be capable of being both a client and a server. Our use of these terms refers only to the role the program is performing for a particular connection, rather than to the program's capabilities in general. Likewise, any server may act as an origin server, proxy, gateway, or tunnel, switching behavior based on the nature of each request ๐Ÿ”„

origin server The server on which a given resource resides or is to be created ๐Ÿ 

proxy An intermediary program which acts as both a server and a client for the purpose of making requests on behalf of other clients. Requests are serviced internally or by passing them on, with possible translation, to other servers. A proxy must implement both the client and server requirements of this specification ๐Ÿงƒ

gateway A server which acts as an intermediary for some other server. Unlike a proxy, a gateway receives requests as if it were the origin server for the requested resource. The requesting client may not even be aware it's talking to a gateway ๐Ÿ•ต๏ธโ€โ™€๏ธ

tunnel An intermediary program which is acting as a blind relay between two connections. Once active, a tunnel is not considered a party to the HTTP communication, though the tunnel may have been initiated by an HTTP request. The tunnel ceases to exist when both ends of the relayed connections are closed ๐Ÿš‡

cache A program's local store of response messages and the subsystem that controls its message storage, retrieval, and deletion. A cache stores cachable responses in order to reduce response time and network bandwidth consumption on future, equivalent requests. Any client or server may include a cache, though a cache cannot be used by a server that is acting as a tunnel ๐Ÿ—ƒ๏ธ

cachable A response is cachable if a cache is allowed to store a copy of the response message for use in answering subsequent requests. The rules for determining the cachability of HTTP responses are defined in section 13. Even if a resource is cachable, there may be additional constraints on whether a cache can use the cached copy for a particular request ๐Ÿง 

first-hand A response is first-hand if it comes directly and without unnecessary delay from the origin server, perhaps via one or more proxies. A response is also first-hand if its validity has just been checked directly with the origin server ๐Ÿซถ

explicit expiration time The time at which the origin server intends that an entity should no longer be returned by a cache without further validation โฐ

heuristic expiration time An expiration time assigned by a cache when no explicit expiration time is available ๐Ÿ”ฎ

age The age of a response is the time since it was sent by, or successfully validated with, the origin server ๐Ÿ•ฐ๏ธ

freshness lifetime The length of time between the generation of a response and its expiration time โณ

fresh A response is fresh if its age has not yet exceeded its freshness lifetime. Fresh and fabulous โœจ

stale A response is stale if its age has passed its freshness lifetime. Oof, it's giving expired ๐Ÿฅ€

semantically transparent A cache behaves in a "semantically transparent" manner, with respect to a particular response, when its use affects neither the requesting client nor the origin server, except to improve performance. When a cache is semantically transparent, the client receives exactly the same response (except for hop-by-hop headers) that it would have received had its request been handled directly by the origin server. Invisible helper energy ๐Ÿงšโ€โ™€๏ธ

validator A protocol element (e.g., an entity tag or a Last-Modified time) that is used to find out whether a cache entry is an equivalent copy of an entity ๐Ÿ”

1.4 Overall Operation

HTTP is a request/response protocol, so the whole thing is basically a conversation ๐Ÿ’ฌ. A client sends a request to the server, and that request has a request method, a URI, and a protocol version, followed by a MIME-like message with request modifiers, client information, and possible body content. Everything travels over a connection with a server. The server replies with a status line that includes the message's protocol version and a success or error code, followed by a MIME-like message with server information, entity metainformation, and possible entity-body content. The relationship between HTTP and MIME is covered in appendix 19.4 ๐ŸŽ€

Most HTTP communication starts with a user agent that wants a request applied to a resource on some origin server. In the simplest case, that happens over one single connection (v) between the user agent (UA) and the origin server (O). Very clean โœจ

          request chain ------------------------>
       UA -------------------v------------------- O
          <----------------------- response chain

Things get more interesting when one or more intermediaries show up in the request/response chain ๐Ÿ‘€ There are three common kinds. A proxy is a forwarding agent. It receives requests for a URI in its absolute form, rewrites all or part of the message, and forwards the reformatted request toward the server the URI points to. A gateway is a receiving agent that acts as a layer above some other server(s) and, if necessary, translates requests into the underlying server's protocol. A tunnel is a relay point between two connections that doesn't change the messages at all. Tunnels are used when communication needs to pass through an intermediary, like a firewall, even when that intermediary can't understand what the messages actually say ๐Ÿ”

          request chain -------------------------------------->
       UA -----v----- A -----v----- B -----v----- C -----v----- O
          <------------------------------------- response chain

The figure above shows three intermediaries (A, B, and C) between the user agent and the origin server. A request or response that travels the whole chain goes through four separate connections, and this distinction matters a lot ๐Ÿง  Some HTTP communication options might only apply to the connection with the nearest, non-tunnel neighbor. Others apply only to the end-points of the chain, and some apply to every connection along the chain. Also, even though the diagram looks linear, each participant can be juggling multiple simultaneous communications. For example, B might be getting requests from lots of clients other than A, and/or forwarding requests to servers other than C, at the very same time it's handling A's request. Multitasking queen ๐Ÿ‘‘

Any party to the communication that isn't acting as a tunnel may use an internal cache to handle requests. A cache makes the request/response chain shorter if one of the participants along the chain has a cached response that applies to the request. Here's what that looks like if B has a cached copy of an earlier response from O (which came via C) for a request that neither UA nor A has cached:

          request chain ---------->
       UA -----v----- A -----v----- B - - - - - - C - - - - - - O
          <--------- response chain

Not every response is usefully cachable, and some requests come with modifiers that put special requirements on cache behavior. The HTTP requirements for cache behavior and cachable responses are defined in section 13 ๐Ÿ“ฆ

Honestly, there are a wild variety of cache and proxy architectures and configurations being experimented with or deployed across the World Wide Web right now ๐ŸŒ Some are national hierarchies of proxy caches that save transoceanic bandwidth. Some broadcast or multicast cache entries. Some organizations distribute subsets of cached data on CD-ROM, and so on. HTTP systems run in corporate intranets over high-bandwidth links, and they're also used from PDAs with low-power radio links and intermittent connectivity. The goal of HTTP/1.1 is to support that huge diversity of already-deployed configurations while adding protocol constructs for people building web applications who need high reliability and, failing that, at least reliable indications of failure ๐Ÿ’–

HTTP communication usually happens over TCP/IP connections. The default port is TCP 80, but other ports can be used too ๐Ÿ”Œ None of that stops HTTP from being implemented on top of any other protocol on the Internet, or on other networks. HTTP only presumes a reliable transport, so any protocol that provides those guarantees can be used. How the HTTP/1.1 request and response structures map onto the transport data units of that protocol is outside the scope of this specification, so that's a whole other story ๐Ÿซถ

In HTTP/1.0, most implementations used a new connection for each request/response exchange. In HTTP/1.1, a connection may be used for one or more request/response exchanges, although connections may be closed for a variety of reasons (see section 8.1). Glow-up era ๐Ÿฆ‹


2 Notational Conventions and Generic Grammar

2.1 Augmented BNF

Okay, so every mechanism in this document is described in both prose and an augmented Backus-Naur Form (BNF) that's similar to the one used by RFC 822 [9]. Implementers really do need to get comfy with this notation to understand the spec ๐Ÿ“ Here are the constructs it includes:

name = definition

The name of a rule is just the name itself (no enclosing < and >), and it's separated from its definition by the equal = character. Whitespace only matters in that indenting continuation lines shows a rule definition that spans more than one line. Certain basic rules are written in uppercase, like SP, LWS, HT, CRLF, DIGIT, ALPHA, and so on. Angle brackets get used inside definitions whenever their presence helps you tell which rule names are which ๐ŸŒธ

"literal"

Quotation marks wrap literal text. Unless stated otherwise, that text is case-insensitive ๐Ÿ’…

rule1 | rule2

Elements separated by a bar (|) are alternatives. For example, "yes | no" will accept yes or no โœจ

(rule1 rule2)

Elements inside parentheses are treated as a single element. So (elem (foo | bar) elem) allows the token sequences elem foo elem and elem bar elem ๐Ÿงฉ

*rule

The character * in front of an element means repetition. The full form is <n>*<m>element, which means at least <n> and at most <m> occurrences of the element. The default values are 0 and infinity, so *(element) allows any number, including zero. 1*element requires at least one, and 1*2element allows one or two ๐Ÿ”

[rule]

Square brackets enclose optional elements. [foo bar] is equivalent to *1(foo bar) ๐ŸŽˆ

N rule

This is specific repetition. <n>(element) is equivalent to <n>*<n>(element), meaning exactly <n> occurrences of the element. So 2DIGIT is a 2-digit number, and 3ALPHA is a string of three alphabetic characters ๐Ÿ”ข

#rule

The # construct is defined like *, but it's for defining lists of elements. The full form is <n>#<m>element, which means at least <n> and at most <m> elements, each separated by one or more commas (,) and optional linear whitespace (LWS). This makes normal lists super easy, since a rule like ( *LWS element *( *LWS "," *LWS element )) can be shown as 1#element. Wherever this construct is used, null elements are allowed, but they don't count toward the number of elements present. So (element), , (element) is permitted but only counts as two elements. That means that wherever at least one element is required, at least one non-null element must be present. The default values are 0 and infinity, so #element allows any number, including zero. 1#element requires at least one, and 1#2element allows one or two ๐Ÿ“‹

; comment

A semi-colon, set off some distance to the right of the rule text, starts a comment that continues to the end of the line. It's a simple way to include useful notes right alongside the specification ๐Ÿ’ฌ

implied *LWS

The grammar in this specification is word-based. Except where noted otherwise, linear whitespace (LWS) can be included between any two adjacent words (token or quoted-string), and between adjacent tokens and delimiters (tspecials), without changing how a field is interpreted. At least one delimiter (tspecials) must exist between any two tokens, because otherwise they'd be read as one single token. Don't skip the delimiter, bestie ๐Ÿšซ

2.2. Basic Rules

okay bestie, these are the building blocks everything else in the spec gets parsed out of, so pay attention ๐Ÿ’… the US-ASCII character set is defined by ANSI X3.4-1986 [21] ๐ŸŽ€

OCTET          = <any 8-bit sequence of data>
CHAR           = <any US-ASCII character (octets 0 - 127)>
UPALPHA        = <any US-ASCII uppercase letter "A".."Z">
LOALPHA        = <any US-ASCII lowercase letter "a".."z">
ALPHA          = UPALPHA | LOALPHA
DIGIT          = <any US-ASCII digit "0".."9">
CTL            = <any US-ASCII control character
                 (octets 0 - 31) and DEL (127)>
CR             = <US-ASCII CR, carriage return (13)>
LF             = <US-ASCII LF, linefeed (10)>
SP             = <US-ASCII SP, space (32)>
HT             = <US-ASCII HT, horizontal-tab (9)>
<">            = <US-ASCII double-quote mark (34)>

so HTTP/1.1 uses CR LF as the end-of-line marker for every protocol element โœจ the only exception is the entity-body (see appendix 19.3 for tolerant applications) ๐ŸŒธ the end-of-line marker inside an entity-body is decided by its media type, as described in section 3.7 ๐Ÿฆ‹

CRLF           = CR LF

headers can get folded onto multiple lines ๐Ÿงš as long as the continuation line starts with a space or a horizontal tab. all linear white space, folding included, works the same as SP ๐Ÿ’œ

LWS            = [CRLF] 1*( SP | HT )

the TEXT rule is only for descriptive field contents and values the message parser isn't supposed to interpret ๐Ÿ“ words of *TEXT can only use characters from character sets other than ISO 8859-1 [22] when they're encoded according to RFC 1522 [14] ๐Ÿ™ˆ

TEXT           = <any OCTET except CTLs,
                 but including LWS>

hex characters show up in a bunch of protocol elements ๐Ÿ”ฅ

HEX            = "A" | "B" | "C" | "D" | "E" | "F"
               | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT

lots of HTTP/1.1 header field values are words separated by LWS or special characters ๐ŸŒˆ these special characters MUST be in a quoted string to be used within a parameter value. no exceptions, periodt ๐Ÿ’…

token          = 1*<any CHAR except CTLs or tspecials>

tspecials      = "(" | ")" | "<" | ">" | "@"
               | "," | ";" | ":" | "\" | <">
               | "/" | "[" | "]" | "?" | "="
               | "{" | "}" | SP | HT

comments can live inside some HTTP header fields ๐Ÿ’– you just wrap the comment text in parentheses. comments are only allowed in fields that have "comment" in their field value definition ๐Ÿ‘‘ in all other fields, parentheses count as part of the field value ๐Ÿ˜ญ

comment        = "(" *( ctext | comment ) ")"
ctext          = <any TEXT excluding "(" and ")">

a string of text gets parsed as one single word if you quote it with double-quote marks โœจ

quoted-string  = ( <"> *(qdtext) <"> )

qdtext         = <any TEXT except <">>

the backslash ("") works as a single-character quoting mechanism, but only inside quoted-string and comment constructs ๐ŸŽ€

quoted-pair    = "\" CHAR

3. Protocol Parameters โœจ

3.1. HTTP Version

HTTP uses a "<major>.<minor>" numbering scheme to show which version of the protocol is in play ๐Ÿฆ‹ the versioning is there so the sender can say what format a message is in and how much further HTTP communication it can handle, not what features that communication gets you ๐Ÿ’… adding message components that don't change communication behavior, or that only add to extensible field values, does not bump the version number ๐ŸŒธ the <minor> number goes up when the protocol gets features that don't change the general message parsing algorithm but might add to message semantics and imply extra capabilities for the sender ๐Ÿงš the <major> number goes up when the format of a message within the protocol changes ๐Ÿ‘‘

the version of an HTTP message is shown by an HTTP-Version field in the first line of the message ๐Ÿ’œ

HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT

ok this part is so important ๐Ÿ˜ญ the major and minor numbers MUST be treated as separate integers, and each one can climb past a single digit. so HTTP/2.4 is a lower version than HTTP/2.13, which is lower than HTTP/12.3 ๐Ÿ”ฅ leading zeros MUST be ignored by recipients and MUST NOT be sent ๐Ÿ™ˆ

applications that send Request or Response messages, as this spec defines them, MUST include an HTTP-Version of "HTTP/1.1" ๐ŸŒˆ using that version number tells everyone the sending application is at least conditionally compliant with this spec ๐Ÿ’–

the HTTP version of an application is the highest HTTP version it's at least conditionally compliant with โœจ

Note: proxies and gateways need to be extra careful when forwarding messages in protocol versions that are different from their own ๐Ÿซถ since the protocol version tells everyone the sender's protocol capability, a proxy/gateway MUST never send a message with a version indicator greater than its actual version ๐Ÿ’€ if it gets a higher-version request, the proxy/gateway MUST either downgrade the request version, respond with an error, or switch to tunnel behavior ๐Ÿ˜ญ requests with a version lower than the proxy/gateway's own MAY be upgraded before being forwarded ๐Ÿฆ‹ and the proxy/gateway's response to that request MUST be in the same major version as the request ๐ŸŽ€
Note: converting between HTTP versions may involve changing header fields that are required or forbidden by the versions involved ๐ŸŒธ

3.2. Uniform Resource Identifiers

URIs have been called a lot of things over the years ๐Ÿ“ WWW addresses, Universal Document Identifiers, Universal Resource Identifiers, and finally the mashup of Uniform Resource Locators (URL) and Names (URN) ๐Ÿ’… as far as HTTP is concerned, a URI is just a formatted string that identifies a resource, whether that's by name, location, or some other characteristic ๐Ÿงš

3.2.1. General Syntax

URIs in HTTP can be written in absolute form or relative to some known base URI, depending on the context ๐Ÿฆ‹ the two forms are told apart by one thing: absolute URIs always begin with a scheme name followed by a colon ๐Ÿ‘‘

URI            = ( absoluteURI | relativeURI ) [ "#" fragment ]

absoluteURI    = scheme ":" *( uchar | reserved )

relativeURI    = net_path | abs_path | rel_path

net_path       = "//" net_loc [ abs_path ]
abs_path       = "/" rel_path
rel_path       = [ path ] [ ";" params ] [ "?" query ]

path           = fsegment *( "/" segment )
fsegment       = 1*pchar
segment        = *pchar

params         = param *( ";" param )
param          = *( pchar | "/" )
scheme         = 1*( ALPHA | DIGIT | "+" | "-" | "." )
net_loc        = *( pchar | ";" | "?" )

query          = *( uchar | reserved )
fragment       = *( uchar | reserved )

pchar          = uchar | ":" | "@" | "&" | "=" | "+"
uchar          = unreserved | escape
unreserved     = ALPHA | DIGIT | safe | extra | national

escape         = "%" HEX HEX
reserved       = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+"
extra          = "!" | "*" | "'" | "(" | ")" | ","
safe           = "$" | "-" | "_" | "."
unsafe         = CTL | SP | <"> | "#" | "%" | "<" | ">"
national       = <any OCTET excluding ALPHA, DIGIT,
                 reserved, extra, safe, and unsafe>

for the real, definitive URL syntax and semantics, check out RFC 1738 [4] and RFC 1808 [11] ๐ŸŒˆ the BNF above includes national characters that aren't allowed in valid URLs under RFC 1738 ๐Ÿ™ˆ that's because HTTP servers aren't limited in which unreserved characters can show up in the rel_path part of addresses, and HTTP proxies might get requests for URIs that RFC 1738 never defined ๐Ÿ’–

here's the length situation โœจ HTTP doesn't put any a priori limit on how long a URI can be ๐Ÿซถ servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET-based forms that could generate such URIs ๐Ÿ”ฅ a server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15) ๐Ÿ˜ญ

Note: servers should be careful about depending on URI lengths above 255 bytes, since some older client or proxy implementations may not properly support those lengths ๐Ÿ’€

3.2.2. http URL

the "http" scheme is how you locate network resources over the HTTP protocol ๐Ÿฆ‹ this section defines the scheme-specific syntax and semantics for http URLs ๐ŸŽ€

http_URL       = "http:" "//" host [ ":" port ] [ abs_path ]

host           = <A legal Internet host domain name
                  or IP address (in dotted-decimal form),
                  as defined by Section 2.1 of RFC 1123>

port           = *DIGIT

if the port is empty or not given, port 80 is assumed ๐Ÿ“ the identified resource lives at the server listening for TCP connections on that port of that host, and the Request-URI for the resource is abs_path ๐Ÿงš the use of IP addresses in URL's SHOULD be avoided whenever possible (see RFC 1900 [24]) ๐Ÿ’… and if abs_path isn't in the URL, it MUST be given as "/" when used as a Request-URI for a resource (section 5.1.2) ๐Ÿ‘‘

3.2.3. URI Comparison

when you're comparing two URIs to figure out if they match, a client SHOULD use a case-sensitive, octet-by-octet comparison of the entire URIs ๐Ÿ’œ but there are a few exceptions ๐ŸŒธ

  • a port that is empty or not given is equivalent to the default port for that URI;
  • comparisons of host names MUST be case-insensitive;
  • comparisons of scheme names MUST be case-insensitive;
  • an empty abs_path is equivalent to an abs_path of "/".

characters outside the "reserved" and "unsafe" sets (see section 3.2) are equivalent to their ""%" HEX HEX" encodings ๐Ÿฆ‹

for example, these three URIs are equivalent ๐Ÿซถ

http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html

3.3. Date/Time Formats

3.3.1 Full Date โœจ

Okay bestie, so HTTP apps have historically allowed three different formats for writing date/time stamps ๐Ÿ—“๏ธ, and it's giving chaos:

Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format

The first format is the preferred Internet standard ๐Ÿ‘‘. It's basically a fixed-length version of what RFC 1123 defines (and RFC 1123 is an update to RFC 822) ๐Ÿ’…. The second format is everywhere in the wild, but it's built on the obsolete RFC 850 [12] date format and it doesn't even have a four-digit year ๐Ÿ’€. HTTP/1.1 clients and servers that parse the date value MUST accept all three formats (for compatibility with HTTP/1.0), though they MUST only generate the RFC 1123 format for representing HTTP-date values in header fields. So be accepting when you read and strict when you send ๐Ÿซถ.

Note: Recipients of date values are encouraged to be robust in accepting date values that may have been sent by non-HTTP applications, as is sometimes the case when retrieving or posting messages via proxies/gateways to SMTP or NNTP.

All HTTP date/time stamps MUST be represented in Greenwich Mean Time (GMT), without exception ๐ŸŒ. The first two formats show this with "GMT" as the three-letter time zone abbreviation, and the asctime format MUST be assumed to be GMT when you read it ๐Ÿ•ฐ๏ธ.

       HTTP-date    = rfc1123-date | rfc850-date | asctime-date

       rfc1123-date = wkday "," SP date1 SP time SP "GMT"
       rfc850-date  = weekday "," SP date2 SP time SP "GMT"
       asctime-date = wkday SP date3 SP time SP 4DIGIT

       date1        = 2DIGIT SP month SP 4DIGIT
                      ; day month year (e.g., 02 Jun 1982)
       date2        = 2DIGIT "-" month "-" 2DIGIT
                      ; day-month-year (e.g., 02-Jun-82)
       date3        = month SP ( 2DIGIT | ( SP 1DIGIT ))
                      ; month day (e.g., Jun  2)

       time         = 2DIGIT ":" 2DIGIT ":" 2DIGIT
                      ; 00:00:00 - 23:59:59

       wkday        = "Mon" | "Tue" | "Wed"
                    | "Thu" | "Fri" | "Sat" | "Sun"

       weekday      = "Monday" | "Tuesday" | "Wednesday"
                    | "Thursday" | "Friday" | "Saturday" | "Sunday"

       month        = "Jan" | "Feb" | "Mar" | "Apr"
                    | "May" | "Jun" | "Jul" | "Aug"
                    | "Sep" | "Oct" | "Nov" | "Dec"
Note: HTTP requirements for the date/time stamp format apply only to their usage within the protocol stream. Clients and servers are not required to use these formats for user presentation, request logging, etc.

3.3.2 Delta Seconds โฑ๏ธ

Some HTTP header fields let you specify a time value as an integer number of seconds (written in decimal) counted from the moment the message was received. Very handy ๐Ÿฆ‹.

       delta-seconds  = 1*DIGIT

3.4 Character Sets ๐Ÿ”ค

HTTP uses the exact same definition of "character set" that MIME uses ๐ŸŽ€:

The term "character set" is used in this document to refer to a method used with one or more tables to convert a sequence of octets into a sequence of characters. Note that unconditional conversion in the other direction is not required, in that not all characters may be available in a given character set and a character set may provide more than one sequence of octets to represent a particular character. This definition is intended to allow various kinds of character encodings, from simple single-table mappings such as US-ASCII to complex table switching methods such as those that use ISO 2022's techniques. However, the definition associated with a MIME character set name MUST fully specify the mapping to be performed from octets to characters. In particular, use of external profiling information to determine the exact mapping is not permitted.
Note: This use of the term "character set" is more commonly referred to as a "character encoding." However, since HTTP and MIME share the same registry, it is important that the terminology also be shared.

HTTP character sets are identified by case-insensitive tokens ๐Ÿง. The complete set of tokens is defined by the IANA Character Set registry [19].

       charset = token

Even though HTTP lets you use any arbitrary token as a charset value, any token with a predefined value in the IANA Character Set registry MUST represent the character set defined by that registry ๐Ÿ“–. Applications SHOULD limit their use of character sets to those defined by the IANA registry. Stick to the list, babe ๐Ÿ’œ.

3.5 Content Codings ๐Ÿ—œ๏ธ

Content coding values tell you about an encoding transformation that has been applied, or can be applied, to an entity ๐ŸŽ. Content codings mainly exist so a document can be compressed or otherwise usefully transformed without losing the identity of its underlying media type and without losing information. Usually the entity is stored in coded form, sent as-is, and only decoded by the recipient โœจ.

       content-coding   = token

All content-coding values are case-insensitive. HTTP/1.1 uses content-coding values in the Accept-Encoding (section 14.3) and Content-Encoding (section 14.12) header fields. The value describes the content-coding, but what really matters is that it tells you what decoding mechanism will be needed to remove the encoding ๐Ÿ”‘.

The Internet Assigned Numbers Authority (IANA) acts as a registry for content-coding value tokens. To start, the registry contains the following tokens ๐ŸŒธ:

gzip An encoding format produced by the file compression program "gzip" (GNU zip) as described in RFC 1952 [25]. This format is a Lempel-Ziv coding (LZ77) with a 32 bit CRC.

compress The encoding format produced by the common UNIX file compression program "compress". This format is an adaptive Lempel-Ziv-Welch coding (LZW).

Note: Use of program names for the identification of encoding formats is not desirable and should be discouraged for future encodings. Their use here is representative of historical practice, not good design. For compatibility with previous implementations of HTTP, applications should consider "x-gzip" and "x-compress" to be equivalent to "gzip" and "compress" respectively.

deflate The "zlib" format defined in RFC 1950[31] in combination with the "deflate" compression mechanism described in RFC 1951[29].

New content-coding value tokens should be registered. For clients and servers to interoperate, the specs for the content coding algorithms needed to implement a new value should be publicly available and detailed enough for independent implementation, and they should match the purpose of content coding defined in this section ๐Ÿง .

3.6 Transfer Codings ๐Ÿšš

Transfer coding values say that an encoding transformation has been, can be, or may need to be applied to an entity-body so it can get through the network "safely" ๐Ÿ›ก๏ธ. This is different from a content coding because a transfer coding is a property of the message, not of the original entity.

       transfer-coding         = "chunked" | transfer-extension

       transfer-extension      = token

All transfer-coding values are case-insensitive. HTTP/1.1 uses transfer coding values in the Transfer-Encoding header field (section 14.40).

Transfer codings are kind of like the Content-Transfer-Encoding values of MIME, which were designed to safely move binary data over a 7-bit transport service ๐Ÿงƒ. "Safe transport" means something different for an 8bit-clean transfer protocol, though. In HTTP, the only unsafe thing about message-bodies is that it can be hard to figure out the exact body length (section 7.2.2), or that you might want to encrypt data over a shared transport ๐Ÿ™ˆ.

The chunked encoding changes the body of a message so it can be sent as a series of chunks. Each chunk has its own size indicator, and there's an optional footer containing entity-header fields after them. This lets dynamically-produced content get sent along with the info the recipient needs to check that it got the whole message ๐ŸŽ€.

    Chunked-Body   = *chunk
                     "0" CRLF
                     footer
                     CRLF

    chunk          = chunk-size [ chunk-ext ] CRLF
                     chunk-data CRLF

    hex-no-zero    = <HEX excluding "0">

    chunk-size     = hex-no-zero *HEX
    chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
    chunk-ext-name = token
    chunk-ext-val  = token | quoted-string
    chunk-data     = chunk-size(OCTET)

    footer         = *entity-header

The chunked encoding ends with a zero-sized chunk, then the footer, which finishes with an empty line ๐Ÿ. The footer exists so you can efficiently send info about an entity that's generated dynamically. Applications MUST NOT send header fields in the footer that aren't explicitly defined as appropriate for the footer, like Content-MD5 or future HTTP extensions for digital signatures or other facilities. Don't be that person ๐Ÿ™…โ€โ™€๏ธ.

An example process for decoding a Chunked-Body is in appendix 19.4.6 ๐Ÿงฉ.

All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer coding, and MUST ignore transfer coding extensions they don't understand ๐Ÿ‘€. A server that gets an entity-body with a transfer-coding it doesn't understand SHOULD return 501 (Unimplemented), and close the connection. A server MUST NOT send transfer-codings to an HTTP/1.0 client ๐Ÿ’€.

3.7 Media Types ๐ŸŽจ

HTTP uses Internet Media Types in the Content-Type (section 14.18) and Accept (section 14.1) header fields. That's how it gets open, extensible data typing and type negotiation ๐ŸŒˆ.

       media-type     = type "/" subtype *( ";" parameter )
       type           = token
       subtype        = token

Parameters can follow the type/subtype as attribute/value pairs ๐Ÿ’–.

       parameter      = attribute "=" value
       attribute      = token
       value          = token | quoted-string

The type, subtype, and parameter attribute names are case-insensitive. Parameter values may or may not be case-sensitive, depending on what the parameter name means ๐Ÿง. Linear white space (LWS) MUST NOT be used between the type and subtype, or between an attribute and its value ๐Ÿšซ. User agents that recognize the media-type MUST process the parameters for that MIME type as described by that type/subtype definition to the and inform the user of any problems discovered (or arrange to have them processed by any external applications the user agent uses for that type/subtype) ๐Ÿ”.

Note: some older HTTP applications do not recognize media type parameters. When sending data to older HTTP applications, implementations should only use media type parameters when they are required by that type/subtype definition.

Media-type values are registered with the Internet Assigned Number Authority (IANA). The media type registration process is outlined in RFC 2048 [17]. Using non-registered media types is discouraged ๐Ÿ™ƒ.

3.7.1 Canonicalization and Text Defaults โœจ

okay so Internet media types get registered with a canonical form ๐Ÿ’… and in general, an entity-body sent through HTTP MUST be represented in that canonical form before it gets transmitted. the one exception is "text" types, which the next paragraph covers ๐Ÿฆ‹

when it's in canonical form, media subtypes of "text" use CRLF as the line break. HTTP loosens this a bit ๐ŸŒธ it lets text media use a plain CR or a plain LF on its own as a line break, as long as it's done consistently across the whole entity-body. HTTP applications MUST accept CRLF, bare CR, and bare LF as line breaks in text media they receive over HTTP ๐Ÿซถ and if the text uses a character set that doesn't use octets 13 and 10 for CR and LF (some multi-byte character sets do this), HTTP lets you use whatever octet sequences that character set defines for line breaks ๐ŸŒˆ BUT this flexibility is only for text media in the entity-body. a bare CR or LF MUST NOT be swapped in for CRLF inside any HTTP control structures, like header fields and multipart boundaries ๐Ÿ™…โ€โ™€๏ธ

if an entity-body has a Content-Encoding, the underlying data MUST be in one of the forms above before it gets encoded ๐Ÿ’–

the "charset" parameter tells you which character set (section 3.4) the data uses for some media types ๐ŸŽ€ when the sender doesn't give an explicit charset, media subtypes of "text" are defined to default to "ISO-8859-1" when they come over HTTP. and data in any character set other than "ISO-8859-1" or its subsets MUST be labeled with a proper charset value ๐Ÿ“

ngl this part is so relatable ๐Ÿ˜ญ some HTTP/1.0 software read a Content-Type header with no charset parameter as "recipient should guess" ๐Ÿ’€ if a sender wants to avoid that, they MAY include a charset parameter even when the charset is ISO-8859-1, and they SHOULD do it when it's known it won't confuse the recipient โœจ

unfortunately some older HTTP/1.0 clients couldn't handle an explicit charset parameter properly ๐Ÿ™ˆ so HTTP/1.1 recipients MUST respect the charset label the sender gave them. and any user agents that can "guess" a charset MUST use the charset from the content-type field (if they support it) instead of the recipient's own preference when they first display a document ๐Ÿ‘‘

3.7.2 Multipart Types ๐Ÿงš

MIME has a bunch of "multipart" types, which are encapsulations of one or more entities inside a single message-body ๐Ÿ’œ they all share a common syntax, defined in MIME [7], and they MUST include a boundary parameter as part of the media type value. the message body is its own protocol element, so it MUST use only CRLF to represent line breaks between body-parts ๐ŸŒธ unlike regular MIME, the epilogue of any multipart message MUST be empty, and HTTP applications MUST NOT transmit the epilogue (even if the original multipart had one) ๐Ÿ™…โ€โ™€๏ธ

in HTTP, multipart body-parts MAY have header fields that matter for what that part means โœจ a Content-Location header field (section 14.15) SHOULD be included in the body-part of each enclosed entity that can be identified by a URL ๐Ÿฆ‹

generally, an HTTP user agent SHOULD act the same as, or similarly to, a MIME user agent would when it gets a multipart type ๐Ÿ’… and if an application gets a multipart subtype it doesn't recognize, it MUST treat it as "multipart/mixed" ๐Ÿซถ

Note: "multipart/form-data" was specifically made for carrying form data that's meant to be processed with the POST request method, as described in RFC 1867 [15]. it's giving form data energy ๐Ÿ“โœจ

3.8 Product Tokens ๐ŸŽ€

product tokens let apps say who they are by software name and version ๐Ÿ’– most fields that use them also let you list sub-products that make up a big part of the app, separated by whitespace. by convention, the products are listed in order of how much they matter for identifying the app ๐Ÿ‘‘

product         = token ["/" product-version]
product-version = token

examples:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4

product tokens should be short and to the point ๐Ÿ“ using them for advertising or other non-essential info is explicitly forbidden, no exceptions ๐Ÿ™…โ€โ™€๏ธ and even though any token character can show up in a product-version, this token SHOULD only be used for a version identifier (so successive versions of the same product SHOULD only differ in the product-version part of the product value) ๐ŸŒˆ

3.9 Quality Values ๐ŸŒธ

HTTP content negotiation (section 12) uses short "floating point" numbers to show how important ("weight") different negotiable parameters are ๐Ÿฆ‹ a weight gets normalized to a real number from 0 through 1, where 0 is the minimum and 1 is the maximum ๐Ÿ”ฅ HTTP/1.1 applications MUST NOT generate more than three digits after the decimal point ๐Ÿ™ˆ user configuration of these values SHOULD also be limited the same way ๐Ÿ’…

qvalue         = ( "0" [ "." 0*3DIGIT ] )
               | ( "1" [ "." 0*3("0") ] )

"Quality values" is kind of a misnomer ๐Ÿ˜ญ these values just show the relative degradation in desired quality ๐Ÿซถ

3.10 Language Tags ๐ŸŒˆ

a language tag identifies a natural language that humans speak, write, or otherwise use to share information with each other โœจ computer languages are explicitly excluded ๐Ÿ™…โ€โ™€๏ธ HTTP uses language tags in the Accept-Language and Content-Language fields ๐Ÿ’–

the syntax and registry of HTTP language tags is the same as the one defined by RFC 1766 [1] ๐ŸŽ€ in short, a language tag has 1 or more parts: a primary language tag and a possibly empty series of subtags ๐Ÿ“

language-tag  = primary-tag *( "-" subtag )

primary-tag   = 1*8ALPHA
subtag        = 1*8ALPHA

whitespace is not allowed inside the tag, and all tags are case-insensitive ๐Ÿงš the name space of language tags is administered by the IANA ๐Ÿ‘‘ example tags include:

en, en-US, en-cockney, i-cherokee, x-pig-latin

where any two-letter primary-tag is an ISO 639 language abbreviation, and any two-letter initial subtag is an ISO 3166 country code ๐ŸŒธ (the last three tags above aren't registered tags. all but the last one are examples of tags that could be registered in the future ๐Ÿฆ‹)

3.11 Entity Tags ๐Ÿ’œ

entity tags are used to compare two or more entities from the same requested resource ๐Ÿ’… HTTP/1.1 uses entity tags in the ETag (section 14.20), If-Match (section 14.25), If-None-Match (section 14.26), and If-Range (section 14.27) header fields ๐Ÿซถ how they're used and compared as cache validators is in section 13.3.3 โœจ an entity tag is an opaque quoted string, possibly prefixed by a weakness indicator ๐ŸŽ€

entity-tag = [ weak ] opaque-tag

weak       = "W/"
opaque-tag = quoted-string

a "strong entity tag" may be shared by two entities of a resource only if they are equivalent by octet equality ๐Ÿ”ฅ

a "weak entity tag," marked by the "W/" prefix, may be shared by two entities of a resource only if the entities are equivalent and could be swapped for each other with no significant change in semantics ๐Ÿฆ‹ a weak entity tag can only be used for weak comparison ๐Ÿ™ˆ

an entity tag MUST be unique across all versions of all entities associated with a particular resource ๐Ÿ‘‘ a given entity tag value may be used for entities obtained by requests on different URIs, without implying anything about whether those entities are equivalent ๐ŸŒˆ

3.12 Range Units ๐Ÿงš

HTTP/1.1 lets a client ask for only part (a range of) the response entity to be included in the response ๐Ÿ’– HTTP/1.1 uses range units in the Range (section 14.36) and Content-Range (section 14.17) header fields ๐Ÿ“ an entity can be broken down into subranges based on different structural units โœจ

range-unit       = bytes-unit | other-range-unit

bytes-unit       = "bytes"
other-range-unit = token

the only range unit HTTP/1.1 defines is "bytes" ๐ŸŒธ HTTP/1.1 implementations may ignore ranges specified with other units ๐Ÿซถ and HTTP/1.1 was designed so that apps that don't depend on knowing about ranges can still work ๐Ÿ’…

4 HTTP Message ๐Ÿ’–

4.1 Message Types ๐Ÿฆ‹

HTTP messages are made up of requests from client to server and responses from server to client ๐Ÿ’œ

HTTP-message   = Request | Response     ; HTTP/1.1 messages

Request (section 5) and Response (section 6) messages use the generic message format of RFC 822 [9] for transferring entities (the payload of the message) โœจ both types of message have a start-line, one or more header fields (aka "headers"), an empty line (a line with nothing before the CRLF) that marks the end of the header fields, and an optional message-body ๐ŸŽ€

generic-message = start-line
                  *message-header
                  CRLF
                  [ message-body ]

start-line      = Request-Line | Status-Line

for the sake of robustness, servers SHOULD ignore any empty line(s) received where a Request-Line is expected ๐Ÿ™ˆ in other words, if the server is reading the protocol stream at the start of a message and gets a CRLF first, it should ignore that CRLF ๐ŸŒˆ

Note: some buggy HTTP/1.0 client implementations send an extra CRLF after a POST request ๐Ÿ˜ญ to restate what the BNF explicitly forbids, an HTTP/1.1 client must not put an extra CRLF before or after a request ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’…

4.2 Message Headers โœจ

okay so header fields ๐Ÿ’… โ€” that's general-header (section 4.5), request-header (section 5.3), response-header (section 6.2), and entity-header (section 7.1) fields, and they all follow the same generic format as Section 3.1 of RFC 822 [9]. Each one is a name, then a colon (:), then the field value. Field names are case-insensitive ๐Ÿฆ‹ The value can start with any amount of LWS, but a single SP is the preferred vibe. You can also continue a header over multiple lines by starting each extra line with at least one SP or HT. And here's the important bit: applications SHOULD stick to "common form" when generating HTTP stuff ๐Ÿซถ because some implementations are only ready for the common forms and will fail on anything fancier. Be a good citizen, bestie.

message-header = field-name ":" [ field-value ] CRLF

field-name     = token
field-value    = *( field-content | LWS )

field-content  = <the OCTETs making up the field-value
                 and consisting of either *TEXT or combinations
                 of token, tspecials, and quoted-string>

The order that headers with different field names arrive in doesn't matter ๐ŸŒธ BUT it's "good practice" to send general-header fields first, then request-header or response-header fields, and wrap up with the entity-header fields. Very organized, very iconic.

Now the spicy part ๐ŸŒถ๏ธ Multiple message-header fields with the same field-name can show up in one message ONLY IF the whole field-value for that header is defined as a comma-separated list [i.e., #(values)]. Every single time, the multiple fields MUST be combinable into one "field-name: field-value" pair without changing what the message means, by appending each later field-value to the first one and separating them with commas. Since the order of same-named fields matters when you combine them, a proxy MUST NOT change the order of these field values when it forwards a message. Order is sacred here, no cap ๐Ÿ”ฅ

4.3 Message Body ๐ŸŽ€

the message-body (if there is one) of an HTTP message is what carries the entity-body for the request or response. These two only differ when a transfer coding has been applied, which gets flagged by the Transfer-Encoding header field (section 14.40) ๐Ÿ’œ

message-body = entity-body
             | <entity-body encoded as per Transfer-Encoding>

Here's the rule: Transfer-Encoding MUST be used to indicate any transfer codings an application has applied, so the message gets transferred safely and properly ๐Ÿงš It's a property of the message, not the entity, which means any application along the request/response chain can add or remove it. Main character energy for sure โœจ

The rules for when a message-body is allowed are different for requests and responses, so let's split them up ๐Ÿฆ‹

For requests, a message-body is signaled by including a Content-Length or Transfer-Encoding header field in the request's message-headers. A message-body MAY be included in a request only when the request method (section 5.1.1) allows an entity-body. ๐Ÿ“

For responses, it depends on BOTH the request method and the response status code (section 6.1.1) ๐Ÿ™ˆ Every response to the HEAD request method MUST NOT include a message-body, even though the entity-header fields might make you think one is there. All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body. Everything else DOES include a message-body, though it may be of zero length ๐Ÿ’€

4.4 Message Length ๐ŸŒˆ

when a message-body comes with a message, its length is figured out by one of these, in order of precedence (the first one that applies wins, periodt ๐Ÿ‘‘):

  1. Any response message which MUST NOT include a message-body (such as the 1xx, 204, and 304 responses and any response to a HEAD request) is always ended by the first empty line after the header fields, no matter which entity-header fields are in the message. ๐Ÿ˜ญ
  2. If a Transfer-Encoding header field (section 14.40) is present and says the "chunked" transfer coding has been applied, then the length is defined by the chunked encoding (section 3.6). ๐ŸŒธ
  3. If a Content-Length header field (section 14.14) is present, its value in bytes is the length of the message-body. ๐Ÿ’–
  4. If the message uses the media type "multipart/byteranges", which is self-delimiting, then that defines the length. This media type MUST NOT be used unless the sender knows the recipient can parse it. Also, a request with a Range header that has multiple byte-range specifiers implies the client can parse multipart/byteranges responses ๐Ÿซถ
  5. By the server closing the connection. (Closing the connection cannot be used to mark the end of a request body, because that would leave the server no way to send back a response. ๐Ÿ™ƒ)

For compatibility with HTTP/1.0 applications, HTTP/1.1 requests that contain a message-body MUST include a valid Content-Length header field, UNLESS the server is known to be HTTP/1.1 compliant. If a request has a message-body and no Content-Length, the server SHOULD respond with 400 (bad request) if it can't work out the length of the message, or with 411 (length required) if it wants to insist on a valid Content-Length. Strict but fair ๐Ÿ’…

All HTTP/1.1 applications that receive entities MUST accept the "chunked" transfer coding (section 3.6). That lets this mechanism be used for messages whose length can't be known in advance, which is so useful โœจ

Messages MUST NOT include both a Content-Length header field AND the "chunked" transfer coding. If both show up, the Content-Length MUST be ignored. Pick one, babe ๐Ÿ”ฅ

When a Content-Length is given in a message where a message-body is allowed, its field value MUST exactly match the number of OCTETs in the message-body. And HTTP/1.1 user agents MUST notify the user when an invalid length is received and detected. No hiding the bad news, bestie ๐Ÿ™ˆ

4.5 General Header Fields ๐Ÿฆ‹

there are a few header fields that apply to both request and response messages, but they don't apply to the entity being transferred. They only apply to the message being sent, so they're basically the messages' own little accessories ๐Ÿ’œ

general-header = Cache-Control            ; Section 14.9
               | Connection               ; Section 14.10
               | Date                     ; Section 14.19
               | Pragma                   ; Section 14.32
               | Transfer-Encoding        ; Section 14.40
               | Upgrade                  ; Section 14.41
               | Via                      ; Section 14.44

General-header field names can only be extended reliably together with a change in the protocol version ๐ŸŒˆ New or experimental header fields may be given the semantics of general header fields if every party in the communication recognizes them as general-header fields. Unrecognized header fields are treated as entity-header fields. iykyk ๐Ÿงš


5 Request ๐Ÿ’–

a request message from a client to a server includes, in its first line, the method to be applied to the resource, the identifier of the resource, and the protocol version in use. The whole shape looks like this ๐Ÿ‘‘

Request       = Request-Line              ; Section 5.1
                *( general-header         ; Section 4.5
                 | request-header         ; Section 5.3
                 | entity-header )        ; Section 7.1
                CRLF
                [ message-body ]          ; Section 7.2

5.1 Request-Line โœจ

the Request-Line starts with a method token, followed by the Request-URI and the protocol version, and it ends with CRLF. The elements are separated by SP characters. No CR or LF is allowed except in the final CRLF sequence. Very strict, very clean ๐Ÿซถ

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

5.1.1 Method ๐ŸŒธ

the Method token says what should be done to the resource identified by the Request-URI. The method is case-sensitive, so get and GET are NOT the same girl ๐Ÿ™ˆ

Method         = "OPTIONS"                ; Section 9.2
               | "GET"                    ; Section 9.3
               | "HEAD"                   ; Section 9.4
               | "POST"                   ; Section 9.5
               | "PUT"                    ; Section 9.6
               | "DELETE"                 ; Section 9.7
               | "TRACE"                  ; Section 9.8
               | extension-method

extension-method = token

A resource's allowed methods can be listed in an Allow header field (section 14.7). The response's return code always tells the client whether a method is allowed on a resource right now, because the allowed set can change on the fly ๐Ÿฆ‹ Servers SHOULD return status code 405 (Method Not Allowed) if the method is known to the server but not allowed for that resource, and 501 (Not Implemented) if the method is unrecognized or not implemented by the server. The methods a server knows can be listed in a Public response-header field (section 14.35) ๐Ÿ’…

The methods GET and HEAD MUST be supported by all general-purpose servers. All other methods are optional. But if the methods above ARE implemented, they MUST be implemented with the same semantics as those in section 9 ๐Ÿ”ฅ

5.1.2. Request-URI ๐ŸŽ€

okay so the Request-URI is a Uniform Resource Identifier (section 3.2) and it tells the server which resource the request is about ๐Ÿฆ‹

Request-URI = "*" | absoluteURI | abs_path

there are three options for the Request-URI and which one you use depends on what kind of request you're sending ๐Ÿ’… the asterisk "*" means the request isn't about a particular resource, it's about the server itself, and you can only use it when the method doesn't have to apply to a resource. an example would be

OPTIONS * HTTP/1.1

the absoluteURI form is required when you're sending the request to a proxy ๐Ÿซถ the proxy is asked to forward the request, or serve it from a valid cache, and send back the response. the proxy MAY forward the request on to another proxy or straight to the server named in the absoluteURI โœจ but to avoid request loops, a proxy MUST be able to recognize all of its server names, including any aliases, local variations, and the numeric IP address ๐Ÿ˜ญ an example Request-Line would be:

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

so future versions of HTTP can switch to absoluteURIs in every request, all HTTP/1.1 servers MUST accept the absoluteURI form in requests ๐ŸŒˆ even though HTTP/1.1 clients will only actually generate them for requests going to proxies

the most common form of Request-URI is the one used to reach a resource on an origin server or gateway ๐Ÿ“ in that case the absolute path of the URI MUST be transmitted (see section 3.2.1, abs_path) as the Request-URI, and the network location of the URI (net_loc) MUST be transmitted in a Host header field. for example, a client that wants to grab the resource above straight from the origin server would open a TCP connection to port 80 of the host "www.w3.org" and send these lines:

GET /pub/WWW/TheProject.html HTTP/1.1 Host: www.w3.org

and then the rest of the request โœจ quick note: the absolute path cannot be empty. if there isn't one in the original URI, it MUST be given as "/" (the server root) ๐Ÿ‘‘

if a proxy gets a request with no path in the Request-URI, and the method can support the asterisk form, then the last proxy on the request chain MUST forward the request with "*" as the final Request-URI ๐Ÿงš for example, this request

OPTIONS http://www.ics.uci.edu:8001 HTTP/1.1

would get forwarded by the proxy as

OPTIONS * HTTP/1.1 Host: www.ics.uci.edu:8001

after it connects to port 8001 of the host "www.ics.uci.edu" ๐Ÿ’–

the Request-URI is sent in the format from section 3.2.1. the origin server MUST decode the Request-URI so it can properly understand the request ๐Ÿ™ˆ and servers SHOULD respond to invalid Request-URIs with an appropriate status code

when proxies forward requests, they MUST NOT rewrite the "abs_path" part of a Request-URI in any way, no matter what their internal implementation does ๐Ÿ”ฅ the only exception is the one noted above, replacing a null abs_path with "*"

Note: The "no rewrite" rule prevents the proxy from changing the meaning of the request when the origin server is improperly using a non-reserved URL character for a reserved purpose. Implementers should be aware that some pre-HTTP/1.1 proxies have been known to rewrite the Request-URI.

5.2. The Resource Identified by a Request ๐ŸŒธ

HTTP/1.1 origin servers SHOULD be aware that the exact resource an Internet request is pointing at is determined by looking at both the Request-URI and the Host header field ๐Ÿ‘€

an origin server that doesn't let resources differ by requested host MAY ignore the Host header field value. (but see section 19.5.1 for other requirements on Host support in HTTP/1.1 ๐Ÿ™ƒ)

an origin server that DOES tell resources apart based on the host requested (sometimes called virtual hosts or vanity hostnames) MUST use these rules to work out the requested resource on an HTTP/1.1 request, and it's giving very organized energy ๐Ÿ“‹

  1. If Request-URI is an absoluteURI, the host is part of the Request-URI. Any Host header field value in the request MUST be ignored.
  2. If the Request-URI is not an absoluteURI, and the request includes a Host header field, the host is determined by the Host header field value.
  3. If the host as determined by rule 1 or 2 is not a valid host on the server, the response MUST be a 400 (Bad Request) error message.

recipients of an HTTP/1.0 request that has no Host header field MAY try heuristics (like checking the URI path for something unique to a particular host) to figure out which exact resource is being asked for ๐Ÿ•ต๏ธโ€โ™€๏ธ


5.3. Request Header Fields ๐ŸŽ€

the request-header fields let the client pass extra info about the request, and about the client itself, over to the server โœจ they act as request modifiers, kind of like the parameters you pass into a programming language method call ๐Ÿ’…

request-header = Accept ; Section 14.1

Accept-Charset ; Section 14.2
Accept-Encoding ; Section 14.3
Accept-Language ; Section 14.4
Authorization ; Section 14.8
From ; Section 14.22
Host ; Section 14.23
If-Modified-Since ; Section 14.24
If-Match ; Section 14.25
If-None-Match ; Section 14.26
If-Range ; Section 14.27
If-Unmodified-Since ; Section 14.28
Max-Forwards ; Section 14.31
Proxy-Authorization ; Section 14.34
Range ; Section 14.36
Referer ; Section 14.37
User-Agent ; Section 14.42

request-header field names can only be extended reliably in combination with a change in the protocol version ๐Ÿฆ‹ however, new or experimental header fields MAY be given the semantics of request-header fields if all parties in the communication recognize them as request-header fields. unrecognized header fields are treated as entity-header fields ๐ŸŒˆ


6. Response ๐Ÿ’œ

after a server receives and interprets a request message, it responds with an HTTP response message ๐Ÿซถ

Response = Status-Line ; Section 6.1 *( general-header ; Section 4.5

response-header ; Section 6.2
entity-header ) ; Section 7.1

CRLF [ message-body ] ; Section 7.2


6.1. Status-Line ๐Ÿ“

the first line of a Response message is the Status-Line, which is made of the protocol version, then a numeric status code, then its matching textual phrase, with each element separated by SP characters ๐Ÿงš no CR or LF is allowed except in the final CRLF sequence ๐Ÿ™ˆ

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF


6.1.1. Status Code and Reason Phrase ๐ŸŒธ

the Status-Code is a 3-digit integer result code for how the attempt to understand and satisfy the request went ๐Ÿ“Š these codes are fully defined in section 10. the Reason-Phrase is meant to be a short textual description of the Status-Code. the Status-Code is for automata (machines!) and the Reason-Phrase is for the human user ๐Ÿค– the client doesn't have to examine or display the Reason-Phrase ๐Ÿ’…

the first digit of the Status-Code defines the class of response ๐Ÿ”ฅ the last two digits don't have any categorization role. there are 5 values for the first digit:

  • 1xx: Informational - Request received, continuing process
  • 2xx: Success - The action was successfully received, understood, and accepted
  • 3xx: Redirection - Further action must be taken in order to complete the request
  • 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
  • 5xx: Server Error - The server failed to fulfill an apparently valid request

here are the individual numeric status codes defined for HTTP/1.1, plus an example set of matching Reason-Phrases ๐Ÿ‘‘ the reason phrases listed here are only recommended, and they can be swapped for local equivalents without affecting the protocol โœจ

Status-Code = "100" ; Continue

"101" ; Switching Protocols
"200" ; OK
"201" ; Created
"202" ; Accepted
"203" ; Non-Authoritative Information
"204" ; No Content
"205" ; Reset Content
"206" ; Partial Content
"300" ; Multiple Choices
"301" ; Moved Permanently
"302" ; Moved Temporarily
"303" ; See Other
"304" ; Not Modified
"305" ; Use Proxy
"400" ; Bad Request
"401" ; Unauthorized
"402" ; Payment Required
"403" ; Forbidden
"404" ; Not Found
"405" ; Method Not Allowed
"406" ; Not Acceptable
"407" ; Proxy Authentication Required
"408" ; Request Time-out
"409" ; Conflict
"410" ; Gone
"411" ; Length Required
"412" ; Precondition Failed
"413" ; Request Entity Too Large
"414" ; Request-URI Too Large
"415" ; Unsupported Media Type
"500" ; Internal Server Error
"501" ; Not Implemented
"502" ; Bad Gateway
"503" ; Service Unavailable
"504" ; Gateway Time-out
"505" ; HTTP Version not supported
extension-code

extension-code = 3DIGIT

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

HTTP status codes are extensible ๐ŸŒˆ HTTP applications don't have to understand every registered status code, though understanding them is obviously desirable ๐Ÿ’– however, applications MUST understand the class of any status code, as shown by the first digit, and treat any unrecognized response as equivalent to the x00 status code of that class, with one exception: an unrecognized response MUST NOT be cached ๐Ÿ™…โ€โ™€๏ธ for example, if a client gets an unrecognized status code of 431, it can safely assume something was wrong with its request and treat the response as if it had gotten a 400 status code ๐Ÿ˜ญ in cases like this, user agents SHOULD show the user the entity returned with the response, since that entity is likely to include human-readable info explaining the unusual status ๐Ÿซถ

6.2. Response Header Fields ๐ŸŽ€

Okay so response headers are how the server sneaks in extra info that just doesn't fit in the Status-Line ๐Ÿ’… Think of it as the server giving you the tea on itself and on what you can do next with the resource at the Request-URI โœจ

          response-header = Age                     ; Section 14.6
                          | Location                ; Section 14.30
                          | Proxy-Authenticate      ; Section 14.33
                          | Public                  ; Section 14.35
                          | Retry-After             ; Section 14.38
                          | Server                  ; Section 14.39
                          | Vary                    ; Section 14.43
                          | Warning                 ; Section 14.45
                          | WWW-Authenticate        ; Section 14.46

Real talk, response header names can only be extended reliably alongside a protocol version change ๐Ÿฆ‹ BUT new or experimental header fields MAY be given response-header semantics, as long as every party in the conversation recognizes them as response headers ๐ŸŒˆ And if nobody recognizes a header, it gets treated as an entity-header field, so it's not lost in the void ๐Ÿงš

7. Entity โœจ

Okay bestie, here's the deal: Request and Response messages MAY carry an entity, as long as the request method or response status code doesn't say otherwise ๐Ÿซถ An entity is made up of entity-header fields and an entity-body, though some responses only bring the entity-headers to the party ๐Ÿ’œ

Quick heads up, in this section "sender" and "recipient" just mean whoever is the client or the server, depending on who's sending and who's receiving the entity ๐ŸŒธ

7.1. Entity Header Fields ๐Ÿ“

These fields are optional metainformation about the entity-body, or if there's no body, about the resource the request identified ๐Ÿ’…

          entity-header  = Allow                    ; Section 14.7
                         | Content-Base             ; Section 14.11
                         | Content-Encoding         ; Section 14.12
                         | Content-Language         ; Section 14.13
                         | Content-Length           ; Section 14.14
                         | Content-Location         ; Section 14.15
                         | Content-MD5              ; Section 14.16
                         | Content-Range            ; Section 14.17
                         | Content-Type             ; Section 14.18
                         | ETag                     ; Section 14.20
                         | Expires                  ; Section 14.21
                         | Last-Modified            ; Section 14.29
                         | extension-header

          extension-header = message-header

The extension-header thing lets you define extra entity-header fields without changing the protocol ๐Ÿ”ฅ But you can't assume the recipient will recognize them, ngl ๐Ÿ’€ Unrecognized header fields SHOULD be ignored by the recipient and forwarded by proxies ๐Ÿ™ˆ

7.2. Entity Body ๐Ÿฆ‹

The entity-body (if there is one) in an HTTP request or response is in whatever format and encoding the entity-header fields say it's in ๐ŸŽ€

          entity-body    = *OCTET

An entity-body only shows up when a message-body is there too, as covered in section 4.3 โœจ To get the entity-body, you decode whatever Transfer-Encoding was applied to the message-body, so the transfer stays safe and proper ๐Ÿซถ

7.2.1. Type ๐Ÿ‘‘

When a message includes an entity-body, its data type comes from the Content-Type and Content-Encoding header fields. Together they make a two-layer, ordered encoding model, and it's giving very specific ๐Ÿ’…

          entity-body := Content-Encoding( Content-Type( data ) )

Content-Type tells you the media type of the underlying data ๐ŸŒˆ Content-Encoding can name any extra content codings applied to the data, usually for compression, which are a property of the requested resource ๐Ÿ—œ๏ธ There is no default encoding, so don't go looking for one ๐Ÿ™ˆ

Any HTTP/1.1 message with an entity-body SHOULD include a Content-Type header field that defines the media type of that body ๐Ÿ’– If and only if the media type isn't given by a Content-Type field, the recipient MAY try to guess it by inspecting the content and/or the name extension(s) of the URL used to identify the resource ๐Ÿ” If the media type is still unknown, the recipient SHOULD treat it as type "application/octet-stream" ๐Ÿงš

7.2.2. Length ๐ŸŒธ

The length of an entity-body is the length of the message-body after any transfer codings have been removed ๐Ÿ“ Section 4.4 explains how the length of a message-body gets figured out ๐Ÿ’…

8. Connections โœจ

8.1. Persistent Connections ๐Ÿฆ‹

8.1.1. Purpose ๐ŸŽ€

Before persistent connections, every URL needed its own separate TCP connection ๐Ÿ˜ญ That meant more load on HTTP servers and congestion on the Internet, which was not it ๐Ÿ’€ Inline images and other associated data often mean a client has to hit the same server a bunch of times in a short window, so the performance problems were real ๐Ÿ”ฅ Analyses of these are available in [30][27], and analysis plus results from a prototype implementation are in [26] ๐Ÿ“š

Persistent HTTP connections come with a bunch of perks, bestie ๐Ÿ‘‘

  • By opening and closing fewer TCP connections, CPU time gets saved, and so does the memory used for TCP protocol control blocks ๐Ÿ’œ
  • HTTP requests and responses can be pipelined on a connection ๐ŸŒˆ Pipelining lets a client make multiple requests without waiting for each response, so a single TCP connection gets used way more efficiently, with much lower elapsed time โญ
  • Network congestion goes down because there are fewer packets from TCP opens, and TCP gets enough time to figure out the congestion state of the network ๐ŸŒŠ
  • HTTP can evolve more gracefully, since errors can be reported without the penalty of closing the TCP connection ๐Ÿฆ‹ Clients using future versions of HTTP might optimistically try a new feature, and if they're talking to an older server, they can retry with the old semantics after an error is reported ๐Ÿซถ

HTTP implementations SHOULD implement persistent connections โœจ

8.1.2. Overall Operation ๐Ÿ’…

Here's the big difference between HTTP/1.1 and earlier versions: persistent connections are the default behavior for any HTTP connection ๐ŸŽ€ Unless something says otherwise, the client can assume the server will keep a persistent connection open for it ๐Ÿฆ‹

Persistent connections also give the client and server a way to signal that a TCP connection should close ๐ŸŒธ That signal goes through the Connection header field ๐Ÿ“จ Once a close has been signaled, the client MUST not send any more requests on that connection ๐Ÿ™…โ€โ™€๏ธ

8.1.2.1. Negotiation ๐ŸŒˆ

Hmm, heading depth note: this is ### per the format rules, so it's written below.

Okay so an HTTP/1.1 server MAY assume an HTTP/1.1 client wants a persistent connection, unless the request had a Connection header including the connection-token close ๐Ÿ’œ If the server decides to close the connection right after sending the response, it SHOULD send a Connection header including the connection-token close ๐Ÿ”ฅ

An HTTP/1.1 client MAY expect a connection to stay open, but it decides whether to keep it open based on whether the server's response has a Connection header with the connection-token close ๐Ÿ‘€ If the client doesn't want to keep the connection for more than that one request, it SHOULD send a Connection header including the connection-token close โœจ

If either the client or the server sends the close token in the Connection header, that request becomes the last one on the connection ๐Ÿซถ

Clients and servers SHOULD NOT assume a persistent connection is maintained for HTTP versions less than 1.1 unless it's explicitly signaled ๐Ÿ™ˆ See section 19.7.1 for more on backwards compatibility with HTTP/1.0 clients ๐Ÿ“š

To stay persistent, every message on the connection has to have a self-defined message length, meaning one not defined by the connection closing, as described in section 4.4 ๐Ÿ’–

8.1.2.2. Pipelining ๐Ÿงš

A client that supports persistent connections MAY "pipeline" its requests, which means sending multiple requests without waiting for each response ๐Ÿš€ A server MUST send its responses to those requests in the same order the requests were received ๐Ÿ“ฌ

Clients that assume persistent connections and pipeline right after connection establishment SHOULD be ready to retry their connection if the first pipelined attempt fails ๐Ÿ” If a client does retry, it MUST NOT pipeline until it knows the connection is persistent ๐Ÿ™…โ€โ™€๏ธ Clients MUST also be ready to resend their requests if the server closes the connection before sending all of the corresponding responses ๐Ÿ˜ญ

8.1.3. Proxy Servers ๐ŸŒธ

It's especially important that proxies correctly implement the properties of the Connection header field as specified in 14.2.1 ๐ŸŽ€

The proxy server MUST signal persistent connections separately with its clients and with the origin servers (or other proxy servers) it connects to ๐Ÿ’… Each persistent connection applies to only one transport link ๐Ÿฆ‹

A proxy server MUST NOT establish a persistent connection with an HTTP/1.0 client ๐Ÿ™ˆ

8.1.4. Practical Considerations ๐Ÿ’œ

Servers usually have some time-out value past which they stop maintaining an inactive connection โฐ Proxy servers might set this higher, since the client is probably making more connections through the same server ๐ŸŒ Using persistent connections puts no requirements on how long this time-out is, for either the client or the server โœจ

When a client or server wants to time-out, it SHOULD issue a graceful close on the transport connection ๐Ÿ‘‹ Clients and servers SHOULD both constantly watch for the other side closing the transport, and respond to it as appropriate ๐Ÿ‘€ If a client or server doesn't notice the other side's close promptly, it could cause unnecessary resource drain on the network ๐Ÿ˜ฉ

A client, server, or proxy MAY close the transport connection at any time ๐Ÿ’… For example, a client MAY have started sending a new request at the exact moment the server decided to close the "idle" connection ๐Ÿ˜ณ From the server's point of view the connection was closed while it was idle, but from the client's point of view a request was in progress ๐Ÿซ 

So clients, servers, and proxies MUST be able to recover from asynchronous close events ๐Ÿ› ๏ธ Client software SHOULD reopen the transport connection and retransmit the aborted request without user interaction, as long as the request method is idempotent (see section 9.1.2) ๐Ÿ” Other methods MUST NOT be automatically retried, although user agents MAY offer a human operator the choice of retrying the request ๐Ÿ™‹โ€โ™€๏ธ

That said, this automatic retry SHOULD NOT be repeated if the second request fails ๐Ÿ›‘

Servers SHOULD always respond to at least one request per connection, if at all possible โœจ Servers SHOULD NOT close a connection in the middle of transmitting a response, unless a network or client failure is suspected ๐Ÿšซ

Clients that use persistent connections SHOULD limit how many simultaneous connections they maintain to a given server ๐ŸŒˆ A single-user client SHOULD maintain AT MOST 2 connections with any server or proxy ๐Ÿซถ A proxy SHOULD use up to 2*N connections to another server or proxy, where N is the number of simultaneously active users ๐Ÿ‘‘ These guidelines exist to improve HTTP response times and avoid congestion of the Internet or other networks ๐Ÿงš

8.2. Message Transmission Requirements ๐Ÿ’–

Okay so the general requirements are basically the golden rules of HTTP/1.1 connections ๐Ÿ’…

  • HTTP/1.1 servers SHOULD keep persistent connections alive ๐Ÿซถ and lean on TCP's flow control to handle temporary overloads, instead of slamming connections shut and hoping clients come back to retry. ngl that second move can make network congestion way worse ๐Ÿ’€
  • An HTTP/1.1 (or later) client sending a message-body SHOULD keep an eye on the network connection for an error status while it's still sending the request ๐Ÿ‘€ If the client sees an error status, it SHOULD immediately stop sending the body. If the body is going out with a "chunked" encoding (section 3.6), a zero length chunk and empty footer MAY be used to prematurely mark the end of the message โœจ If the body was preceded by a Content-Length header, the client MUST close the connection.
  • An HTTP/1.1 (or later) client MUST be prepared to accept a 100 (Continue) status followed by a regular response ๐ŸŽ€
  • An HTTP/1.1 (or later) server that gets a request from a HTTP/1.0 (or earlier) client MUST NOT transmit the 100 (continue) response ๐Ÿ™ˆ it SHOULD either wait for the request to be completed normally (thus avoiding an interrupted request) or close the connection prematurely.

Upon receiving a method subject to these requirements from an HTTP/1.1 (or later) client, an HTTP/1.1 (or later) server MUST either respond with 100 (Continue) status and continue to read from the input stream, or respond with an error status. If it responds with an error status, it MAY close the transport (TCP) connection or it MAY continue to read and discard the rest of the request. It MUST NOT perform the requested method if it returns an error status ๐Ÿšซ

Clients SHOULD remember the version number of at least the most recently used server ๐Ÿง  if an HTTP/1.1 client has seen an HTTP/1.1 or later response from the server, and it sees the connection close before receiving any status from the server, the client SHOULD retry the request without user interaction so long as the request method is idempotent (see section 9.1.2) ๐Ÿ” other methods MUST NOT be automatically retried, although user agents MAY offer a human operator the choice of retrying the request.. If the client does retry the request, the client:

  • MUST first send the request header fields, and then
  • MUST wait for the server to respond with either a 100 (Continue) response, in which case the client should continue, or with an error status ๐Ÿซง

If an HTTP/1.1 client has not seen an HTTP/1.1 or later response from the server, it should assume that the server implements HTTP/1.0 or older and will not use the 100 (Continue) response ๐Ÿค” If in this case the client sees the connection close before receiving any status from the server, the client SHOULD retry the request. If the client does retry the request to this HTTP/1.0 server, it should use the following "binary exponential backoff" algorithm to be assured of obtaining a reliable response ๐ŸŒธ

  1. Initiate a new connection to the server
  2. Transmit the request-headers
  3. Initialize a variable R to the estimated round-trip time to the server (e.g., based on the time it took to establish the connection), or to a constant value of 5 seconds if the round-trip time is not available.
  4. Compute T = R * (2**N), where N is the number of previous retries of this request.
  5. Wait either for an error response from the server, or for T seconds (whichever comes first)
  6. If no error response is received, after T seconds transmit the body of the request.
  7. If client sees that the connection is closed prematurely, repeat from step 1 until the request is accepted, an error response is received, or the user becomes impatient and terminates the retry process. ๐Ÿ˜ค

No matter what the server version, if an error status is received, the client:

  • MUST NOT continue and
  • MUST close the connection if it has not completed sending the message.

An HTTP/1.1 (or later) client that sees the connection close after receiving a 100 (Continue) but before receiving any other status SHOULD retry the request, and need not wait for 100 (Continue) response (but MAY do so if this simplifies the implementation) ๐Ÿ’–


9 Method Definitions ๐ŸŽ€

The set of common methods for HTTP/1.1 is defined below. Although this set can be expanded, additional methods cannot be assumed to share the same semantics for separately extended clients and servers ๐Ÿงš

The Host request-header field (section 14.23) MUST accompany all HTTP/1.1 requests ๐Ÿ’…

9.1 Safe and Idempotent Methods

9.1.1 Safe Methods

Implementers should be aware that the software represents the user in their interactions over the Internet, and should be careful to allow the user to be aware of any actions they may take which may have an unexpected significance to themselves or others ๐Ÿซถ

In particular, the convention has been established that the GET and HEAD methods should never have the significance of taking an action other than retrieval. These methods should be considered "safe." This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested โœจ

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature ๐ŸŒˆ The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them ๐Ÿ™ˆ

9.1.2 Idempotent Methods

Methods may also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property ๐Ÿ”

9.2 OPTIONS

The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval ๐Ÿ”

Unless the server's response is an error, the response MUST NOT include entity information other than what can be considered as communication options (e.g., Allow is appropriate, but Content-Type is not). Responses to this method are not cachable ๐Ÿšซ

If the Request-URI is an asterisk ("*"), the OPTIONS request is intended to apply to the server as a whole. A 200 response SHOULD include any header fields which indicate optional features implemented by the server (e.g., Public), including any extensions not defined by this specification, in addition to any applicable general or response-header fields. As described in section 5.1.2, an "OPTIONS *" request can be applied through a proxy by specifying the destination server in the Request-URI without any path information ๐ŸŒ

If the Request-URI is not an asterisk, the OPTIONS request applies only to the options that are available when communicating with that resource. A 200 response SHOULD include any header fields which indicate optional features implemented by the server and applicable to that resource (e.g., Allow), including any extensions not defined by this specification, in addition to any applicable general or response-header fields. If the OPTIONS request passes through a proxy, the proxy MUST edit the response to exclude those options which apply to a proxy's capabilities and which are known to be unavailable through that proxy ๐Ÿงน

9.3 GET

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process ๐Ÿ“ฆ

The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the client ๐Ÿฆ‹

The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A partial GET requests that only part of the entity be transferred, as described in section 14.36. The partial GET method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed without transferring data already held by the client ๐Ÿงฉ

The response to a GET request is cachable if and only if it meets the requirements for HTTP caching described in section 13 ๐Ÿ’œ

9.4 HEAD

The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information sent in response to a GET request. This method can be used for obtaining metainformation about the entity implied by the request without transferring the entity-body itself. This method is often used for testing hypertext links for validity, accessibility, and recent modification ๐Ÿ”—

The response to a HEAD request may be cachable in the sense that the information contained in the response may be used to update a previously cached entity from that resource. If the new field values indicate that the cached entity differs from the current entity (as would be indicated by a change in Content-Length, Content-MD5, ETag or Last-Modified), then the cache MUST treat the cache entry as stale ๐Ÿซ 

9.5 POST

okay bestie, POST is the method that says "hey server, please accept this entity as a brand new subordinate of the resource in my Request-Line!" ๐Ÿ’Œ The Request-URI is the boss, and the entity you send is its new little helper. ๐ŸŽ€ The vibe is that one method covers a bunch of different jobs:

  • Annotating an existing resource ๐Ÿ“
  • Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles ๐Ÿ“ฎ
  • Handing over a block of data, like the result of submitting a form, to a data-handling process ๐Ÿ“‹
  • Extending a database through an append operation ๐Ÿ—„๏ธ

What POST actually does is up to the server, and it usually depends on the Request-URI. โœจ The posted entity is subordinate to that URI the same way a file belongs to the directory holding it, a news article belongs to the newsgroup it's posted to, or a record belongs to a database. ๐Ÿงš

Sometimes a POST doesn't end up making a resource you can name with a URI. ๐Ÿคทโ€โ™€๏ธ In that case, 200 (OK) or 204 (No Content) is the right response status. Which one depends on whether the response includes an entity that describes the result. ๐Ÿ’…

If a resource has been created on the origin server, the response SHOULD be 201 (Created). It should contain an entity that describes the status of the request and refers to the new resource, plus a Location header (see section 14.30). ๐Ÿฆ‹ Main character energy!

Responses to this method are not cachable, unless the response includes appropriate Cache-Control or Expires header fields. ๐Ÿ™ˆ The only exception is that the 303 (See Other) response can send the user agent off to retrieve a cachable resource. ๐Ÿ”€

POST requests must obey the message transmission requirements set out in section 8.2. ๐ŸŒˆ


9.6 PUT

Okay, PUT is basically "please store this enclosed entity under the Request-URI I just gave you." ๐Ÿ’– If the Request-URI already points at a resource, the enclosed entity SHOULD be treated as a modified version of the one living on the origin server. โœจ

If the Request-URI doesn't point to an existing resource, and the requesting user agent can define that URI as a new resource, the origin server can create it. ๐ŸŒธ When a new resource is created, the origin server MUST tell the user agent with a 201 (Created) response. If an existing resource gets modified instead, either 200 (OK) or 204 (No Content) SHOULD be sent to say the request went through. ๐ŸŽ€

If the resource can't be created or modified at that Request-URI, an appropriate error response SHOULD be given, one that reflects what went wrong. ๐Ÿ˜ญ And the recipient of the entity MUST NOT ignore any Content-* headers (like Content-Range) that it doesn't understand or implement. In that case it MUST return a 501 (Not Implemented) response. ๐Ÿ’€ No ignoring headers, bestie!

If the request goes through a cache and the Request-URI identifies one or more currently cached entities, those entries should be treated as stale. ๐ŸงŠ Responses to this method are not cachable.

Here's the big difference between POST and PUT, and it's all about the Request-URI. ๐Ÿ‘‘ In a POST, the URI identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. ๐Ÿ”ฅ In a PUT, the URI identifies the entity enclosed with the request. The user agent knows exactly what URI it means, so the server MUST NOT try to apply the request to some other resource. ๐Ÿšซ If the server wants the request applied to a different URI, it MUST send a 301 (Moved Permanently) response. The user agent MAY then decide for itself whether or not to redirect the request. ๐Ÿฆ‹

A single resource MAY be identified by many different URIs. ๐ŸŒˆ For example, an article might have one URI for "the current version" and a separate URI for each particular version. In that case, a PUT on a general URI may result in several other URIs being defined by the origin server. ๐Ÿงš

HTTP/1.1 doesn't define how a PUT method affects the state of an origin server. ๐Ÿคทโ€โ™€๏ธ

PUT requests must obey the message transmission requirements set out in section 8.2. ๐Ÿ’œ


9.7 DELETE

DELETE is the "please get rid of this resource" method. ๐Ÿ—‘๏ธ It requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. ๐Ÿ™ˆ The client can't be guaranteed that the operation was actually carried out, even if the status code says it completed successfully. ๐Ÿ˜ฌ Still, the server SHOULD NOT indicate success unless, at the time it responds, it intends to delete the resource or move it somewhere inaccessible. ๐Ÿ’…

A successful response SHOULD be 200 (OK) if it includes an entity describing the status. It SHOULD be 202 (Accepted) if the action hasn't been enacted yet, or 204 (No Content) if the response is OK but has no entity. โœจ

If the request goes through a cache and the Request-URI identifies one or more currently cached entities, those entries should be treated as stale. ๐ŸงŠ Responses to this method are not cachable.


9.8 TRACE

TRACE is basically a remote, application-layer loop-back of the request message. ๐Ÿชž The final recipient SHOULD reflect the message it received back to the client as the entity-body of a 200 (OK) response. The final recipient is either the origin server, or the first proxy or gateway to receive a Max-Forwards value of zero (0) in the request (see section 14.31). ๐Ÿ” A TRACE request MUST NOT include an entity. ๐Ÿšซ

TRACE lets the client see what's arriving at the other end of the request chain, and use that info for testing or diagnostics. ๐Ÿงช The Via header field (section 14.44) is especially iconic here, because it acts as a trace of the request chain. ๐Ÿ‘€ The Max-Forwards header field lets the client limit how long the request chain can get, which is handy for testing a chain of proxies that's forwarding messages in an infinite loop. ๐Ÿ”

If it succeeds, the response SHOULD contain the entire request message in the entity-body, with a Content-Type of message/http. ๐Ÿ’Œ Responses to this method MUST NOT be cached. ๐Ÿ™…โ€โ™€๏ธ


10 Status Code Definitions โœจ

Every Status-Code gets described below, including which method(s) it can follow and any metainformation the response needs. ๐Ÿ“‹ Let's go, bestie! ๐Ÿš€

10.1 Informational 1xx

This class of status code is for a provisional response. It only has the Status-Line and optional headers, and it ends with an empty line. ๐ŸŒ™ HTTP/1.0 didn't define any 1xx status codes, so servers MUST NOT send a 1xx response to an HTTP/1.0 client, except under experimental conditions. ๐Ÿงช Don't do it, babe!

10.1.1 100 Continue

The client may continue with its request. ๐ŸŒธ This interim response tells the client that the initial part of the request has been received and hasn't been rejected by the server yet. โœ… The client SHOULD continue by sending the rest of the request. If the request is already complete, it can ignore this response. ๐Ÿ™ˆ The server MUST send a final response once the request has been completed. ๐Ÿ’ฏ

10.1.2 101 Switching Protocols

Here the server understands the client's request and is willing to comply with it, via the Upgrade message header field (section 14.41). ๐Ÿฆ‹ It's a change in the application protocol being used on this connection. The server switches to the protocols named in the response's Upgrade header field immediately after the empty line that ends the 101 response. ๐Ÿ”€

Only switch protocols when it's actually worth it! โœจ Switching to a newer version of HTTP is advantageous over older versions, and switching to a real-time, synchronous protocol may be advantageous when delivering resources that use those features. ๐ŸŽ€

10.2 Successful 2xx

This class of status code means the client's request was successfully received, understood, and accepted. ๐Ÿฅณ Yasss! ๐Ÿ‘‘

10.2.1 200 OK

The request has succeeded. ๐ŸŽ‰ What comes back depends on the method used in the request. For example:

  • GET: an entity corresponding to the requested resource is sent in the response ๐Ÿ“ฆ
  • HEAD: the entity-header fields corresponding to the requested resource are sent in the response without any message-body ๐Ÿงพ
  • POST: an entity describing or containing the result of the action ๐Ÿ“
  • TRACE: an entity containing the request message as received by the end server ๐Ÿชž

10.2.2 201 Created

The request has been fulfilled and a new resource was created. ๐ŸŒŸ The new resource can be referenced by the URI(s) returned in the response entity, and the most specific URL for it is given by a Location header field. ๐Ÿ“ The origin server MUST create the resource before it returns the 201 status code. โš ๏ธ If the action can't be carried out immediately, the server should respond with 202 (Accepted) instead. โณ

10.2.3 202 Accepted

The request has been accepted for processing, but the processing hasn't been completed yet. โฐ The request MAY or MAY NOT eventually be acted upon, since it MAY be disallowed when processing actually happens. ๐Ÿคทโ€โ™€๏ธ There's no way to re-send a status code from an asynchronous operation like this. ๐Ÿ˜…

The 202 response is intentionally non-committal. ๐Ÿซถ Its purpose is to let a server accept a request for some other process (maybe a batch job that only runs once a day) without making the user agent's connection stay open until that process finishes. ๐ŸŒ™ The entity returned with this response SHOULD include an indication of the request's current status, plus either a pointer to a status monitor or an estimate of when the user can expect the request to be fulfilled. ๐Ÿ“Š

10.2.4 203 Non-Authoritative Information

The metainformation in the returned entity-header isn't the definitive set from the origin server. It was gathered from a local or third-party copy instead. ๐Ÿงณ The set presented MAY be a subset or a superset of the original version. For example, including local annotation info about the resource MAY result in a superset of the metainformation the origin server knows. ๐Ÿ“š Using this response code isn't required, and it's only appropriate when the response would otherwise have been 200 (OK). ๐Ÿ™‚

10.2.5 204 No Content

The server has fulfilled the request, but there's no new information to send back. ๐Ÿซฅ If the client is a user agent, it SHOULD NOT change its document view from the one that caused the request to be sent. ๐ŸชŸ This response is mainly meant to let input for actions take place without changing the user agent's active document view. โœจ The response MAY include new metainformation in the form of entity-headers, which SHOULD apply to the document currently in the user agent's active view. ๐ŸŽ€

The 204 response MUST NOT include a message-body, so it always ends at the first empty line after the header fields. ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’…

10.2.6 205 Reset Content

Okay bestie, so the server has fulfilled the request and the user agent SHOULD reset the document view that sent the request ๐Ÿงนโœจ This response is mainly there so you can type in some input, and then the form gets cleared so you can easily start another input action ๐Ÿ’… The response MUST NOT include an entity ๐Ÿ™…โ€โ™€๏ธ

10.2.7 206 Partial Content

Okay this one is giving partial vibes ๐Ÿฆ‹ The server has fulfilled the partial GET request for the resource. The request must have included a Range header field (section 14.36) indicating the desired range ๐ŸŽ€ The response MUST include either a Content-Range header field (section 14.17) indicating the range included with this response, or a multipart/byteranges Content-Type including Content-Range fields for each part ๐ŸŒˆ If multipart/byteranges is not used, the Content-Length header field in the response MUST match the actual number of OCTETs transmitted in the message-body ๐Ÿ”ข

A cache that does not support the Range and Content-Range headers MUST NOT cache 206 (Partial) responses ๐Ÿ™ˆ No cap, that one is a hard rule ๐Ÿ’€

10.3 Redirection 3xx

Redirection is the class where the user agent has to go do more stuff to finish the request ๐Ÿงญ The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD ๐ŸŒธ A user agent SHOULD NOT automatically redirect a request more than 5 times, since such redirections usually indicate an infinite loop ๐Ÿ”๐Ÿ˜ญ

10.3.1 300 Multiple Choices

The requested resource matches any one of a set of representations, each with its own specific location ๐ŸŒท Agent-driven negotiation information (section 12) is provided so the user (or user agent) can pick a preferred representation and redirect the request to that location ๐Ÿ’œ

Unless it was a HEAD request, the response SHOULD include an entity containing a list of resource characteristics and locations the user or user agent can choose from, picking the one that's most appropriate ๐Ÿ“‹ The entity format is specified by the media type in the Content-Type header field ๐ŸŽ€ Depending on the format and the user agent's capabilities, the selection may be done automatically ๐Ÿค– However, this specification does not define any standard for that automatic selection ๐Ÿ™…โ€โ™€๏ธ

If the server has a preferred choice of representation, it SHOULD include the specific URL for that representation in the Location field, and user agents MAY use the Location field value for automatic redirection ๐Ÿงš This response is cachable unless indicated otherwise ๐Ÿ“

10.3.2 301 Moved Permanently

The requested resource has a new permanent URI now ๐Ÿ โœจ Future references SHOULD use one of the returned URIs ๐Ÿ”— Clients with link editing capabilities SHOULD automatically re-link references to the Request-URI to one or more of the new references the server returns, where possible ๐Ÿช„ This response is cachable unless indicated otherwise ๐Ÿ’พ

If the new URI is a location, its URL SHOULD be given by the Location field in the response ๐Ÿ“ Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s) ๐ŸŒ

If a 301 status code comes back for a request that isn't GET or HEAD, the user agent MUST NOT automatically redirect the request unless the user confirms it ๐Ÿ›‘ That's because it might change the conditions under which the request was issued ๐Ÿ˜ฌ

Note: When automatically redirecting a POST request after receiving a 301 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request. ๐Ÿซฃ

10.3.3 302 Moved Temporarily

The requested resource is temporarily living under a different URI ๐ŸŒค๏ธ Since the redirection may change on occasion, the client SHOULD keep using the Request-URI for future requests ๐Ÿ”„ This response is only cachable if a Cache-Control or Expires header field says so ๐Ÿ“…

If the new URI is a location, its URL SHOULD be given by the Location field in the response ๐Ÿ“ Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s) ๐ŸŒ

If a 302 status code comes back for a request that isn't GET or HEAD, the user agent MUST NOT automatically redirect the request unless the user confirms it ๐Ÿ›‘ That's because it might change the conditions under which the request was issued ๐Ÿ˜ฌ

Note: When automatically redirecting a POST request after receiving a 302 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request. ๐Ÿซฃ

10.3.4 303 See Other

The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource ๐Ÿ‘€ This one mostly exists so a POST-activated script can send the user agent over to a selected resource ๐ŸŽฏ The new URI is not a substitute reference for the originally requested resource ๐Ÿ™…โ€โ™€๏ธ The 303 response is not cachable, but the response to the second (redirected) request MAY be cachable ๐Ÿ’…

If the new URI is a location, its URL SHOULD be given by the Location field in the response ๐Ÿ“ Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s) ๐ŸŒ

10.3.5 304 Not Modified

If the client sent a conditional GET request and access is allowed, but the document hasn't changed, the server SHOULD respond with this status code ๐Ÿฅฑ The response MUST NOT contain a message-body ๐Ÿšซ

The response MUST include the following header fields:

  • Date
  • ETag and/or Content-Location, if the header would have been sent in a 200 response to the same request
  • Expires, Cache-Control, and/or Vary, if the field-value might differ from that sent in any previous response for the same variant

If the conditional GET used a strong cache validator (see section 13.3.3), the response SHOULD NOT include other entity-headers ๐Ÿ’ช Otherwise (the conditional GET used a weak validator), the response MUST NOT include other entity-headers, which prevents inconsistencies between cached entity-bodies and updated headers ๐Ÿงฉ

If a 304 response shows up for an entity that isn't currently cached, the cache MUST disregard the response and repeat the request without the conditional ๐Ÿ” If a cache uses a received 304 response to update a cache entry, the cache MUST update the entry to reflect any new field values given in the response ๐Ÿ“

The 304 response MUST NOT include a message-body, so it always ends at the first empty line after the header fields ๐Ÿ

10.3.6 305 Use Proxy

The requested resource MUST be accessed through the proxy given by the Location field ๐Ÿšช The Location field gives the URL of the proxy ๐Ÿ—บ๏ธ The recipient is expected to repeat the request via the proxy ๐Ÿ”

10.4 Client Error 4xx

The 4xx class is for when the client seems to have messed up ๐Ÿ™ˆ Except when responding to a HEAD request, the server SHOULD include an entity explaining the error, and whether it's a temporary or permanent condition ๐Ÿ“ These status codes apply to any request method ๐ŸŒ User agents SHOULD display any included entity to the user ๐Ÿ‘€

Note: If the client is sending data, a server implementation using TCP should be careful to ensure that the client acknowledges receipt of the packet(s) containing the response, before the server closes the input connection. If the client continues sending data to the server after the close, the server's TCP stack will send a reset packet to the client, which may erase the client's unacknowledged input buffers before they can be read and interpreted by the HTTP application. ๐Ÿ˜ฑ

10.4.1 400 Bad Request

The server couldn't understand the request because the syntax is malformed ๐Ÿคทโ€โ™€๏ธ The client SHOULD NOT repeat the request without modifications ๐Ÿšซ

10.4.2 401 Unauthorized

The request needs user authentication ๐Ÿ” The response MUST include a WWW-Authenticate header field (section 14.46) containing a challenge that applies to the requested resource ๐ŸŽซ The client MAY repeat the request with a suitable Authorization header field (section 14.8) ๐Ÿ”‘ If the request already included Authorization credentials, the 401 response means authorization was refused for those credentials ๐Ÿ™…โ€โ™€๏ธ If the 401 response has the same challenge as the prior response, and the user agent already tried authentication at least once, then the user SHOULD be shown the entity given in the response, since it MAY include useful diagnostic info ๐Ÿฉบ HTTP access authentication is explained in section 11 ๐Ÿ“–

10.4.3 402 Payment Required

This code is reserved for future use ๐Ÿ”ฎ

10.4.4 403 Forbidden

The server understood the request but is refusing to fulfill it ๐Ÿ›‘ Authorization won't help, and the request SHOULD NOT be repeated ๐Ÿ™…โ€โ™€๏ธ If the request method was not HEAD and the server wants to make public why the request wasn't fulfilled, it SHOULD describe the reason for the refusal in the entity ๐Ÿ“ฃ This status code is commonly used when the server doesn't want to reveal exactly why the request was refused, or when no other response fits ๐Ÿค

10.4.5 404 Not Found

The server hasn't found anything matching the Request-URI ๐Ÿ” No indication is given of whether the condition is temporary or permanent ๐Ÿค”

If the server doesn't want to share this info with the client, the status code 403 (Forbidden) can be used instead ๐Ÿ™ˆ The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address ๐Ÿชฆ

10.4.6 405 Method Not Allowed

The method in the Request-Line isn't allowed for the resource identified by the Request-URI ๐Ÿšท The response MUST include an Allow header containing a list of valid methods for the requested resource ๐Ÿ“œ

10.4.7 406 Not Acceptable

The resource identified by the request can only generate response entities with content characteristics that aren't acceptable according to the accept headers sent in the request ๐Ÿ˜ฌ

Unless it was a HEAD request, the response SHOULD include an entity containing a list of available entity characteristics and locations the user or user agent can choose from, picking the most appropriate one ๐Ÿ“‹ The entity format is specified by the media type in the Content-Type header field ๐ŸŽ€ Depending on the format and the user agent's capabilities, the selection may be done automatically ๐Ÿค– However, this specification does not define any standard for that automatic selection ๐Ÿ™…โ€โ™€๏ธ

Note: HTTP/1.1 servers are allowed to return responses that aren't acceptable according to the accept headers sent in the request. In some cases, this may even be preferable to sending a 406 response. User agents are encouraged to inspect the headers of an incoming response to determine if it is acceptable. If the response could be unacceptable, a user agent SHOULD temporarily stop receipt of more data and query the user for a decision on further actions. ๐Ÿง๐Ÿ’–

10.4.8 407 Proxy Authentication Required ๐ŸŽ€

okay bestie, 407 is basically the 401's cousin, but this one is for the proxy ๐Ÿงš. The client MUST first authenticate itself with the proxy ๐Ÿ’…, so no sneaking past the bouncer. The proxy MUST return a Proxy-Authenticate header field (section 14.33) with a challenge that applies to the proxy for the requested resource ๐Ÿ”’. Then the client MAY repeat the request with a suitable Proxy-Authorization header field (section 14.34). HTTP access authentication is explained in section 11 โœจ, so scroll down, it's giving.

10.4.9 408 Request Timeout โฐ

the client took too long to send its request, and the server got tired of waiting ๐Ÿ™„. The client MAY repeat the request without modifications at any later time ๐ŸŒธ.

10.4.10 409 Conflict ๐Ÿ˜ฌ

the request couldn't be completed because it clashes with the resource's current state. This code is only allowed when the user might actually be able to sort out the conflict and resubmit the request. The response body SHOULD include enough info for the user to recognize where the conflict came from ๐Ÿ”. Ideally the response would have enough detail for the user or user agent to fix the problem, but that may not be possible, and it's not required ๐Ÿซถ.

Conflicts usually pop up with PUT requests ๐Ÿ™ˆ. If versioning is in play and the entity being PUT has changes that clash with an earlier (third-party) request, the server MAY use the 409 to say it can't finish the request. In that case the response entity SHOULD contain a list of the differences between the two versions, in a format defined by the response Content-Type ๐Ÿ“‹.

10.4.11 410 Gone ๐Ÿ’€

the resource isn't available on the server anymore, and no forwarding address is known. This condition SHOULD be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. If the server doesn't know, or has no way to figure out, whether the condition is permanent, 404 (Not Found) SHOULD be used instead. This response is cachable unless indicated otherwise ๐Ÿ—‚๏ธ.

The 410 is mainly there to help with web maintenance. It tells the recipient that the resource is gone on purpose and that the server owners want remote links to it removed ๐Ÿงน. This is super common for limited-time promos and for stuff belonging to people who've left the team at the server's site. You don't have to mark every permanently unavailable resource as "gone", and you don't have to keep the mark forever. That's up to the server owner ๐Ÿ‘‘.

10.4.12 411 Length Required ๐Ÿ“

the server won't accept the request without a defined Content-Length. The client MAY repeat the request if it adds a valid Content-Length header field containing the length of the message-body in the request message ๐Ÿ’–.

10.4.13 412 Precondition Failed ๐Ÿ™…

the precondition in one or more of the request-header fields evaluated to false when the server tested it. This lets the client put preconditions on the current resource metainformation (header field data), so the requested method can't accidentally hit a resource other than the one intended ๐ŸŽฏ.

10.4.14 413 Request Entity Too Large ๐Ÿ“ฆ

the server is refusing to process the request because the request entity is bigger than the server is willing or able to handle. It may close the connection to stop the client from continuing ๐Ÿšช.

If the condition is temporary, the server SHOULD include a Retry-After header field to say it's temporary and after what time the client can try again โณ.

10.4.15 414 Request-URI Too Long ๐ŸŒ€

the server is refusing to service the request because the Request-URI is longer than the server is willing to interpret. This is a rare one, and it usually happens when a client wrongly turned a POST into a GET with long query info, when the client fell into a URL "black hole" of redirection (e.g., a redirected URL prefix that points to a suffix of itself), or when the server is under attack from a client trying to exploit security holes in servers that use fixed-length buffers for reading or manipulating the Request-URI ๐Ÿšจ. Scary stuff, bestie.

10.4.16 415 Unsupported Media Type ๐ŸŽž๏ธ

the server is refusing to service the request because the request's entity is in a format the requested resource doesn't support for the requested method ๐Ÿ™ƒ.

10.5 Server Error 5xx ๐Ÿ˜ญ

Status codes starting with the digit "5" mean the server knows it messed up, or it can't perform the request at all. Except when responding to a HEAD request, the server SHOULD include an entity explaining the error and whether it's a temporary or permanent condition. User agents SHOULD display any included entity to the user. These codes apply to any request method ๐ŸŒˆ.

10.5.1 500 Internal Server Error ๐Ÿ’ฅ

the server ran into an unexpected condition that stopped it from fulfilling the request.

10.5.2 501 Not Implemented ๐Ÿคท

the server doesn't support the functionality the request needs. This is the right response when the server doesn't recognize the request method and can't support it for any resource.

10.5.3 502 Bad Gateway ๐ŸŒ‰

while acting as a gateway or proxy, the server got an invalid response from the upstream server it contacted while trying to fulfill the request.

10.5.4 503 Service Unavailable ๐Ÿ› ๏ธ

the server can't handle the request right now because it's temporarily overloaded or under maintenance. That means the situation is temporary and should get better after some delay. If the delay is known, it may be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response the same way it would handle a 500 response.

Note: Having the 503 status code doesn't mean a server must use it when it gets overloaded. Some servers may just prefer to refuse the connection outright ๐Ÿ™…โ€โ™€๏ธ.

10.5.5 504 Gateway Timeout โณ

while acting as a gateway or proxy, the server didn't get a timely response from the upstream server it contacted to complete the request.

10.5.6 505 HTTP Version Not Supported ๐Ÿ“œ

the server doesn't support, or won't support, the HTTP protocol version used in the request message. It's saying it's unable or unwilling to complete the request using the same major version as the client, as described in section 3.1, and is sending this error message instead. The response SHOULD contain an entity explaining why that version isn't supported and which other protocols that server does support.

11 Access Authentication ๐Ÿ”

HTTP has a simple challenge-response authentication mechanism which MAY be used by a server to challenge a client request, and by a client to provide authentication information. It uses an extensible, case-insensitive token to name the authentication scheme, followed by a comma-separated list of attribute-value pairs that carry the parameters needed to achieve authentication via that scheme ๐ŸŽ€.

          auth-scheme    = token

          auth-param     = token "=" quoted-string

The 401 (Unauthorized) response is used by an origin server to challenge the authorization of a user agent. This response MUST include a WWW-Authenticate header field containing at least one challenge applicable to the requested resource ๐Ÿชช.

          challenge      = auth-scheme 1*SP realm *( "," auth-param )

          realm          = "realm" "=" realm-value
          realm-value    = quoted-string

The realm attribute (case-insensitive) is required for all authentication schemes that issue a challenge. The realm value (case-sensitive), combined with the canonical root URL (see section 5.1.2) of the server being accessed, defines the protection space ๐Ÿฐ. Realms let the protected resources on a server be split into a set of protection spaces, each with its own authentication scheme and/or authorization database. The realm value is a string, usually assigned by the origin server, and it may have extra semantics specific to the authentication scheme ๐Ÿ’œ.

A user agent that wants to authenticate itself with a server (usually, but not necessarily, after getting a 401 or 411 response) MAY do so by including an Authorization header field with the request. The Authorization field value holds credentials containing the user agent's authentication info for the realm of the requested resource โœจ.

          credentials    = basic-credentials
                         | auth-scheme #auth-param

The domain over which a user agent can automatically apply credentials is set by the protection space. If a prior request was authorized, the same credentials MAY be reused for all other requests within that protection space, for a period determined by the authentication scheme, its parameters, and/or user preference. Unless the authentication scheme defines otherwise, a single protection space can't extend outside the scope of its server ๐Ÿšง.

If the server doesn't want to accept the credentials sent with a request, it SHOULD return a 401 (Unauthorized) response. The response MUST include a WWW-Authenticate header field containing the (possibly new) challenge applicable to the requested resource, along with an entity explaining the refusal ๐Ÿ™…โ€โ™€๏ธ.

HTTP doesn't limit apps to this simple challenge-response mechanism for access authentication. Additional mechanisms MAY be used, such as encryption at the transport level or via message encapsulation, and with additional header fields specifying authentication information. However, these additional mechanisms are not defined by this specification ๐ŸŒŸ.

Proxies MUST be completely transparent regarding user agent authentication. That is, they MUST forward the WWW-Authenticate and Authorization headers untouched, and follow the rules found in section 14.8 ๐Ÿซถ.

HTTP/1.1 lets a client pass authentication information to and from a proxy via the Proxy-Authenticate and Proxy-Authorization headers ๐Ÿ“.

11.1. Basic Authentication Scheme ๐Ÿ”

okay so the "basic" scheme is built on a super simple idea: the user agent has to prove who it is with a user-ID and a password for each realm ๐ŸŽ€ The realm is an opaque string, which means you can only check whether two realms are equal. No peeking inside ๐Ÿซถ The server only services the request if it can validate the user-ID and password for the protection space of the Request-URI. And there are no optional authentication parameters, so no extra knobs here ๐Ÿ’…

When an unauthorized request comes in for a URI inside the protection space, the server MAY respond with a challenge that looks like this:

WWW-Authenticate: Basic realm="WallyWorld"

where "WallyWorld" is the string the server assigned to identify the protection space of the Request-URI ๐ŸŒธ

To get authorization, the client sends the userid and password, separated by a single colon (":") character, inside a base64 encoded string in the credentials ๐Ÿงš

basic-credentials = "Basic" SP basic-cookie

basic-cookie   = <base64 [7] encoding of user-pass,
                 except not limited to 76 char/line>

user-pass   = userid ":" password

userid      = *<TEXT excluding ":">

password    = *TEXT

Userids might be case sensitive ๐Ÿ‘€

If the user agent wishes to send the userid "Aladdin" and password "open sesame", it would use the following header field:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
See section 15 for security considerations associated with Basic authentication. Section 15 is where the security considerations for Basic auth live, and they are seriously important, bestie ๐Ÿ’€

11.2. Digest Authentication Scheme ๐Ÿ“

A digest authentication for HTTP is specified in RFC 2069 [32].


12. Content Negotiation โœจ

okay so most HTTP responses include an entity with information meant to be read by a human user ๐Ÿ“– Naturally, you want to give the user the "best available" entity for their request. The tea is that servers and caches can't always tell what "best" means, because not every user has the same preferences, and not every user agent can render every entity type ๐Ÿ˜ญ That's why HTTP has several mechanisms for "content negotiation": the process of picking the best representation for a given response when there are multiple representations available ๐Ÿฆ‹

Note: This is not called "format negotiation" because the alternate representations may be of the same media type, but use different capabilities of that type, be in different languages, etc.

Any response containing an entity-body MAY be subject to negotiation, including error responses ๐Ÿ’–

There are two kinds of content negotiation possible in HTTP: server-driven and agent-driven negotiation. They're orthogonal, so you can use them separately or together โœจ One combo, called transparent negotiation, happens when a cache uses the agent-driven negotiation information from the origin server to provide server-driven negotiation for later requests ๐Ÿ”ฅ

12.1. Server-driven Negotiation ๐Ÿ‘‘

If the selection of the best representation for a response is made by an algorithm at the server, it's called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary, e.g. language, content-coding, etc.) and on the contents of particular header fields in the request message, or on other information about the request (such as the network address of the client) ๐ŸŒˆ

Server-driven negotiation is a win when the algorithm for choosing among the representations is hard to describe to the user agent, or when the server wants to send its "best guess" along with the first response. That way it can skip the round-trip delay of a follow-up request, if the "best guess" is good enough for the user. To improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) that describe its preferences for such a response ๐Ÿ“

Server-driven negotiation has disadvantages, though ๐Ÿ™ˆ

  1. It is impossible for the server to accurately determine what might be "best" for any given user, since that would require complete knowledge of both the capabilities of the user agent and the intended use for the response (e.g., does the user want to view it on screen or print it on paper?).
  2. Having the user agent describe its capabilities in every request can be both very inefficient (given that only a small percentage of responses have multiple representations) and a potential violation of the user's privacy.
  3. It complicates the implementation of an origin server and the algorithms for generating responses to a request.
  4. It may limit a public cache's ability to use the same response for multiple user's requests.

HTTP/1.1 includes the following request-header fields for enabling server-driven negotiation through description of user agent capabilities and user preferences: Accept (section 14.1), Accept-Charset (section 14.2), Accept-Encoding (section 14.3), Accept-Language (section 14.4), and User-Agent (section 14.42). However, an origin server is not limited to these dimensions and MAY vary the response based on any aspect of the request, including information outside the request-header fields or within extension header fields not defined by this specification ๐Ÿง 

HTTP/1.1 origin servers MUST include an appropriate Vary header field (section 14.43) in any cachable response based on server-driven negotiation. The Vary header field describes the dimensions over which the response might vary (i.e. the dimensions over which the origin server picks its "best guess" response from multiple representations) ๐Ÿ’…

HTTP/1.1 public caches MUST recognize the Vary header field when it is included in a response, and obey the requirements described in section 13.6, which covers the interactions between caching and content negotiation ๐Ÿซถ

12.2. Agent-driven Negotiation ๐Ÿฆ‹

With agent-driven negotiation, the user agent does the selecting of the best representation after it gets an initial response from the origin server. Selection is based on a list of the available representations of the response, included within the header fields (this specification reserves the field-name Alternates, as described in appendix 19.6.2.1) or the entity-body of the initial response, with each representation identified by its own URI. Selection may be performed automatically (if the user agent is capable of doing so) or manually, with the user picking from a generated (possibly hypertext) menu ๐ŸŽ€

Agent-driven negotiation is a great fit when the response would vary over commonly-used dimensions (such as type, language, or encoding), when the origin server can't figure out a user agent's capabilities from the request, and generally when public caches are used to spread out server load and reduce network usage โœจ

Agent-driven negotiation has one main downside: it needs a second request to get the best alternate representation. That second request is only efficient when caching is used. Also, this specification doesn't define any mechanism for automatic selection, though it also doesn't prevent one from being developed as an extension and used within HTTP/1.1 ๐ŸŒธ

HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable) status codes for enabling agent-driven negotiation when the server is unwilling or unable to provide a varying response using server-driven negotiation ๐Ÿ“

12.3. Transparent Negotiation ๐Ÿงš

Transparent negotiation is a combo of server-driven and agent-driven negotiation. When a cache gets a form of the list of available representations (like in agent-driven negotiation) and the cache completely understands the dimensions of variance, the cache can do server-driven negotiation on behalf of the origin server for later requests on that resource ๐Ÿ”ฅ

Transparent negotiation is a big win because it spreads out the negotiation work that would otherwise fall on the origin server, and it removes the second-request delay of agent-driven negotiation when the cache correctly guesses the right response ๐Ÿ’–

This specification doesn't define any mechanism for transparent negotiation, though it also doesn't prevent one from being developed as an extension and used within HTTP/1.1. An HTTP/1.1 cache performing transparent negotiation MUST include a Vary header field in the response (defining the dimensions of its variance) if it is cachable, to make sure it interoperates correctly with all HTTP/1.1 clients. The agent-driven negotiation information supplied by the origin server SHOULD be included with the transparently negotiated response ๐ŸŽ€

13. Caching in HTTP โœจ

okay bestie, HTTP is typically used for distributed information systems ๐ŸŒ, and performance can be seriously improved with response caches ๐Ÿ’–. HTTP/1.1 has a bunch of built-in elements to make caching work as well as possible ๐Ÿ’…. They're inextricable from the rest of the protocol (they're stuck together ๐Ÿซถ) and they interact with each other, so it's useful to explain the basic caching design separately from the detailed stuff on methods, headers, response codes, etc.

Caching would be useless if it didn't actually boost performance ๐Ÿ˜ญ. The goal in HTTP/1.1 is to skip sending requests in lots of cases, and to skip sending full responses in lots of other cases. The first one cuts down on network round-trips for many operations, and we use an "expiration" mechanism for it (see section 13.2) ๐Ÿฆ‹. The second one saves network bandwidth, and we use a "validation" mechanism for that (see section 13.3) ๐Ÿ’œ.

Performance, availability, and disconnected operation all need us to be able to relax semantic transparency a little ๐ŸŒธ. HTTP/1.1 lets origin servers, caches, and clients explicitly reduce transparency when they have to. BUT non-transparent operation can confuse non-expert users, and it can clash with certain server applications (like the ones for ordering merchandise ๐Ÿ›๏ธ), so the protocol requires that transparency be relaxed:

  • only by an explicit protocol-level request when relaxed by client or origin server
  • only with an explicit warning to the end user when relaxed by cache or client

So HTTP/1.1 gives us these important elements:

  1. Protocol features that provide full semantic transparency when all parties need it.
  2. Protocol features that let an origin server or user agent explicitly request and control non-transparent operation.
  3. Protocol features that let a cache attach warnings to responses that don't preserve the requested approximation of semantic transparency.

The big principle here is that clients need to be able to detect any potential relaxation of semantic transparency ๐Ÿ‘€.

Note: The server, cache, or client implementer may run into design decisions that this specification doesn't explicitly cover ๐Ÿค“. If a decision might affect semantic transparency, the implementer ought to err on the side of keeping transparency, unless a careful and complete analysis shows significant benefits in breaking it.

13.1.1 Cache Correctness

A correct cache MUST respond to a request with the most up-to-date response it holds that is appropriate to the request (see sections 13.2.5, 13.2.6, and 13.12) and that meets one of the following conditions ๐ŸŽ€:

  1. It has been checked for equivalence with what the origin server would have returned, by revalidating the response with the origin server (section 13.3);
  2. It is "fresh enough" (see section 13.2). In the default case, this means it meets the least restrictive freshness requirement of the client, server, and cache (see section 14.9). If the origin server specifies so, it's the origin server's freshness requirement alone ๐Ÿ‘‘;
  3. It includes a warning if the freshness demand of the client or the origin server is violated (see section 13.1.5 and 14.45);
  4. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect), or error (4xx or 5xx) response message.

If the cache can't communicate with the origin server, then a correct cache SHOULD respond as above, as long as the response can be correctly served from the cache. If it can't do that, it MUST return an error or a warning saying there was a communication failure ๐Ÿ™ˆ.

If a cache gets a response (either a whole response or a 304 (Not Modified) response) that it would normally forward to the requesting client, and that response is no longer fresh, the cache SHOULD forward it anyway without adding a new Warning (but it also shouldn't remove any Warning headers that are already there) ๐Ÿซ . A cache SHOULD NOT try to revalidate a response just because it went stale in transit, because that could lead to an infinite loop ๐Ÿ’€. A user agent that gets a stale response without a Warning MAY show a warning indication to the user โœจ.

13.1.2 Warnings

Whenever a cache returns a response that is neither first-hand nor "fresh enough" (in the sense of condition 2 in section 13.1.1), it must attach a warning to that effect, using a Warning response-header. This warning lets clients take appropriate action ๐Ÿšจ.

Warnings can be used for other purposes too, both cache-related and not. Using a warning instead of an error status code is what tells these responses apart from true failures ๐Ÿฆ‹.

Warnings are always cacheable, because they never weaken the transparency of a response. That means warnings can be passed to HTTP/1.0 caches safely, and those caches will just pass the warning along as an entity-header in the response ๐Ÿ’….

Warnings are assigned numbers between 0 and 99. This specification defines the code numbers and meanings of each currently assigned warning, so a client or cache can take automated action in some (but not all) cases ๐Ÿค–.

Warnings also carry a warning text. The text can be in any appropriate natural language (maybe based on the client's Accept headers), and it can include an optional indication of what character set is used ๐ŸŒ.

Multiple warnings can be attached to a response, either by the origin server or by a cache, including several with the same code number. For example, a server might send the same warning with texts in both English and Basque ๐ŸŒธ.

When there are multiple warnings on a response, showing all of them to the user might not be practical or reasonable ๐Ÿ˜ฉ. This version of HTTP doesn't set strict priority rules for deciding which warnings to display and in what order, but it does suggest some heuristics ๐Ÿงš.

The Warning header and the currently defined warnings are described in section 14.45.

13.1.3 Cache-control Mechanisms

The basic cache mechanisms in HTTP/1.1 (server-specified expiration times and validators) act as implicit directives to caches. Sometimes a server or client needs to give the HTTP caches explicit directives, and that's what the Cache-Control header is for ๐Ÿ’œ.

The Cache-Control header lets a client or server send a variety of directives in either requests or responses. These directives typically override the default caching algorithms. As a general rule, if there's any apparent conflict between header values, the most restrictive interpretation should be applied (meaning the one most likely to preserve semantic transparency) ๐Ÿ”’. BUT in some cases, Cache-Control directives are explicitly specified as weakening the approximation of semantic transparency (for example, "max-stale" or "public") ๐Ÿ™ƒ.

The Cache-Control directives are described in detail in section 14.9 ๐ŸŽ€.

13.1.4 Explicit User Agent Warnings

Lots of user agents let users override the basic caching mechanisms. For example, a user agent might let someone say that cached entities (even explicitly stale ones) are never validated. Or a user agent might habitually add Cache-Control: max-stale=3600 to every request ๐Ÿ™ˆ. The user should have to explicitly ask for either non-transparent behavior or behavior that makes caching abnormally ineffective ๐Ÿซถ.

If the user has overridden the basic caching mechanisms, the user agent should explicitly tell the user whenever this results in showing information that might not meet the server's transparency requirements (especially if the displayed entity is known to be stale) ๐Ÿ‘€. Since the protocol normally lets the user agent figure out whether responses are stale, this indication only needs to appear when that actually happens โœจ. It doesn't have to be a dialog box. It could be an icon (like a picture of a rotting fish ๐ŸŸ) or some other visual indicator ๐Ÿ’€.

If the user has overridden the caching mechanisms in a way that would abnormally reduce the effectiveness of caches, the user agent should keep showing an indication (like a picture of currency in flames ๐Ÿ”ฅ๐Ÿ’ธ) the whole time, so the user doesn't accidentally eat up excess resources or suffer from excessive latency ๐Ÿ˜ญ.

13.1.5 Exceptions to the Rules and Warnings

Sometimes the operator of a cache might choose to configure it to return stale responses even when clients didn't ask for them ๐Ÿคจ. This shouldn't be decided lightly, but it may be necessary for reasons of availability or performance, especially when the cache is poorly connected to the origin server ๐ŸŒง๏ธ. Whenever a cache returns a stale response, it MUST mark it as such (using a Warning header). That lets the client software alert the user that there might be a potential problem ๐Ÿšฉ.

It also lets the user agent take steps to get a first-hand or fresh response. For this reason, a cache SHOULD NOT return a stale response if the client explicitly asks for a first-hand or fresh one, unless it's impossible to comply for technical or policy reasons ๐Ÿ™…โ€โ™€๏ธ.

13.1.6 Client-controlled Behavior

The origin server is the primary source of expiration information (and intermediate caches are a secondary source, through their contribution to the age of a response) ๐Ÿงš. But sometimes the client needs to control whether a cache returns a cached response without validating it ๐ŸŽ€. Clients do this using several directives of the Cache-Control header ๐Ÿ’….

A client's request can specify the maximum age it's willing to accept for an unvalidated response. Specifying a value of zero forces the cache(s) to revalidate all responses ๐Ÿ”. A client can also specify the minimum time remaining before a response expires. Both of these options add constraints on cache behavior, so they can't further relax the cache's approximation of semantic transparency ๐Ÿ”’.

A client can also say it will accept stale responses, up to some maximum amount of staleness. This loosens the constraints on caches, so it may break the origin server's specified constraints on semantic transparency, but it may be needed to support disconnected operation or high availability when connectivity is poor ๐Ÿ“ถ๐ŸŒˆ.

13.2. Expiration Model ๐Ÿ•ฐ๏ธ

13.2.1 Server-Specified Expiration ๐ŸŒธ

okay bestie, caches are at their absolute best when they never have to bug the origin server at all ๐Ÿ’… The main way to skip it is for the origin to hand over an explicit expiration time in the future, which basically says "yep, this response is good to reuse until then." So a cache can serve a fresh response without even asking the server first โœจ

Servers pick future expiration times because they believe the entity won't change in a semantically significant way before that time hits ๐Ÿฆ‹ When the server picks its times carefully, this keeps semantic transparency intact, and it's honestly so iconic.

The expiration mechanism only applies to responses taken from a cache. It does NOT apply to first-hand responses that get forwarded straight to the client who asked ๐Ÿ™ˆ

If an origin server wants to force a semantically transparent cache to validate every request, it can give an explicit expiration time in the past. That makes the response always stale, so the cache SHOULD validate it before using it for later requests. For a stricter way to force revalidation, check section 14.9.4 ๐Ÿ’œ

If an origin server wants to force any HTTP/1.1 cache, no matter how it's configured, to validate every request, it should use the "must-revalidate" Cache-Control directive (see section 14.9). Main character energy ๐Ÿ‘‘

Servers specify explicit expiration times using either the Expires header, or the max-age directive of the Cache-Control header.

An expiration time can't be used to make a user agent refresh its display or reload a resource. Its semantics only apply to caching mechanisms, and those only need to check a resource's expiration status when a new request for that resource is initiated. For the difference between caches and history mechanisms, see section 13.13 ๐ŸŽ€

13.2.2 Heuristic Expiration ๐Ÿงš

Since origin servers don't always give explicit expiration times, HTTP caches usually assign heuristic expiration times. They use algorithms that look at other header values (such as the Last-Modified time) to estimate a plausible expiration time ๐Ÿ“ The HTTP/1.1 spec doesn't provide specific algorithms, but it does impose worst-case constraints on their results.

Heuristic expiration times can compromise semantic transparency, so they should be used cautiously, and we really encourage origin servers to provide explicit expiration times as much as possible ๐Ÿซถ

13.2.3 Age Calculations ๐Ÿฆ‹

To know if a cached entry is fresh, a cache needs to know whether its age exceeds its freshness lifetime. We'll talk about calculating the lifetime in section 13.2.4. This section is about working out the age of a response or cache entry ๐Ÿ’–

In this discussion, "now" means "the current value of the clock at the host performing the calculation." Hosts that use HTTP, especially origin servers and caches, should use NTP [28] or some similar protocol to sync their clocks to a globally accurate time standard โฐ

HTTP/1.1 requires origin servers to send a Date header with every response, giving the time the response was generated. We use "date_value" to mean the value of the Date header, in a form that's good for arithmetic.

HTTP/1.1 uses the Age response-header to help pass age info between caches. The Age value is the sender's estimate of the amount of time since the response was generated at the origin server. For a cached response that's been revalidated with the origin server, the Age value is based on the time of revalidation, not the original response ๐Ÿ”ฅ

Basically, the Age value is the sum of the time the response has been sitting in each cache along the path from the origin server, plus the time it spent in transit on network paths ๐ŸŒˆ

We use "age_value" to mean the value of the Age header, in a form that's good for arithmetic.

A response's age can be calculated in two totally independent ways:

  1. now minus date_value, if the local clock is reasonably well synchronized to the origin server's clock. If the result is negative, the result is replaced by zero.
  2. age_value, if all of the caches along the response path implement HTTP/1.1.

Since we have two independent ways to compute a response's age when it's received, we can combine them like this:

corrected_received_age = max(now - date_value, age_value)

and as long as we have either nearly synchronized clocks or all-HTTP/1.1 paths, one gets a reliable (conservative) result ๐ŸŽฏ

Note that this correction is applied at each HTTP/1.1 cache along the path, so if there's an HTTP/1.0 cache in the path, the correct received age is still computed as long as the receiving cache's clock is nearly in sync. We don't need end-to-end clock synchronization (although it's good to have), and there's no explicit clock synchronization step ๐Ÿงš

Because of network-imposed delays, some significant interval can pass between the moment a server generates a response and the moment it's received at the next outbound cache or client. If uncorrected, this delay could result in improperly low ages ๐Ÿ™ˆ

The request that resulted in the returned Age value must have been initiated before that Age value was generated. So we can correct for network delays by recording the time the request was initiated. Then, when an Age value is received, it MUST be interpreted relative to the time the request was initiated, not the time the response was received. This algorithm results in conservative behavior no matter how much delay is experienced. So, we compute:

corrected_initial_age = corrected_received_age
                      + (now - request_time)

where "request_time" is the time (according to the local clock) when the request that elicited this response was sent ๐Ÿ’œ

Summary of the age calculation algorithm, when a cache receives a response:

/*
 * age_value
 *      is the value of Age: header received by the cache with
 *              this response.
 * date_value
 *      is the value of the origin server's Date: header
 * request_time
 *      is the (local) time when the cache made the request
 *              that resulted in this cached response
 * response_time
 *      is the (local) time when the cache received the
 *              response
 * now
 *      is the current (local) time
 */
apparent_age = max(0, response_time - date_value);
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time;
current_age   = corrected_initial_age + resident_time;

When a cache sends a response, it must add to the corrected_initial_age the amount of time the response was resident locally. It must then transmit this total age, using the Age header, to the next recipient cache ๐Ÿ“ฆ

Note that a client cannot reliably tell that a response is first-hand. But the presence of an Age header indicates that a response is definitely NOT first-hand. Also, if the Date in a response is earlier than the client's local request time, the response is probably not first-hand (in the absence of serious clock skew) ๐Ÿ•ต๏ธโ€โ™€๏ธ

13.2.4 Expiration Calculations ๐ŸŽ€

To decide whether a response is fresh or stale, we need to compare its freshness lifetime to its age. The age is calculated as described in section 13.2.3. This section explains how to calculate the freshness lifetime and how to tell if a response has expired. The values below can be represented in any form that's good for arithmetic ๐Ÿงฎ

"expires_value" is the value of the Expires header. "max_age_value" is the number of seconds carried by the max-age directive of the Cache-Control header in a response (see section 14.10.

The max-age directive takes priority over Expires. So if max-age is present in a response, the calculation is simply:

freshness_lifetime = max_age_value

Otherwise, if Expires is present in the response, the calculation is:

freshness_lifetime = expires_value - date_value

Neither of these calculations is vulnerable to clock skew, since all of the information comes from the origin server ๐ŸŒธ

If neither Expires nor Cache-Control: max-age appears in the response, and the response doesn't include other restrictions on caching, the cache MAY compute a freshness lifetime using a heuristic. If the value is greater than 24 hours, the cache must attach Warning 13 to any response whose age is more than 24 hours, if such a warning hasn't already been added โš ๏ธ

Also, if the response does have a Last-Modified time, the heuristic expiration value SHOULD be no more than some fraction of the interval since that time. A typical setting for this fraction might be 10% ๐Ÿ’…

The calculation to determine if a response has expired is pretty simple:

response_is_fresh = (freshness_lifetime > current_age)

13.2.5 Disambiguating Expiration Values ๐ŸŒˆ

Because expiration values are assigned optimistically, it's possible for two caches to contain fresh values for the same resource that are different ๐Ÿ‘€

If a client performing a retrieval receives a non-first-hand response for a request that was already fresh in its own cache, and the Date header in its existing cache entry is newer than the Date on the new response, then the client MAY ignore the response. If so, it MAY retry the request with a "Cache-Control: max-age=0" directive (see section 14.9), to force a check with the origin server ๐Ÿ”

If a cache has two fresh responses for the same representation with different validators, it MUST use the one with the more recent Date header. This can happen because the cache is pooling responses from other caches, or because a client asked for a reload or a revalidation of an apparently fresh cache entry. Periodt ๐Ÿ’–

13.2.6 Disambiguating Multiple Responses โœจ

okay so here's the tea ๐Ÿซ– a client can be getting responses through multiple paths, which means some responses go through one group of caches and others go through a totally different group. so the responses can show up in a different order than the origin server actually sent them ๐Ÿ˜ญ the goal is for the client to use the most recently generated response, even if older ones still look fresh. main character energy only ๐Ÿ’…

neither the entity tag nor the expiration value can set the order, bestie, because a later response can intentionally have an earlier expiration time ๐Ÿ™ˆ so what's the move? the HTTP/1.1 spec requires Date headers on every response, and Date values are ordered to a granularity of one second ๐Ÿ•ฐ๏ธ that's the key.

when a client tries to revalidate a cache entry and the response has a Date header that appears older than the one for the existing entry, then the client SHOULD repeat the request unconditionally ๐Ÿ” and include:

Cache-Control: max-age=0

this forces any intermediate caches to validate their copies directly with the origin server, or:

Cache-Control: no-cache

this forces any intermediate caches to grab a brand new copy from the origin server ๐Ÿซถ

if the Date values are equal, the client may use either response (or may, if it's being extremely prudent, request a new response ๐Ÿง). and servers MUST NOT depend on clients being able to pick deterministically between responses generated during the same second, if their expiration times overlap. no vibes-based decision making here, fr fr ๐Ÿ’€


13.3 Validation Model ๐ŸŽ€

so a cache has a stale entry and wants to serve it to a client. first it has to check in with the origin server (or maybe an intermediate cache with a fresh response) to see if the entry is still usable. this is called "validating" the cache entry ๐Ÿฆ‹ we don't want to pay the cost of resending the full response if the cached copy is still good, and we also don't want to eat an extra round trip if the cached copy is invalid. so HTTP/1.1 supports conditional methods ๐Ÿ’œ

the key features for conditional methods are the ones about "cache validators." when an origin server generates a full response, it attaches some kind of validator to it, and that gets stored with the cache entry. when a client (a user agent or a proxy cache) makes a conditional request for a resource it has a cache entry for, it includes the associated validator in the request ๐Ÿงš

the server then checks that validator against the current validator for the entity. if they match, it responds with a special status code (usually 304 (Not Modified)) and no entity-body ๐ŸŒธ otherwise it returns a full response, entity-body included. so we skip sending the full response when the validator matches, and we skip the extra round trip when it doesn't. iconic ๐Ÿ‘‘

Note: the comparison functions used to decide if validators match are defined in section 13.3.3.

in HTTP/1.1, a conditional request looks exactly like a normal request for the same resource, except it carries a special header (which includes the validator) that quietly turns the method (usually GET) into a conditional โœจ

the protocol has both positive and negative senses of cache-validating conditions. so you can ask for a method to be performed if and only if a validator matches, or if and only if no validators match ๐Ÿซง

Note: a response that lacks a validator may still be cached, and served from cache until it expires, unless a Cache-Control directive explicitly prohibits this. however, a cache cannot do a conditional retrieval if it doesn't have a validator for the entity, which means it won't be refreshable after it expires ๐Ÿ˜ญ

13.3.1 Last-modified Dates ๐Ÿ“…

the Last-Modified entity-header field value is often used as a cache validator. in simple terms, a cache entry is considered valid if the entity hasn't been modified since the Last-Modified value ๐Ÿ“

13.3.2 Entity Tag Cache Validators ๐Ÿท๏ธ

the ETag entity-header field value, an entity tag, gives you an "opaque" cache validator. this can allow more reliable validation when it's inconvenient to store modification dates, when the one-second resolution of HTTP date values isn't enough, or when the origin server wants to avoid certain paradoxes that can come up with modification dates ๐ŸŒˆ

entity tags are described in section 3.11. the headers used with entity tags are described in sections 14.20, 14.25, 14.26 and 14.43 ๐Ÿ’–

13.3.3 Weak and Strong Validators ๐Ÿ’Ž

since both origin servers and caches compare two validators to decide whether they represent the same or different entities, you'd normally expect that if the entity (the entity-body or any entity-headers) changes in any way, the associated validator changes too. if that's true, we call it a "strong validator" ๐Ÿ’ช

but sometimes a server prefers to change the validator only on semantically significant changes, not when insignificant parts of the entity change. a validator that doesn't always change when the resource changes is a "weak validator" ๐Ÿซถ

entity tags are normally "strong validators," but the protocol gives you a way to tag an entity tag as "weak." think of a strong validator as one that changes whenever the bits of an entity change, while a weak one changes whenever the meaning of an entity changes ๐Ÿง  another way to see it: a strong validator is part of an identifier for one specific entity, while a weak validator is part of an identifier for a set of semantically equivalent entities ๐Ÿฆ‹

Note: One example of a strong validator is an integer that is incremented in stable storage every time an entity is changed. An entity's modification time, if represented with one-second resolution, could be a weak validator, since it is possible that the resource may be modified twice during a single second. Support for weak validators is optional; however, weak validators allow for more efficient caching of equivalent objects. for example, a hit counter on a site is probably good enough if it's updated every few days or weeks, and any value during that period is likely "good enough" to be equivalent ๐Ÿ”ข A "use" of a validator is either when a client generates a request and includes the validator in a validating header field, or when a server compares two validators.

strong validators are usable in any context. weak validators are only usable in contexts that don't depend on exact equality of an entity. for example, either kind works for a conditional GET of a full entity. but only a strong validator works for a sub-range retrieval, because otherwise the client might end up with an internally inconsistent entity ๐Ÿ™ˆ

the only function HTTP/1.1 defines on validators is comparison. there are two validator comparison functions, depending on whether the comparison context allows weak validators or not:

  • The strong comparison function: in order to be considered equal, both validators must be identical in every way, and neither may be weak.
  • The weak comparison function: in order to be considered equal, both validators must be identical in every way, but either or both of them may be tagged as "weak" without affecting the result.

the weak comparison function MAY be used for simple (non-subrange) GET requests. the strong comparison function MUST be used in all other cases ๐Ÿ”

an entity tag is strong unless it's explicitly tagged as weak. section 3.11 gives the syntax for entity tags ๐Ÿท๏ธ

a Last-Modified time, when used as a validator in a request, is implicitly weak unless it's possible to deduce that it's strong, using the following rules ๐Ÿงฉ

  • The validator is being compared by an origin server to the actual current validator for the entity, and,
  • That origin server reliably knows that the associated entity did not change twice during the second covered by the presented validator.

or

  • The validator is about to be used by a client in an If-Modified-Since or If-Unmodified-Since header, because the client has a cache entry for the associated entity, and
  • That cache entry includes a Date value, which gives the time when the origin server sent the original response, and
  • The presented Last-Modified time is at least 60 seconds before the Date value.

or

  • The validator is being compared by an intermediate cache to the validator stored in its cache entry for the entity, and
  • That cache entry includes a Date value, which gives the time when the origin server sent the original response, and
  • The presented Last-Modified time is at least 60 seconds before the Date value.

this method relies on the fact that if two different responses were sent by the origin server during the same second, but both had the same Last-Modified time, then at least one of those responses would have a Date value equal to its Last-Modified time. the arbitrary 60-second limit guards against the possibility that the Date and Last-Modified values come from different clocks, or get generated at somewhat different times during the preparation of the response. an implementation may use a value larger than 60 seconds, if it's believed that 60 seconds is too short โฑ๏ธ

if a client wants to do a sub-range retrieval on a value for which it only has a Last-Modified time and no opaque validator, it may do this only if the Last-Modified time is strong in the sense described here ๐Ÿซง

a cache or origin server receiving a cache-conditional request, other than a full-body GET request, MUST use the strong comparison function to evaluate the condition ๐Ÿ›ก๏ธ

these rules let HTTP/1.1 caches and clients safely do sub-range retrievals on values that were obtained from HTTP/1.0 servers ๐Ÿฅนโœจ

13.3.4 Rules for When to Use Entity Tags and Last-modified Dates โœจ

okay bestie, we're setting up a squad of rules and recommendations ๐Ÿ“‹ for origin servers, clients, and caches about when each validator type is used and what for ๐Ÿ’…

HTTP/1.1 origin servers:

  • SHOULD send an entity tag validator unless it is not feasible to generate one. ๐Ÿท๏ธ
  • MAY send a weak entity tag instead of a strong entity tag, if performance considerations support the use of weak entity tags, or if it is unfeasible to send a strong entity tag. ๐ŸŒธ
  • SHOULD send a Last-Modified value if it is feasible to send one, unless the risk of a breakdown in semantic transparency that could result from using this date in an If-Modified-Since header would lead to serious problems. ๐Ÿงš

In other words, the preferred behavior for an HTTP/1.1 origin server is to send both a strong entity tag and a Last-Modified value. ๐Ÿ‘‘

In order to be legal, a strong entity tag MUST change whenever the associated entity value changes in any way. A weak entity tag SHOULD change whenever the associated entity changes in a semantically significant way. ๐Ÿ”ฅ

Note: in order to provide semantically transparent caching, an origin server must avoid reusing a specific strong entity tag value for two different entities, or reusing a specific weak entity tag value for two semantically different entities. Cache entries may persist for arbitrarily long periods, regardless of expiration times, so it may be inappropriate to expect that a cache will never again attempt to validate an entry using a validator that it obtained at some point in the past. ๐Ÿ™ˆ

HTTP/1.1 clients:

  • If an entity tag has been provided by the origin server, MUST use that entity tag in any cache-conditional request (using If-Match or If-None-Match). ๐Ÿ’œ
  • If only a Last-Modified value has been provided by the origin server, SHOULD use that value in non-subrange cache-conditional requests (using If-Modified-Since). ๐Ÿฆ‹
  • If only a Last-Modified value has been provided by an HTTP/1.0 origin server, MAY use that value in subrange cache-conditional requests (using If-Unmodified-Since:). The user agent should provide a way to disable this, in case of difficulty. ๐ŸŒˆ
  • If both an entity tag and a Last-Modified value have been provided by the origin server, SHOULD use both validators in cache-conditional requests. This allows both HTTP/1.0 and HTTP/1.1 caches to respond appropriately. ๐Ÿซถ

An HTTP/1.1 cache, upon receiving a request, MUST use the most restrictive validator when deciding whether the client's cache entry matches the cache's own cache entry. This is only an issue when the request contains both an entity tag and a last-modified-date validator (If-Modified-Since or If-Unmodified-Since). ๐Ÿง 

A note on rationale: the general principle behind these rules is that HTTP/1.1 servers and clients should transmit as much non-redundant information as is available in their responses and requests. HTTP/1.1 systems receiving this information will make the most conservative assumptions about the validators they receive. ๐Ÿ“

HTTP/1.0 clients and caches will ignore entity tags. Generally, last-modified values received or used by these systems will support transparent and efficient caching, and so HTTP/1.1 origin servers should provide Last-Modified values. In those rare cases where the use of a Last-Modified value as a validator by an HTTP/1.0 system could result in a serious problem, then HTTP/1.1 origin servers should not provide one. ๐Ÿ’€


13.3.5 Non-validating Conditionals โœจ

the whole principle behind entity tags is that only the service author knows the semantics of a resource well enough to pick an appropriate cache validation mechanism ๐Ÿง and specifying any validator comparison function more complex than byte-equality would open up a can of worms. So comparisons of any other headers (except Last-Modified, for compatibility with HTTP/1.0) are never used for purposes of validating a cache entry. ๐Ÿ™…โ€โ™€๏ธ

13.4 Response Cachability ๐Ÿ’–

unless a Cache-Control (section 14.9) directive specifically constrains it, a caching system may always store a successful response (see section 13.8) as a cache entry, may return it without validation if it is fresh, and may return it after successful validation. If there is neither a cache validator nor an explicit expiration time associated with a response, we do not expect it to be cached, but certain caches may violate this expectation (for example, when little or no network connectivity is available). A client can usually detect that such a response was taken from a cache by comparing the Date header to the current time. ๐Ÿ•ต๏ธโ€โ™€๏ธ

Note that some HTTP/1.0 caches are known to violate this expectation without providing any Warning. ๐Ÿ˜ญ

however, in some cases it may be inappropriate for a cache to retain an entity, or to return it in response to a subsequent request. This may be because absolute semantic transparency is deemed necessary by the service author, or because of security or privacy considerations. Certain Cache-Control directives are therefore provided so that the server can indicate that certain resource entities, or portions thereof, may not be cached regardless of other considerations. ๐Ÿ”’

Note that section 14.8 normally prevents a shared cache from saving and returning a response to a previous request if that request included an Authorization header. ๐Ÿ›ก๏ธ

A response received with a status code of 200, 203, 206, 300, 301 or 410 may be stored by a cache and used in reply to a subsequent request, subject to the expiration mechanism, unless a Cache-Control directive prohibits caching. However, a cache that does not support the Range and Content-Range headers MUST NOT cache 206 (Partial Content) responses. ๐ŸŽ€

A response received with any other status code MUST NOT be returned in a reply to a subsequent request unless there are Cache-Control directives or another header(s) that explicitly allow it. For example, these include the following: an Expires header (section 14.21); a "max-age", "must-revalidate", "proxy-revalidate", "public" or "private" Cache-Control directive (section 14.9). ๐Ÿšซ

13.5 Constructing Responses From Caches ๐Ÿง

the whole point of an HTTP cache is to store information received in responses, for use in answering future requests ๐Ÿค In many cases, a cache simply returns the appropriate parts of a response to the requester. However, if the cache holds a cache entry based on a previous response, it may have to combine parts of a new response with what is held in the cache entry. โœจ

13.5.1 End-to-end and Hop-by-hop Headers ๐Ÿฆ‹

for defining how caches and non-caching proxies behave, we split HTTP headers into two categories:

  • End-to-end headers, which must be transmitted to the ultimate recipient of a request or response. End-to-end headers in responses must be stored as part of a cache entry and transmitted in any response formed from a cache entry. ๐Ÿ“ฌ
  • Hop-by-hop headers, which are meaningful only for a single transport-level connection, and are not stored by caches or forwarded by proxies. ๐Ÿšช

The following HTTP/1.1 headers are hop-by-hop headers:

  • Connection
  • Keep-Alive
  • Public
  • Proxy-Authenticate
  • Transfer-Encoding
  • Upgrade

All other headers defined by HTTP/1.1 are end-to-end headers. ๐Ÿ’…

Hop-by-hop headers introduced in future versions of HTTP MUST be listed in a Connection header, as described in section 14.10. ๐Ÿ“

13.5.2 Non-modifiable Headers ๐Ÿ”

some features of HTTP/1.1, like Digest Authentication, depend on the value of certain end-to-end headers ๐Ÿ‘€ A cache or non-caching proxy SHOULD NOT modify an end-to-end header unless the definition of that header requires or specifically allows that. โš ๏ธ

A cache or non-caching proxy MUST NOT modify any of the following fields in a request or response, nor may it add any of these fields if not already present: ๐Ÿ™…

  • Content-Location
  • ETag
  • Expires
  • Last-Modified

A cache or non-caching proxy MUST NOT modify or add any of the following fields in a response that contains the no-transform Cache-Control directive, or in any request: ๐Ÿšท

  • Content-Encoding
  • Content-Length
  • Content-Range
  • Content-Type

A cache or non-caching proxy MAY modify or add these fields in a response that does not include no-transform, but if it does so, it MUST add a Warning 14 (Transformation applied) if one does not already appear in the response. ๐ŸŽจ

Warning: unnecessary modification of end-to-end headers may cause authentication failures if stronger authentication mechanisms are introduced in later versions of HTTP. Such authentication mechanisms may rely on the values of header fields not listed here. ๐Ÿšจ

13.5.3 Combining Headers ๐Ÿงฉ

When a cache makes a validating request to a server, and the server provides a 304 (Not Modified) response, the cache must construct a response to send to the requesting client. The cache uses the entity-body stored in the cache entry as the entity-body of this outgoing response. The end-to-end headers stored in the cache entry are used for the constructed response, except that any end-to-end headers provided in the 304 response MUST replace the corresponding headers from the cache entry. Unless the cache decides to remove the cache entry, it MUST also replace the end-to-end headers stored with the cache entry with corresponding headers received in the incoming response. ๐Ÿ’ซ

in other words, the set of end-to-end headers received in the incoming response overrides all corresponding end-to-end headers stored with the cache entry. The cache may add Warning headers (see section 14.45) to this set. ๐ŸŒŸ

If a header field-name in the incoming response matches more than one header in the cache entry, all such old headers are replaced. ๐Ÿ”„

Note: this rule allows an origin server to use a 304 (Not Modified) response to update any header associated with a previous response for the same entity, although it might not always be meaningful or correct to do so. This rule does not allow an origin server to use a 304 (not Modified) response to entirely delete a header that it had provided with a previous response. ๐Ÿ™ˆ

13.5.4 Combining Byte Ranges ๐Ÿฐ

a response may transfer only a subrange of the bytes of an entity-body, either because the request included one or more Range specifications, or because a connection was broken prematurely. After several such transfers, a cache may have received several ranges of the same entity-body. ๐Ÿงƒ

If a cache has a stored non-empty set of subranges for an entity, and an incoming response transfers another subrange, the cache MAY combine the new subrange with the existing set if both the following conditions are met: ๐Ÿค”

  • Both the incoming response and the cache entry must have a cache validator.
  • The two cache validators must match using the strong comparison function (see section 13.3.3).

If either requirement is not meant, the cache must use only the most recent partial response (based on the Date values transmitted with every response, and using the incoming response if these values are equal or missing), and must discard the other partial information. ๐Ÿ—‘๏ธ

13.6 Caching Negotiated Responses ๐ŸŽ€

okay so server-driven content negotiation (section 12) is when the server picks which version of a resource to send, and you can spot it because the response has a Vary header field ๐Ÿ‘€ that changes what a cache is allowed to do with the response for later requests, so pay attention bestie ๐Ÿงš

A server MUST use the Vary header field (section 14.43) to tell a cache which header field dimensions were used to pick among multiple representations of a cachable response. A cache may use the selected representation (the entity included with that particular response) to answer later requests on that resource, but only when those requests have the same or equivalent values for every header field listed in the Vary response-header. Requests with a different value for one or more of those header fields get forwarded toward the origin server ๐Ÿš€

If an entity tag was assigned to the representation, the forwarded request SHOULD be conditional and include the entity tags in an If-None-Match header field, pulled from all of its cache entries for the Request-URI ๐Ÿซถ this tells the server which entities the cache is already holding, so if one of them matches the requested entity, the server can send back a 304 (Not Modified) response with the ETag header and let the cache know which entry is the right one. If the entity-tag of the new response matches an existing entry, the new response SHOULD be used to update that entry's header fields, and the result MUST be returned to the client โœจ

The Vary header field can also tell the cache that the representation was picked using criteria that go beyond the request-headers. In that case, a cache MUST NOT use the response to answer a later request unless it relays the new request to the origin server as a conditional request and the server replies with 304 (Not Modified), including an entity tag or Content-Location that shows which entity should be used ๐Ÿ’…

If any existing cache entry only holds partial content for its entity, that entry's entity-tag SHOULD NOT be included in the If-None-Match header, unless the request is for a range that the entry could fully satisfy ๐Ÿงฉ

If a cache gets a successful response whose Content-Location matches an existing cache entry for the same Request-URI, whose entity-tag is different from that entry's, and whose Date is more recent than the entry's, then the existing entry SHOULD NOT be returned for future requests, and should be deleted from the cache ๐Ÿ—‘๏ธ bye bye old entry

13.7 Shared and Non-Shared Caches ๐Ÿ”

for security and privacy reasons, we have to split caches into two groups: "shared" and "non-shared" ๐Ÿซฃ a non-shared cache is one that only a single user can access, and access in this case SHOULD be enforced by appropriate security mechanisms. Every other cache counts as "shared." Other sections of this specification put some rules on how shared caches work, so they don't leak privacy or break access controls ๐Ÿ™ˆ

13.8 Errors or Incomplete Response Cache Behavior ๐Ÿ’€

if a cache gets an incomplete response (like one with fewer bytes of data than the Content-Length header says), the cache may store it, BUT it MUST treat it as a partial response. Partial responses can be combined as described in section 13.5.4, and the result might be a full response or might still be partial ๐Ÿงฉ A cache MUST NOT return a partial response to a client without explicitly marking it as such, using the 206 (Partial Content) status code. A cache MUST NOT return a partial response using a status code of 200 (OK) โŒ

Okay, and if a cache gets a 5xx response while it's trying to revalidate an entry, it has two options: it can forward that response to the requesting client, or it can act like the server never responded at all ๐Ÿคทโ€โ™€๏ธ In the second case, it MAY return a previously received response, unless the cached entry includes the must-revalidate Cache-Control directive (see section 14.9).

13.9 Side Effects of GET and HEAD ๐Ÿ“

unless the origin server explicitly prohibits caching of its responses, using GET and HEAD on any resources SHOULD NOT have side effects that would cause wrong behavior if those responses come from a cache. They can still have side effects, but a cache doesn't have to think about those side effects when it makes caching decisions. Caches are always expected to respect an origin server's explicit restrictions on caching ๐Ÿ™Œ

there's one exception to this, and it's giving old-school drama ๐ŸŽญ some applications used GETs and HEADs with query URLs (the ones with a "?" in the rel_path part) to do stuff with big side effects. So caches MUST NOT treat responses from those URLs as fresh unless the server gives an explicit expiration time. This specifically means that responses from HTTP/1.0 servers for such URIs should not be taken from a cache. See section 9.1.1 for related information ๐Ÿ“š

13.10 Invalidation After Updates or Deletions ๐Ÿ’ฅ

certain methods running at the origin server can make one or more existing cache entries non-transparently invalid. Those entries might still count as "fresh," but they don't accurately show what the origin server would return for a new request ๐Ÿ˜ฌ

Honestly there's no way for HTTP to guarantee that every one of those cache entries gets marked invalid. For example, the request that changed things at the origin server might never have gone through the proxy where a cache entry is stored. BUT several rules help cut down on the chance of messing things up ๐Ÿซถ

In this section, the phrase "invalidate an entity" means that the cache should either remove all instances of that entity from its storage, or mark them as "invalid" so they need a mandatory revalidation before they can be returned for a later request ๐Ÿงน

Some HTTP methods may invalidate an entity. This is either the entity referred to by the Request-URI, or the entity referred to by the Location or Content-Location response-headers (if they're present). These methods are:

  • PUT
  • DELETE
  • POST

to prevent denial of service attacks, an invalidation based on the URI in a Location or Content-Location header MUST only be performed if the host part is the same as in the Request-URI ๐Ÿ›ก๏ธ

13.11 Write-Through Mandatory โœ๏ธ

all methods that might change the origin server's resources MUST be written through to the origin server. Right now that includes every method except GET and HEAD. A cache MUST NOT reply to such a request from a client before it has sent the request to the inbound server and gotten a matching response back from that server. This doesn't stop a cache from sending a 100 (Continue) response before the inbound server has replied ๐ŸŒธ

The alternative, known as "write-back" or "copy-back" caching, is not allowed in HTTP/1.1. Keeping updates consistent is hard, and there are real problems if the server, cache, or network fails before a write-back happens ๐Ÿ˜ต

13.12 Cache Replacement ๐Ÿ”„

if a new cachable response (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8) comes in from a resource while existing responses for that same resource are cached, the cache SHOULD use the new response to answer the current request. It may store it in cache storage and, if it meets all the other requirements, use it to respond to any future requests that would have gotten the old response before ๐ŸŒˆ If it does put the new response into cache storage, it should follow the rules in section 13.5.3.

Note: a new response with an older Date header value than the existing cached responses is not cachable. Don't let the old one overwrite the fresh tea โ˜•

13.13 History Lists ๐Ÿ“œ

user agents often have history mechanisms, like "Back" buttons and history lists, that can be used to redisplay an entity retrieved earlier in a session ๐Ÿงšโ€โ™€๏ธ

History mechanisms and caches are totally different things ๐Ÿ’… Specifically, history mechanisms SHOULD NOT try to show a semantically transparent view of a resource's current state. Instead, a history mechanism is meant to show exactly what the user saw at the time the resource was retrieved ๐Ÿ“ธ

By default, an expiration time does not apply to history mechanisms. If the entity is still in storage, a history mechanism should display it even if the entity has expired, unless the user has specifically configured the agent to refresh expired history documents ๐Ÿ”

This should not be read as stopping the history mechanism from telling the user that a view may be stale ๐Ÿ‘€

Note: if history list mechanisms unnecessarily stop users from viewing stale resources, service authors will tend to avoid HTTP expiration controls and cache controls when they'd otherwise like to use them. Service authors may think it's important that users never see error or warning messages when they use navigation controls (such as BACK) to view previously fetched resources. Even when such resources ought not to be cached, or ought to expire quickly, user interface considerations may push service authors to use other ways of preventing caching (e.g. "once-only" URLs) so they don't suffer from improperly functioning history mechanisms ๐Ÿ˜ญ

14 Header Field Definitions ๐ŸŽ€

This section defines the syntax and semantics of all standard HTTP/1.1 header fields. For entity-header fields, both sender and recipient refer to either the client or the server, depending on who sends and who receives the entity ๐Ÿ’œ

14.1 Accept ๐Ÿ’–

okay so the Accept request-header field is how a client tells the server which media types it's cool receiving back in the response ๐Ÿ’… like when you only want a tiny set of types, say you're asking for an in-line image, and you literally don't want anything else ๐ŸŽ€

          Accept         = "Accept" ":"
                           #( media-range [ accept-params ] )

          media-range    = ( "*/*"
                           | ( type "/" "*" )
                           | ( type "/" subtype )
                           ) *( ";" parameter )

          accept-params  = ";" "q" "=" qvalue *( accept-extension )

          accept-extension = ";" token [ "=" ( token | quoted-string ) ]

The asterisk "" is how you group media types into ranges ๐Ÿฆ‹ so "/" means all media types and "type/" means all subtypes of that type. The media-range MAY include media type parameters that apply to that range โœจ

Each media-range MAY be followed by one or more accept-params, starting with the "q" parameter for a relative quality factor ๐ŸŒธ The first "q" parameter (if any) is what separates the media-range parameters from the accept-params. Quality factors let the user or user agent show how much they prefer that media-range, using the qvalue scale from 0 to 1 (section 3.9). The default value is q=1 ๐Ÿ’œ

Note: Using the "q" parameter name to split media type parameters from Accept extension parameters is due to historical practice ๐Ÿ™ˆ This means a media type parameter named "q" can't be used with a media range. Such an event is believed to be unlikely, given the lack of any "q" parameters in the IANA media type registry and the rare usage of any media type parameters in Accept. Future media types should be discouraged from registering any parameter named "q".

Here's the example:

Accept: audio/*; q=0.2, audio/basic

This one SHOULD be interpreted as "I prefer audio/basic, but send me any audio type if it is the best available after an 80% mark-down in quality." ๐Ÿ˜ญ If no Accept header field is present, then it is assumed that the client accepts all media types. If an Accept header field is present, and the server cannot send a response which is acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response ๐Ÿ’€

A more elaborate example is:

Accept: text/plain; q=0.5, text/html,
        text/x-dvi; q=0.8, text/x-c

Verbally, this is giving "text/html and text/x-c are the preferred media types, but if they do not exist, then send the text/x-dvi entity, and if that does not exist, send the text/plain entity." main character energy ๐Ÿ‘‘

Media ranges can be overridden by more specific media ranges or specific media types. If more than one media range applies to a given type, the most specific reference has precedence ๐Ÿงš For example:

Accept: text/*, text/html, text/html;level=1, */*

have the following precedence:

1) text/html;level=1
2) text/html
3) text/*
4) */*

The media type quality factor for a given type is determined by finding the media range with the highest precedence which matches that type ๐Ÿ“ For example:

Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
        text/html;level=2;q=0.4, */*;q=0.5

would cause the following values to be associated:

text/html;level=1         = 1
text/html                 = 0.7
text/plain                = 0.3
image/jpeg                = 0.5
text/html;level=2         = 0.4
text/html;level=3         = 0.7
Note: A user agent may be provided with a default set of quality values for certain media ranges. However, unless the user agent is a closed system which cannot interact with other rendering agents, this default set should be configurable by the user ๐ŸŒˆ

14.2 Accept-Charset ๐ŸŽ€

The Accept-Charset request-header field is how you tell the server which character sets are acceptable for the response ๐ŸŒธ Clients that can understand fancier or special-purpose character sets use this to signal that to a server that can represent documents in those sets. The ISO-8859-1 character set can be assumed to be acceptable to all user agents โœจ

          Accept-Charset = "Accept-Charset" ":"
                    1#( charset [ ";" "q" "=" qvalue ] )

Character set values are described in section 3.4. Each charset may be given an associated quality value that shows the user's preference for that charset. The default value is q=1. An example is:

Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

If no Accept-Charset header is present, the default is that any character set is acceptable ๐Ÿฆ‹ If an Accept-Charset header is present, and the server cannot send a response that is acceptable according to that header, then the server SHOULD send an error response with the 406 (not acceptable) status code ๐Ÿ˜ญ though sending an unacceptable response is also allowed ๐Ÿ’…


14.3 Accept-Encoding ๐Ÿงš

The Accept-Encoding request-header field is similar to Accept, but it restricts the content-coding values (section 14.12) that are acceptable in the response ๐Ÿ“

          Accept-Encoding  = "Accept-Encoding" ":"
                                    #( content-coding )

An example of its use is:

Accept-Encoding: compress, gzip

If no Accept-Encoding header is present in a request, the server MAY assume that the client will accept any content coding ๐Ÿ’– If an Accept-Encoding header is present, and the server cannot send a response which is acceptable according to it, then the server SHOULD send an error response with the 406 (Not Acceptable) status code ๐Ÿ’€

An empty Accept-Encoding value indicates none are acceptable. ๐Ÿ™ˆ


14.4 Accept-Language ๐ŸŒธ

The Accept-Language request-header field is similar to Accept, but it restricts the set of natural languages that are preferred as a response to the request ๐ŸŒ

          Accept-Language = "Accept-Language" ":"
                            1#( language-range [ ";" "q" "=" qvalue ] )

          language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )

Each language-range MAY be given an associated quality value that represents an estimate of the user's preference for the languages specified by that range ๐Ÿฆ‹ The quality value defaults to "q=1". For example:

Accept-Language: da, en-gb;q=0.8, en;q=0.7

This would mean: "I prefer Danish, but will accept British English and other types of English." โœจ A language-range matches a language-tag if it exactly equals the tag, or if it exactly equals a prefix of the tag such that the first tag character following the prefix is "-". The special range "*", if present in the Accept-Language field, matches every tag not matched by any other range present in that field ๐Ÿ‘‘

Note: This use of a prefix matching rule does not imply that language tags are assigned to languages in such a way that it is always true that if a user understands a language with a certain tag, then this user will also understand all languages with tags for which this tag is a prefix. The prefix rule simply allows the use of prefix tags if this is the case.

The language quality factor assigned to a language-tag by the Accept-Language field is the quality value of the longest language-range in the field that matches the language-tag ๐Ÿงš If no language-range in the field matches the tag, the language quality factor assigned is 0. If no Accept-Language header is present in the request, the server SHOULD assume that all languages are equally acceptable. If an Accept-Language header is present, then all languages which are assigned a quality factor greater than 0 are acceptable ๐Ÿ’…

It may be contrary to the privacy expectations of the user to send an Accept-Language header with the complete linguistic preferences of the user in every request ๐Ÿ”ฅ For a discussion of this issue, see section 15.7.

Note: As intelligibility is highly dependent on the individual user, it is recommended that client applications make the choice of linguistic preference available to the user. If the choice is not made available, then the Accept-Language header field must not be given in the request. ๐Ÿซถ

14.5 Accept-Ranges ๐Ÿ“

The Accept-Ranges response-header field lets the server say whether it accepts range requests for a resource ๐Ÿฆ‹

          Accept-Ranges     = "Accept-Ranges" ":" acceptable-ranges

          acceptable-ranges = 1#range-unit | "none"

Origin servers that accept byte-range requests MAY send:

Accept-Ranges: bytes

but they are not required to do so โœจ Clients MAY generate byte-range requests without having received this header for the resource involved ๐Ÿ’–

Servers that do not accept any kind of range request for a resource MAY send:

Accept-Ranges: none

to advise the client not to attempt a range request ๐Ÿ™ˆ


14.6 Age ๐ŸŒˆ

The Age response-header field conveys the sender's estimate of the amount of time since the response (or its revalidation) was generated at the origin server โฐ A cached response is "fresh" if its age does not exceed its freshness lifetime. Age values are calculated as specified in section 13.2.3 ๐Ÿ’…

           Age = "Age" ":" age-value

           age-value = delta-seconds

Age values are non-negative decimal integers, representing time in seconds ๐Ÿงš

If a cache receives a value larger than the largest positive integer it can represent, or if any of its age calculations overflows, it MUST transmit an Age header with a value of 2147483648 (2^31) ๐Ÿ˜ญ HTTP/1.1 caches MUST send an Age header in every response. Caches SHOULD use an arithmetic type of at least 31 bits of range ๐Ÿ”ฅ


14.7 Allow ๐Ÿ‘‘

The Allow entity-header field lists the set of methods supported by the resource identified by the Request-URI ๐ŸŽ€ The purpose of this field is strictly to inform the recipient of valid methods associated with the resource. An Allow header field MUST be present in a 405 (Method Not Allowed) response ๐Ÿ’€

          Allow          = "Allow" ":" 1#method

Example of use:

Allow: GET, HEAD, PUT

This field cannot prevent a client from trying other methods ๐Ÿ™ˆ However, the indications given by the Allow header field value SHOULD be followed. The actual set of allowed methods is defined by the origin server at the time of each request ๐Ÿฆ‹

The Allow header field MAY be provided with a PUT request to recommend the methods to be supported by the new or modified resource โœจ The server is not required to support these methods and SHOULD include an Allow header in the response giving the actual supported methods ๐Ÿ’–

A proxy MUST NOT modify the Allow header field even if it does not understand all the methods specified, since the user agent MAY have other means of communicating with the origin server ๐Ÿซถ

The Allow header field does not indicate what methods are implemented at the server level. Servers MAY use the Public response-header field (section 14.35) to describe what methods are implemented on the server as a whole ๐ŸŒธ

14.8 Authorization โœจ

okay bestie, so a user agent that wants to prove who it is to a server can do that by adding an Authorization request-header field to the request ๐Ÿ”. It usually does this after getting a 401 response, but not always. MAY is the magic word here, so it's totally optional ๐Ÿ’…. The value is the credentials, which hold the user agent's login info for the realm of the resource it's asking for.

Authorization  = "Authorization" ":" credentials

HTTP access authentication gets its own deep dive in section 11 ๐Ÿง . If a request is authenticated and a realm is named, the same credentials SHOULD be valid for every other request in that realm. That's the vibe we want, no drama ๐Ÿซถ.

okay now the important part ๐Ÿ˜ค when a shared cache (see section 13.7) gets a request with an Authorization field, it MUST NOT hand that response back to any other request. the only exceptions are these three:

  1. if the response has the proxy-revalidate Cache-Control directive, the cache MAY use it to answer a later request. BUT a proxy cache MUST revalidate it with the origin server first, using the request headers from the new request so the origin server can authenticate that new request ๐Ÿ”.
  2. if the response has the must-revalidate Cache-Control directive, the cache MAY use it to answer a later request. BUT all caches MUST revalidate it with the origin server first, using the request headers from the new request so the origin server can authenticate it ๐Ÿ”.
  3. if the response has the public Cache-Control directive, it may be returned for any later request ๐ŸŒˆ.

14.9 Cache-Control ๐ŸŽ€

the Cache-Control general-header field is how you set directives that MUST be obeyed by every caching mechanism along the request/response chain ๐Ÿ“ฃ. These directives are there to stop caches from messing with the request or response, and they usually override the default caching rules. Cache directives are one-way, so a directive in a request doesn't mean the same directive should show up in the response ๐Ÿฆ‹.

๐Ÿ’€ Note: HTTP/1.0 caches might not support Cache-Control at all, and they may only understand Pragma: no-cache (see section 14.32).

a proxy or gateway MUST pass cache directives along, even if it doesn't care about them itself, since they might matter to everyone else on the chain ๐Ÿซถ. You also can't target a directive at one specific cache.

Cache-Control   = "Cache-Control" ":" 1#cache-directive

cache-directive = cache-request-directive
                | cache-response-directive

cache-request-directive =
                  "no-cache" [ "=" <"> 1#field-name <"> ]
                | "no-store"
                | "max-age" "=" delta-seconds
                | "max-stale" [ "=" delta-seconds ]
                | "min-fresh" "=" delta-seconds
                | "only-if-cached"
                | cache-extension

cache-response-directive =
                  "public"
                | "private" [ "=" <"> 1#field-name <"> ]
                | "no-cache" [ "=" <"> 1#field-name <"> ]
                | "no-store"
                | "no-transform"
                | "must-revalidate"
                | "proxy-revalidate"
                | "max-age" "=" delta-seconds
                | cache-extension

cache-extension = token [ "=" ( token | quoted-string ) ]

when a directive shows up with no 1#field-name parameter, it covers the whole request or response ๐ŸŒธ. when it DOES have a 1#field-name parameter, it only applies to those named fields and not the rest of the message. this is the extensibility trick ๐Ÿงš, so future HTTP versions can apply these directives to header fields that HTTP/1.1 never defined.

the cache-control directives fall into these general categories:

  • Restrictions on what is cachable; these may only be imposed by the origin server.
  • Restrictions on what may be stored by a cache; these may be imposed by either the origin server or the user agent.
  • Modifications of the basic expiration mechanism; these may be imposed by either the origin server or the user agent.
  • Controls over cache revalidation and reload; these may only be imposed by a user agent.
  • Control over transformation of entities.
  • Extensions to the caching system.

14.9.1 What is Cachable ๐Ÿ“

by default, a response is cachable if the request method, the request header fields, and the response status all say it is ๐Ÿ™Œ. section 13.4 sums up those defaults. these Cache-Control response directives let an origin server override the default:

public

  • this says the response is cachable by any cache, even if it would normally be non-cachable or only cachable in a non-shared cache ๐ŸŒˆ. (See also Authorization, section 14.8, for additional details.)

private

  • this says all or part of the response is meant for ONE user and MUST NOT be stored by a shared cache ๐Ÿ”’. the origin server is basically saying those parts are only for one person and aren't a valid answer for anyone else. a private (non-shared) cache is allowed to store it.
โœจ Note: this use of the word private only controls WHERE the response can be cached. It can't guarantee the privacy of the message content.

no-cache

  • this says all or part of the response MUST NOT be cached ANYWHERE ๐Ÿšซ. it stops caching even in caches that were set up to serve stale responses to clients.
๐Ÿ’€ Note: most HTTP/1.0 caches won't recognize or follow this directive.

14.9.2 What May be Stored by Caches ๐Ÿ”

the no-store directive exists to stop sensitive info from being accidentally released or kept around (like on backup tapes ๐Ÿ“ผ). it covers the whole message and can show up in a request or a response. if it's in a request, a cache MUST NOT store any part of that request or any response to it. if it's in a response, a cache MUST NOT store any part of that response or the request that triggered it. this applies to both shared and non-shared caches ๐Ÿ™…โ€โ™€๏ธ. "MUST NOT store" here means the cache MUST NOT deliberately save the info to non-volatile storage, and it MUST make a best-effort attempt to clear it from volatile storage as quickly as possible after forwarding it.

even with this directive on a response, users can still save it outside the caching system (like with a "Save As" dialog ๐Ÿ’พ). history buffers may also keep these responses as part of how they normally work.

this directive is for people and service authors who are worried about info leaking through unexpected access to cache data structures ๐Ÿ‘€. it can help privacy in some cases, BUT we really need to say it is NOT in any way a reliable or sufficient privacy mechanism ๐Ÿ˜ญ. malicious or compromised caches may ignore it, and communications networks may be open to eavesdropping ๐Ÿ•ต๏ธโ€โ™€๏ธ.

14.9.3 Modifications of the Basic Expiration Mechanism โฐ

the origin server can set an entity's expiration time with the Expires header (see section 14.21) ๐Ÿ“…. or it can use the max-age directive in a response instead.

if a response has BOTH an Expires header AND a max-age directive, max-age wins, even when Expires is stricter ๐Ÿ‘‘. this lets an origin server give an HTTP/1.1 (or later) cache a longer expiration time than an HTTP/1.0 cache. it's handy if some HTTP/1.0 caches miscalculate ages or expiration times, maybe because their clocks are out of sync ๐Ÿ•ฐ๏ธ.

๐Ÿ’€ Note: most older caches that don't follow this spec don't support any Cache-Control directives at all. If an origin server wants a directive that limits caching by an HTTP/1.1-compliant cache without fully blocking it, it can rely on the rule that max-age overrides Expires, and on the fact that non-HTTP/1.1-compliant caches ignore max-age ๐Ÿง .

user agents can also tweak the basic expiration mechanism with these request directives:

max-age

  • the client is happy to take a response whose age is no more than the given seconds โฑ๏ธ. unless a max-stale directive is also there, the client won't accept a stale response.

min-fresh

  • the client will accept a response whose freshness lifetime is at least its current age plus the given seconds ๐ŸŒฟ. basically, it wants a response that stays fresh for at least that many more seconds.

max-stale

  • the client will accept a response that's already past its expiration time ๐Ÿฅ€. if max-stale has a value, the client accepts a response that's past expiration by no more than that many seconds. if there's no value, the client will take a stale response of ANY age ๐Ÿ™ˆ.

if a cache returns a stale response, either because of a max-stale directive on the request or because the cache is set up to override the response's expiration time, the cache MUST attach a Warning header to that stale response, using Warning 10 (Response is stale) โš ๏ธ.

14.9.4. Cache Revalidation and Reload Controls โœจ

Okay so sometimes a user agent wants or needs a cache to revalidate its cache entry with the origin server (and not just with the next cache along the path to the origin server), or to reload its cache entry from the origin server. End-to-end revalidation may be necessary if either the cache or the origin server has overestimated the expiration time of the cached response. End-to-end reload may be necessary if the cache entry has become corrupted for some reason ๐Ÿ’€.

End-to-end revalidation may be requested either when the client does not have its own local cached copy, in which case we call it "unspecified end-to-end revalidation", or when the client does have a local cached copy, in which case we call it "specific end-to-end revalidation." ๐Ÿฆ‹

The client can specify these three kinds of action using Cache-Control request directives:

End-to-end reload ๐Ÿ”„ The request includes a "no-cache" Cache-Control directive or, for compatibility with HTTP/1.0 clients, Pragma: no-cache. No field names may be included with the no-cache directive in a request. The server MUST NOT use a cached copy when responding to such a request.

Specific end-to-end revalidation ๐Ÿ” The request includes a "max-age=0" Cache-Control directive, which forces each cache along the path to the origin server to revalidate its own entry, if any, with the next cache or server. The initial request includes a cache-validating conditional with the client's current validator.

Unspecified end-to-end revalidation ๐ŸŒธ The request includes "max-age=0" Cache-Control directive, which forces each cache along the path to the origin server to revalidate its own entry, if any, with the next cache or server. The initial request does not include a cache-validating conditional; the first cache along the path (if any) that holds a cache entry for this resource includes a cache-validating conditional with its current validator.

When an intermediate cache is forced, by means of a max-age=0 directive, to revalidate its own cache entry, and the client has supplied its own validator in the request, the supplied validator may differ from the validator currently stored with the cache entry. In this case, the cache may use either validator in making its own request without affecting semantic transparency. ๐Ÿซถ

However, the choice of validator may affect performance. The best approach is for the intermediate cache to use its own validator when making its request. If the server replies with 304 (Not Modified), then the cache should return its now validated copy to the client with a 200 (OK) response. If the server replies with a new entity and cache validator, however, the intermediate cache should compare the returned validator with the one provided in the client's request, using the strong comparison function. If the client's validator is equal to the origin server's, then the intermediate cache simply returns 304 (Not Modified). Otherwise, it returns the new entity with a 200 (OK) response. โœจ

If a request includes the no-cache directive, it should not include min-fresh, max-stale, or max-age.

In some cases, such as times of extremely poor network connectivity, a client may want a cache to return only those responses that it currently has stored, and not to reload or revalidate with the origin server. To do this, the client may include the only-if-cached directive in a request. If it receives this directive, a cache SHOULD either respond using a cached entry that is consistent with the other constraints of the request, or respond with a 504 (Gateway Timeout) status. However, if a group of caches is being operated as a unified system with good internal connectivity, such a request MAY be forwarded within that group of caches. ๐ŸŒˆ

Because a cache may be configured to ignore a server's specified expiration time, and because a client request may include a max-stale directive (which has a similar effect), the protocol also includes a mechanism for the origin server to require revalidation of a cache entry on any subsequent use. When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry after it becomes stale to respond to a subsequent request without first revalidating it with the origin server. (I.e., the cache must do an end-to-end revalidation every time, if, based solely on the origin server's Expires or max-age value, the cached response is stale.) ๐Ÿ‘‘

The must-revalidate directive is necessary to support reliable operation for certain protocol features. In all circumstances an HTTP/1.1 cache MUST obey the must-revalidate directive; in particular, if the cache cannot reach the origin server for any reason, it MUST generate a 504 (Gateway Timeout) response. ๐Ÿšซ

Servers should send the must-revalidate directive if and only if failure to revalidate a request on the entity could result in incorrect operation, such as a silently unexecuted financial transaction. Recipients MUST NOT take any automated action that violates this directive, and MUST NOT automatically provide an unvalidated copy of the entity if revalidation fails. ๐Ÿ’ธ

Although this is not recommended, user agents operating under severe connectivity constraints may violate this directive but, if so, MUST explicitly warn the user that an unvalidated response has been provided. The warning MUST be provided on each unvalidated access, and SHOULD require explicit user confirmation. โš ๏ธ

The proxy-revalidate directive has the same meaning as the must-revalidate directive, except that it does not apply to non-shared user agent caches. It can be used on a response to an authenticated request to permit the user's cache to store and later return the response without needing to revalidate it (since it has already been authenticated once by that user), while still requiring proxies that service many users to revalidate each time (in order to make sure that each user has been authenticated). Note that such authenticated responses also need the public cache control directive in order to allow them to be cached at all. ๐Ÿ”


14.9.5. No-Transform Directive ๐ŸŽ€

Implementers of intermediate caches (proxies) have found it useful to convert the media type of certain entity bodies. A proxy might, for example, convert between image formats in order to save cache space or to reduce the amount of traffic on a slow link. HTTP has to date been silent on these transformations. ๐Ÿ–ผ๏ธ

Serious operational problems have already occurred, however, when these transformations have been applied to entity bodies intended for certain kinds of applications. For example, applications for medical imaging, scientific data analysis and those using end-to-end authentication, all depend on receiving an entity body that is bit for bit identical to the original entity-body. ๐Ÿฉบ

Therefore, if a response includes the no-transform directive, an intermediate cache or proxy MUST NOT change those headers that are listed in section 13.5.2 as being subject to the no-transform directive. This implies that the cache or proxy must not change any aspect of the entity-body that is specified by these headers. ๐Ÿ™…โ€โ™€๏ธ


14.9.6. Cache Control Extensions ๐Ÿงฉ

The Cache-Control header field can be extended through the use of one or more cache-extension tokens, each with an optional assigned value. Informational extensions (those which do not require a change in cache behavior) may be added without changing the semantics of other directives. Behavioral extensions are designed to work by acting as modifiers to the existing base of cache directives. Both the new directive and the standard directive are supplied, such that applications which do not understand the new directive will default to the behavior specified by the standard directive, and those that understand the new directive will recognize it as modifying the requirements associated with the standard directive. In this way, extensions to the Cache-Control directives can be made without requiring changes to the base protocol. ๐Ÿง 

This extension mechanism depends on a HTTP cache obeying all of the cache-control directives defined for its native HTTP-version, obeying certain extensions, and ignoring all directives that it does not understand. ๐Ÿค“

For example, consider a hypothetical new response directive called "community" which acts as a modifier to the "private" directive. We define this new directive to mean that, in addition to any non-shared cache, any cache which is shared only by members of the community named within its value may cache the response. An origin server wishing to allow the "UCI" community to use an otherwise private response in their shared cache(s) may do so by including:

Cache-Control: private, community="UCI"

A cache seeing this header field will act correctly even if the cache does not understand the "community" cache-extension, since it will also see and understand the "private" directive and thus default to the safe behavior. ๐Ÿฅฐ

Unrecognized cache-directives MUST be ignored; it is assumed that any cache-directive likely to be unrecognized by an HTTP/1.1 cache will be combined with standard directives (or the response's default cachability) such that the cache behavior will remain minimally correct even if the cache does not understand the extension(s). ๐ŸŒŸ


14.10. Connection ๐Ÿ’…

The Connection general-header field allows the sender to specify options that are desired for that particular connection and MUST NOT be communicated by proxies over further connections. ๐Ÿ”—

The Connection header has the following grammar:

Connection-header = "Connection" ":" 1#(connection-token)
connection-token  = token

HTTP/1.1 proxies MUST parse the Connection header field before a message is forwarded and, for each connection-token in this field, remove any header field(s) from the message with the same name as the connection-token. Connection options are signaled by the presence of a connection-token in the Connection header field, not by any corresponding additional header field(s), since the additional header field may not be sent if there are no parameters associated with that connection option. HTTP/1.1 defines the "close" connection option for the sender to signal that the 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 connection should not be considered persistent (section 8.1) after the current request/response is complete. ๐Ÿšช

HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message. ๐Ÿ™‹โ€โ™€๏ธ


14.11. Content-Base ๐Ÿ“„

The Content-Base entity-header field may be used to specify the base URI for resolving relative URLs within the entity. This header field is described as Base in RFC 1808, which is expected to be revised. ๐Ÿ—บ๏ธ

Content-Base      = "Content-Base" ":" absoluteURI

If no Content-Base field is present, the base URI of an entity is defined either by its Content-Location (if that Content-Location URI is an absolute URI) or the URI used to initiate the request, in that order of precedence. Note, however, that the base URI of the contents within the entity-body may be redefined within that entity-body. ๐ŸŽฏ

14.12 Content-Encoding ๐ŸŽ€

okay so Content-Encoding is a modifier that sits on top of the media-type โœจ when it shows up, its value tells you which extra content codings got applied to the entity-body, which means which decoding steps you MUST run to get back the media-type named in Content-Type. it's mainly there so a doc can get compressed without losing its identity as whatever media type it really is ๐Ÿ’–

Content-Encoding  = "Content-Encoding" ":" 1#content-coding

Content codings are defined in section 3.5. an example looks like this ๐Ÿ’…

Content-Encoding: gzip

Content-Encoding is a characteristic of the entity identified by the Request-URI. usually the entity-body is stored with this encoding and only gets decoded right before rendering or something similar ๐Ÿซถ

If multiple encodings have been applied to an entity, the content codings MUST be listed in the order in which they were applied ๐Ÿ”ฅ

Additional information about the encoding parameters MAY be provided by other entity-header fields not defined by this specification โœจ


14.13 Content-Language ๐ŸŒˆ

the Content-Language entity-header field describes the natural language(s) of the intended audience for the enclosed entity ๐Ÿงš and lowkey, this may not be the same as every language used inside the entity-body, so keep that in mind ๐Ÿ‘‘

Content-Language  = "Content-Language" ":" 1#language-tag

Language tags are defined in section 3.10. the main point of Content-Language is to let a user identify and tell entities apart based on their own preferred language ๐Ÿ’œ so if the body is only meant for Danish readers, the field is

Content-Language: da

if no Content-Language is specified, the default is that the content is meant for every language audience ๐Ÿฆ‹ that could mean the sender doesn't think it's specific to any natural language, or that the sender just doesn't know who it's for, which is a very real vibe ๐Ÿ’€

Multiple languages MAY be listed for content meant for multiple audiences. for example, a rendition of the "Treaty of Waitangi," shown side by side in the original Maori and English versions, would call for

Content-Language: mi, en

BUT just because there are multiple languages in an entity doesn't mean it's for multiple linguistic audiences ๐Ÿ™ˆ take a beginner's language primer, like "A First Lesson in Latin," which is clearly meant for an English-literate audience. in that case, the Content-Language should only include "en" ๐Ÿ“

Content-Language may be applied to any media type. it is not limited to textual documents, so go wild ๐ŸŒธ


14.14 Content-Length ๐Ÿงš

the Content-Length entity-header field tells you the size of the message-body, in decimal octets, that gets sent to the recipient. or, when the method is HEAD, it's the size of the entity-body that would have been sent if the request had been a GET โœจ

Content-Length    = "Content-Length" ":" 1*DIGIT

an example is ๐ŸŽ€

Content-Length: 3495

Applications SHOULD use this field to indicate the size of the message-body to be transferred, no matter what the media type of the entity is ๐Ÿ’– the recipient has to be able to reliably figure out where HTTP/1.1 requests with an entity-body end. for instance, that works if the request has a valid Content-Length field, uses Transfer-Encoding: chunked, or has a multipart body ๐Ÿซถ

Any Content-Length greater than or equal to zero is a valid value ๐Ÿ”ฅ Section 4.4 explains how to work out the length of a message-body if no Content-Length is given ๐ŸŒˆ

Note: The meaning of this field is significantly different from the corresponding definition in MIME, where it is an optional field used within the "message/external-body" content-type. In HTTP, it SHOULD be sent whenever the message's length can be determined prior to being transferred. ๐Ÿ’…

14.15 Content-Location ๐Ÿฆ‹

the Content-Location entity-header field can be used to supply the resource location for the entity that's enclosed in the message โœจ when a resource has multiple entities attached, and those entities actually have their own separate locations you can use to reach them individually, the server should provide a Content-Location for the particular variant that gets returned ๐Ÿงš and a server SHOULD also provide a Content-Location for the resource that matches the response entity ๐Ÿ’œ

Content-Location = "Content-Location" ":"
                    ( absoluteURI | relativeURI )

if there's no Content-Base header field, the value of Content-Location also defines the base URL for the entity (see section 14.11) ๐ŸŽ€

The Content-Location value is NOT a replacement for the original requested URI ๐Ÿ™ˆ it's only a statement of where the resource for this particular entity lives at the time of the request. Future requests MAY use the Content-Location URI if they want to identify the source of that particular entity ๐Ÿ“

A cache cannot assume that an entity with a Content-Location that's different from the URI used to retrieve it can be used to answer later requests on that Content-Location URI ๐Ÿ’€ however, Content-Location can be used to tell apart multiple entities retrieved from a single requested resource, as described in section 13.6 ๐Ÿ”ฅ

If the Content-Location is a relative URI, it gets interpreted relative to any Content-Base URI in the response. if no Content-Base is provided, the relative URI is interpreted relative to the Request-URI ๐Ÿ‘‘


14.16 Content-MD5 ๐Ÿ”ฅ

the Content-MD5 entity-header field, as defined in RFC 1864 [23], is an MD5 digest of the entity-body. its job is to give you an end-to-end message integrity check (MIC) of the entity-body ๐Ÿ’– (Note: a MIC is good for catching accidental changes to the entity-body in transit, but it is NOT proof against malicious attacks. stay sus ๐Ÿ‘€)

Content-MD5   = "Content-MD5" ":" md5-digest

md5-digest   = <base64 of 128 bit MD5 digest as per RFC 1864>

The Content-MD5 header field may be generated by an origin server to act as an integrity check of the entity-body โœจ only origin servers may generate it. proxies and gateways MUST NOT generate it, because that would wreck its value as an end-to-end integrity check ๐Ÿ˜ญ any recipient of the entity-body, including gateways and proxies, MAY check that the digest value in this header field matches the entity-body as received ๐Ÿซถ

The MD5 digest is computed over the content of the entity-body, including any Content-Encoding that has been applied, but NOT including any Transfer-Encoding that may have been applied to the message-body. if the message comes in with a Transfer-Encoding, that encoding must be removed before checking the Content-MD5 value against the received entity ๐Ÿงš

So the digest ends up being computed on the octets of the entity-body exactly as, and in the order that, they would be sent if no Transfer-Encoding were being applied ๐ŸŒˆ

HTTP extends RFC 1864 to permit the digest to be computed for MIME composite media-types (e.g., multipart/* and message/rfc822), but that does NOT change how the digest is computed as defined in the paragraph above ๐Ÿ’…

Note: There are several consequences of this. The entity-body for composite types may contain many body-parts, each with its own MIME and HTTP headers (including Content-MD5, Content-Transfer-Encoding, and Content-Encoding headers). If a body-part has a Content-Transfer-Encoding or Content-Encoding header, it is assumed that the content of the body-part has had the encoding applied, and the body-part is included in the Content-MD5 digest as is -- i.e., after the application. The Transfer-Encoding header field is not allowed within body-parts. ๐Ÿ“
Note: while the definition of Content-MD5 is exactly the same for HTTP as in RFC 1864 for MIME entity-bodies, there are several ways in which the application of Content-MD5 to HTTP entity-bodies differs from its application to MIME entity-bodies. One is that HTTP, unlike MIME, does not use Content-Transfer-Encoding, and does use Transfer-Encoding and Content-Encoding. Another is that HTTP more frequently uses binary content types than MIME, so it is worth noting that, in such cases, the byte order used to compute the digest is the transmission byte order defined for the type. Lastly, HTTP allows transmission of text types with any of several line break conventions and not just the canonical form using CRLF. Conversion of all line breaks to CRLF should not be done before computing or checking the digest: the line break convention used in the text actually transmitted should be left unaltered when computing the digest. ๐Ÿฆ‹

14.17 Content-Range โœจ

okay bestie, so Content-Range is the header that says "this is just a slice, and here's exactly where it goes in the big picture" ๐Ÿงฉ Whenever a server sends a partial entity-body, it has to show both the range it's covering and the total length of the whole entity-body ๐Ÿ’…

Content-Range = "Content-Range" ":" content-range-spec

content-range-spec      = byte-content-range-spec

byte-content-range-spec = bytes-unit SP first-byte-pos "-"
                          last-byte-pos "/" entity-length

entity-length           = 1*DIGIT

ngl this is giving main character energy ๐ŸŽ€ Unlike byte-ranges-specifier values, a byte-content-range-spec can only cover one range, and it has to use absolute byte positions for both the first and last byte of that range ๐Ÿฆ‹

A byte-content-range-spec is invalid if its last-byte-pos is less than its first-byte-pos, or if its entity-length is less than or equal to its last-byte-pos. ๐Ÿ’€ The recipient of an invalid byte-content-range-spec MUST ignore it and any content transferred along with it. No exceptions, periodt ๐Ÿšซ

Here are some examples, assuming the entity has a total of 1234 bytes:

  • The first 500 bytes:
bytes 0-499/1234
  • The second 500 bytes:
bytes 500-999/1234
  • All except for the first 500 bytes:
bytes 500-1233/1234
  • The last 500 bytes:
bytes 734-1233/1234

When an HTTP message carries the content of a single range (like a response to a request for one range, or a request for a set of ranges that overlap with no holes), that content gets sent with a Content-Range header, plus a Content-Length header showing how many bytes were actually transferred ๐ŸŒธ For example:

HTTP/1.1 206 Partial content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-Range: bytes 21010-47021/47022
Content-Length: 26012
Content-Type: image/gif

When an HTTP message carries the content of multiple ranges (like a response to a request for several non-overlapping ranges), those get sent as a multipart MIME message ๐Ÿงš This spec defines the multipart MIME content-type for this job as "multipart/byteranges". See appendix 19.2 for its definition ๐Ÿ“–

A client that can't decode a MIME multipart/byteranges message should not ask for multiple byte-ranges in a single request. ๐Ÿ™ˆ

When a client asks for multiple byte-ranges in one request, the server SHOULD return them in the same order they appeared in the request โœจ

If the server ignores a byte-range-spec because it's invalid, the server should treat the request as if the invalid Range header field didn't exist. (Normally that means returning a 200 response with the full entity ๐Ÿ’–) The reason is that a client only makes such an invalid request when the entity is smaller than the entity retrieved by a prior request, so it's basically a sign the file shrank ๐Ÿฅน


14.18 Content-Type ๐ŸŽ€

The Content-Type entity-header field tells the recipient the media type of the entity-body. If the method is HEAD, it tells you the media type that would have been sent if the request had been a GET ๐Ÿ’œ

Content-Type   = "Content-Type" ":" media-type

Media types are defined in section 3.7. Here's an example of the field:

Content-Type: text/html; charset=ISO-8859-4

If you want more on how to figure out the media type of an entity, check out section 7.2.1 ๐Ÿ”


14.19 Date ๐Ÿ—“๏ธ

The Date general-header field shows the date and time when the message was originated. It has the same semantics as orig-date in RFC 822. The field value is an HTTP-date, as described in section 3.3.1 ๐Ÿ•ฐ๏ธ

Date  = "Date" ":" HTTP-date

Here's an example:

Date: Tue, 15 Nov 1994 08:12:31 GMT

If a message comes in over a direct connection with the user agent (for requests) or the origin server (for responses), the receiver can assume the date is the current date on their end ๐Ÿ’… But the date matters a lot for evaluating cached responses, since it's what the origin believes. That's why origin servers MUST include a Date header field in all responses ๐Ÿซถ Clients SHOULD only send a Date header field in messages that have an entity-body, like PUT and POST requests, and even then it's optional. A received message that doesn't have a Date header field SHOULD be assigned one by the recipient if that recipient is going to cache the message or gateway it through a protocol that requires a Date ๐ŸŒˆ

In theory, the date SHOULD represent the moment right before the entity is generated. In practice though, the date can be generated at any time during the message's origination without changing its semantic value โณ

The format of Date is an absolute date and time as defined by HTTP-date in section 3.3. It MUST be sent in RFC1123 [8]-date format ๐Ÿ’Œ


14.20 ETag ๐Ÿท๏ธ

The ETag entity-header field defines the entity tag for the associated entity. The headers used with entity tags are described in sections 14.20, 14.25, 14.26 and 14.43. You can use the entity tag to compare with other entities from the same resource (see section 13.3.2) ๐Ÿ”Ž

ETag = "ETag" ":" entity-tag

Examples:

ETag: "xyzzy"
ETag: W/"xyzzy"
ETag: ""

14.21 Expires โฐ

The Expires entity-header field gives the date and time after which the response should be considered stale. A stale cache entry can't normally be returned by a cache (whether it's a proxy cache or a user agent cache) unless it's validated with the origin server first, or with an intermediate cache that has a fresh copy of the entity. See section 13.2 for more on the expiration model ๐Ÿ“

The presence of an Expires field doesn't mean the original resource will change or cease to exist at, before, or after that time ๐Ÿ™ƒ

The format is an absolute date and time as defined by HTTP-date in section 3.3. It MUST be in RFC1123-date format ๐Ÿ“…

Expires = "Expires" ":" HTTP-date

An example:

Expires: Thu, 01 Dec 1994 16:00:00 GMT
Note: if a response includes a Cache-Control field with the max-age directive, that directive overrides the Expires field.

HTTP/1.1 clients and caches MUST treat other invalid date formats, especially including the value "0", as being in the past (i.e., "already expired") ๐Ÿ’€

To mark a response as "already expired," an origin server should use an Expires date that's equal to the Date header value. (Check the rules for expiration calculations in section 13.2.4 ๐Ÿงฎ)

To mark a response as "never expires," an origin server should use an Expires date about one year from the time the response is sent. HTTP/1.1 servers should not send Expires dates more than one year in the future ๐Ÿฆ‹

If a response would otherwise be non-cacheable by default, but it has an Expires header with a date in the future, that means the response is cachable, unless a Cache-Control header field (section 14.9) says otherwise ๐ŸŒธ


14.22 From ๐Ÿ“ฌ

The From request-header field, if given, SHOULD contain an Internet e-mail address for the human user who controls the requesting user agent. The address SHOULD be machine-usable, as defined by mailbox in RFC 822 (as updated by RFC 1123 ) ๐Ÿ’Œ

From   = "From" ":" mailbox

An example:

From: webmaster@w3.org

This header field MAY be used for logging purposes and as a way to identify where invalid or unwanted requests are coming from. It SHOULD NOT be used as an insecure form of access protection ๐Ÿ” The meaning of this field is that the request is being performed on behalf of the person listed, who takes responsibility for the method performed. Robot agents in particular SHOULD include this header, so the person running the robot can be contacted if something goes wrong on the receiving end ๐Ÿค–

The Internet e-mail address in this field MAY be separate from the Internet host that issued the request. For example, when a request goes through a proxy, the original issuer's address SHOULD be used ๐Ÿงš

Note: The client SHOULD not send the From header field without the user's approval, since it may conflict with the user's privacy interests or their site's security policy. It is strongly recommended that the user be able to disable, enable, and modify the value of this field at any time prior to a request. ๐Ÿซฃ

14.23 Host ๐Ÿ 

The Host request-header field specifies the Internet host and port number of the resource being requested. It's taken from the original URL the user gave, or from the referring resource (usually an HTTP URL, as described in section 3.2.2) ๐Ÿ—บ๏ธ The Host field value MUST represent the network location of the origin server or gateway given by the original URL. This is what lets the origin server or gateway tell apart URLs that look the same internally, like the root "/" URL of a server hosting multiple host names on a single IP address ๐Ÿ’œ

Host = "Host" ":" host [ ":" port ]    ; Section 3.2.2

A "host" with no trailing port information implies the default port for the service requested (for example, "80" for an HTTP URL). So a request on the origin server for <http://www.w3.org/pub/WWW/> MUST include:

GET /pub/WWW/ HTTP/1.1
Host: www.w3.org

A client MUST include a Host header field in all HTTP/1.1 request messages on the Internet (that is, any message corresponding to a request for a URL that includes an Internet host address for the service being requested) ๐Ÿซถ If the Host field isn't already there, an HTTP/1.1 proxy MUST add a Host field to the request message before forwarding it on the Internet. All Internet-based HTTP/1.1 servers MUST respond with a 400 status code to any HTTP/1.1 request message that lacks a Host header field ๐Ÿšจ

See sections 5.2 and 19.5.1 for other requirements relating to Host โœจ

14.24 If-Modified-Since ๐Ÿ•ฐ๏ธ

okay so the If-Modified-Since request-header field is used with the GET method to make it conditional ๐Ÿ’… basically, if the requested variant hasn't been modified since the time in this field, the server won't send the entity back. Instead it sends a 304 (not modified) response with no message-body โœจ

      If-Modified-Since = "If-Modified-Since" ":" HTTP-date

an example of the field:

      If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

a GET with an If-Modified-Since header and no Range header asks for the identified entity to be transferred only if it's been modified since the date in If-Modified-Since ๐ŸŽ€ the algorithm for figuring this out has these cases:

a) If the request would normally result in anything other than a 200 (OK) status, or if the passed If-Modified-Since date is invalid, the response is exactly the same as a normal GET. A date that's later than the server's current time is invalid ๐Ÿ™…โ€โ™€๏ธ

b) If the variant has been modified since the If-Modified-Since date, the response is exactly the same as a normal GET.

c) If the variant has not been modified since a valid If-Modified-Since date, the server MUST return a 304 (Not Modified) response.

the whole point of this feature is letting caches update efficiently with a minimum amount of transaction overhead ๐Ÿฆ‹

Note that the Range request-header field modifies the meaning of If-Modified-Since; see section 14.36 for full details.
Note that If-Modified-Since times are interpreted by the server, whose clock may not be synchronized with the client. ๐Ÿ•ฐ๏ธ

Note that if a client uses an arbitrary date in the If-Modified-Since header instead of a date taken from the Last-Modified header for the same request, the client should be aware that this date is interpreted using the server's understanding of time ๐Ÿงš the client should also consider unsynchronized clocks and rounding problems caused by the different encodings of time between client and server. This includes the possibility of race conditions if the document has changed between the time it was first requested and the If-Modified-Since date of a later request, and the possibility of clock-skew-related problems if the If-Modified-Since date comes from the client's clock without correction to the server's clock. Corrections for different time bases between client and server are at best approximate due to network latency ๐Ÿ˜ญ


14.25 If-Match ๐Ÿ”ฅ

the If-Match request-header field is used with a method to make it conditional. a client that has one or more entities previously obtained from the resource can check that one of those entities is still current by including a list of their associated entity tags in the If-Match header field ๐Ÿ’– the purpose of this feature is efficient updates of cached information with minimal transaction overhead. it's also used on updating requests to stop an accidental change to the wrong version of a resource ๐Ÿ™ˆ as a special case, the value "*" matches any current entity of the resource.

      If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

if any of the entity tags match the entity tag of the entity that would have been returned in the response to a similar GET request (without the If-Match header) on that resource, or if "*" is given and any current entity exists for that resource, then the server MAY perform the requested method as if the If-Match header field did not exist ๐Ÿ‘‘

a server MUST use the strong comparison function (see section 3.11) to compare the entity tags in If-Match.

if none of the entity tags match, or if "*" is given and no current entity exists, the server MUST NOT perform the requested method, and MUST return a 412 (Precondition Failed) response ๐Ÿ’€ this is most useful when the client wants to stop an updating method, like PUT, from changing a resource that changed since the client last grabbed it.

if the request would, without the If-Match header field, result in anything other than a 2xx status, then the If-Match header MUST be ignored.

the meaning of "If-Match: *" is that the method SHOULD be performed if the representation selected by the origin server (or by a cache, possibly using the Vary mechanism, see section 14.43) exists, and MUST NOT be performed if the representation does not exist ๐ŸŒˆ

a request intended to update a resource (e.g., a PUT) MAY include an If-Match header field to signal that the request method MUST NOT be applied if the entity corresponding to the If-Match value (a single entity tag) is no longer a representation of that resource. this lets the user say they don't want the request to succeed if the resource has been changed without their knowledge ๐Ÿซถ examples:

      If-Match: "xyzzy"
      If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
      If-Match: *

14.26 If-None-Match ๐ŸŒธ

the If-None-Match request-header field is used with a method to make it conditional. a client that has one or more entities previously obtained from the resource can check that none of those entities is current by including a list of their associated entity tags in the If-None-Match header field โœจ the purpose is the same as always: efficient updates of cached information with minimal transaction overhead. it's also used on updating requests to prevent an accidental change to a resource that wasn't known to exist ๐Ÿงš

as a special case, the value "*" matches any current entity of the resource.

      If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

if any of the entity tags match the entity tag of the entity that would have been returned in the response to a similar GET request (without the If-None-Match header) on that resource, or if "*" is given and any current entity exists for that resource, then the server MUST NOT perform the requested method. instead, if the request method was GET or HEAD, the server SHOULD respond with a 304 (Not Modified) response, including the cache-related entity-header fields (particularly ETag) of one of the entities that matched. for all other request methods, the server MUST respond with a status of 412 (Precondition Failed) ๐Ÿ™…โ€โ™€๏ธ

see section 13.3.3 for the rules on how to determine if two entity tags match. the weak comparison function can only be used with GET or HEAD requests ๐Ÿฆ‹

if none of the entity tags match, or if "*" is given and no current entity exists, then the server MAY perform the requested method as if the If-None-Match header field did not exist.

if the request would, without the If-None-Match header field, result in anything other than a 2xx status, then the If-None-Match header MUST be ignored.

the meaning of "If-None-Match: *" is that the method MUST NOT be performed if the representation selected by the origin server (or by a cache, possibly using the Vary mechanism, see section 14.43) exists, and SHOULD be performed if the representation does not exist. this feature may be useful in preventing races between PUT operations ๐Ÿƒโ€โ™€๏ธ

examples:

      If-None-Match: "xyzzy"
      If-None-Match: W/"xyzzy"
      If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
      If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
      If-None-Match: *

14.27 If-Range ๐ŸŽ€

okay so say a client has a partial copy of an entity in its cache and wants an up-to-date copy of the whole entity ๐Ÿ’… it could use the Range request-header with a conditional GET (using either or both of If-Unmodified-Since and If-Match). but if the condition fails because the entity was modified, the client would then have to make a second request to get the entire current entity-body. ugh, so much extra work ๐Ÿ˜ฉ

the If-Range header lets a client "short-circuit" that second request โญ informally, its meaning is `if the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity.'

       If-Range = "If-Range" ":" ( entity-tag | HTTP-date )

if the client has no entity tag for an entity, but does have a Last-Modified date, it may use that date in an If-Range header. (The server can distinguish between a valid HTTP-date and any form of entity-tag by examining no more than two characters.) the If-Range header should only be used together with a Range header, and must be ignored if the request does not include a Range header, or if the server does not support the sub-range operation ๐Ÿงฉ

if the entity tag given in the If-Range header matches the current entity tag for the entity, then the server should provide the specified sub-range of the entity using a 206 (Partial content) response ๐Ÿ“ if the entity tag does not match, then the server should return the entire entity using a 200 (OK) response.


14.28 If-Unmodified-Since ๐ŸŒˆ

the If-Unmodified-Since request-header field is used with a method to make it conditional. if the requested resource has not been modified since the time in this field, the server should perform the requested operation as if the If-Unmodified-Since header weren't there โœจ

if the requested variant has been modified since the specified time, the server MUST NOT perform the requested operation, and MUST return a 412 (Precondition Failed) ๐Ÿ™…โ€โ™€๏ธ

      If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date

an example of the field:

      If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT

if the request would normally (i.e., without the If-Unmodified-Since header) result in anything other than a 2xx status, the If-Unmodified-Since header should be ignored.

if the specified date is invalid, the header is ignored ๐Ÿซ 


14.29 Last-Modified ๐Ÿ’œ

the Last-Modified entity-header field tells you the date and time when the origin server believes the variant was last modified ๐Ÿ•ฐ๏ธ

      Last-Modified  = "Last-Modified" ":" HTTP-date

an example of its use:

      Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT

what this header means depends on the implementation of the origin server and the nature of the original resource ๐Ÿงš for files, it might just be the file system last-modified time. for entities with dynamically included parts, it might be the most recent of the last-modify times for its component parts. for database gateways, it might be the last-update timestamp of the record. for virtual objects, it might be the last time the internal state changed ๐Ÿ’…

an origin server MUST NOT send a Last-Modified date which is later than the server's time of message origination. in cases where the resource's last modification would point to some time in the future, the server MUST replace that date with the message origination date ๐Ÿ™ˆ

an origin server should get the Last-Modified value of the entity as close as possible to the time it generates the Date value of its response. this lets a recipient make an accurate assessment of the entity's modification time, especially if the entity changes near the time the response is generated ๐Ÿฆ‹

HTTP/1.1 servers SHOULD send Last-Modified whenever feasible. ๐ŸŒธ

14.30 Location โœจ

okay so the Location response-header field is how a server tells you to go somewhere other than the Request-URI ๐Ÿฆ‹, either to finish your request or to find a brand new resource. for 201 (Created) responses, Location is the address of the new resource your request just made, which is so iconic ๐Ÿ’–. for 3xx responses, the location SHOULD indicate the server's preferred URL for automatic redirection to the resource. the field value is one single absolute URL, no cap ๐ŸŽ€

Location       = "Location" ":" absoluteURI

an example is:

Location: http://www.w3.org/pub/WWW/People.html
๐Ÿ“ bestie, the Content-Location header field (section 14.15) is different from Location ๐Ÿซถ. Content-Location identifies the original location of the entity enclosed in the request. so it's totally possible for a response to have header fields for both Location and Content-Location ๐ŸŒˆ. also see section 13.10 for cache requirements of some methods ๐Ÿงš

14.31 Max-Forwards ๐Ÿงš

the Max-Forwards request-header field can be used with the TRACE method (section 14.31) to limit how many proxies or gateways can forward the request to the next inbound server ๐Ÿ’…. this is so useful when a client is trying to trace a request chain that seems to be failing or looping mid-chain ๐Ÿ˜ญ.

Max-Forwards   = "Max-Forwards" ":" 1*DIGIT

the Max-Forwards value is a decimal integer showing how many more times this request message may be forwarded ๐Ÿ“.

every proxy or gateway that receives a TRACE request with a Max-Forwards header field SHOULD check and update its value before forwarding it ๐Ÿ”ฅ. if the received value is zero (0), the recipient SHOULD NOT forward the request. instead, it SHOULD respond as the final recipient with a 200 (OK) response containing the received request message as the response entity-body (as described in section 9.8) ๐Ÿ’–. if the received Max-Forwards value is greater than zero, then the forwarded message SHOULD contain an updated Max-Forwards field with a value decremented by one (1) โœจ.

the Max-Forwards header field SHOULD be ignored for all other methods defined by this specification, and for any extension methods where it isn't explicitly referred to as part of that method definition ๐Ÿ™ˆ.

14.32 Pragma ๐Ÿ’…

the Pragma general-header field is used to include implementation-specific directives that may apply to any recipient along the request/response chain ๐Ÿฆ‹. all pragma directives specify optional behavior from the viewpoint of the protocol, but some systems MAY require that behavior be consistent with the directives ๐Ÿ‘‘.

Pragma            = "Pragma" ":" 1#pragma-directive

pragma-directive  = "no-cache" | extension-pragma
extension-pragma  = token [ "=" ( token | quoted-string ) ]

when the no-cache directive is in a request message, an application SHOULD forward the request toward the origin server, even if it has a cached copy of what's being requested ๐ŸงŠ. this pragma directive has the same semantics as the no-cache cache-directive (see section 14.9), and it's defined here for backwards compatibility with HTTP/1.0 ๐Ÿ•ฐ๏ธ. clients SHOULD include both header fields when a no-cache request is sent to a server that isn't known to be HTTP/1.1 compliant ๐ŸŽ€.

pragma directives MUST be passed through by a proxy or gateway application, regardless of their significance to that application ๐Ÿซถ, since the directives may be applicable to all recipients along the request/response chain. you can't specify a pragma for one specific recipient ๐Ÿ™…โ€โ™€๏ธ. however, any pragma directive that isn't relevant to a recipient SHOULD be ignored by that recipient ๐ŸŒธ.

HTTP/1.1 clients SHOULD NOT send the Pragma request-header ๐Ÿšซ. HTTP/1.1 caches SHOULD treat Pragma: no-cache as if the client had sent Cache-Control: no-cache โœจ. no new Pragma directives will be defined in HTTP, so this one's kinda the final boss ๐Ÿ‘‘.

14.33 Proxy-Authenticate ๐ŸŒธ

the Proxy-Authenticate response-header field MUST be included as part of a 407 (Proxy Authentication Required) response ๐Ÿ”. the field value is a challenge that shows the authentication scheme and parameters that apply to the proxy for this Request-URI ๐Ÿ’œ.

Proxy-Authenticate  = "Proxy-Authenticate" ":" challenge

the HTTP access authentication process is described in section 11 ๐Ÿงš. unlike WWW-Authenticate, the Proxy-Authenticate header field only applies to the current connection, so it SHOULD NOT be passed on to downstream clients ๐Ÿ™…โ€โ™€๏ธ. the only exception is that an intermediate proxy might need its own credentials, so it asks the downstream client for them. in some circumstances that looks like the proxy is forwarding the Proxy-Authenticate header field, but it's really not ๐Ÿ˜ญ.

14.34 Proxy-Authorization ๐Ÿ”

the Proxy-Authorization request-header field lets the client identify itself (or its user) to a proxy that requires authentication ๐Ÿซถ. the field value is credentials holding the user agent's authentication info for the proxy and/or the realm of the resource being requested ๐Ÿฆ‹.

Proxy-Authorization     = "Proxy-Authorization" ":" credentials

the HTTP access authentication process is described in section 11 ๐Ÿ’…. unlike Authorization, the Proxy-Authorization header field only applies to the next outbound proxy that demanded authentication using the Proxy-Authenticate field ๐Ÿ‘‘. when multiple proxies are chained together, the Proxy-Authorization header field gets consumed by the first outbound proxy that was expecting credentials ๐ŸŒˆ. a proxy MAY relay the credentials from the client request to the next proxy, if that's how the proxies cooperatively authenticate a given request ๐Ÿค.

14.35 Public ๐ŸŒˆ

the Public response-header field lists the set of methods the server supports โœจ. its whole purpose is to tell the recipient what the server can do regarding unusual methods ๐Ÿงš. the methods listed may or may not apply to the Request-URI, and the Allow header field (section 14.7) MAY be used to show which methods are allowed for a particular URI ๐Ÿ’–.

Public         = "Public" ":" 1#method

example of use:

Public: OPTIONS, MGET, MHEAD, GET, HEAD

this header field only applies to the server directly connected to the client, which is the nearest neighbor in a chain of connections ๐Ÿซถ. if the response goes through a proxy, the proxy MUST either remove the Public header field or replace it with one that applies to its own capabilities ๐Ÿ”ฅ.

14.36 Range ๐Ÿ“

14.36.1 Byte Ranges ๐Ÿฆ‹

since all HTTP entities are represented in HTTP messages as sequences of bytes, the concept of a byte range makes sense for any HTTP entity โœจ. (however, not all clients and servers need to support byte-range operations ๐Ÿ’….)

byte range specifications in HTTP apply to the sequence of bytes in the entity-body, which isn't necessarily the same as the message-body ๐ŸงŠ.

a byte range operation can specify a single range of bytes, or a set of ranges within a single entity ๐ŸŒธ.

ranges-specifier = byte-ranges-specifier

byte-ranges-specifier = bytes-unit "=" byte-range-set

byte-range-set  = 1#( byte-range-spec | suffix-byte-range-spec )

byte-range-spec = first-byte-pos "-" [last-byte-pos]

first-byte-pos  = 1*DIGIT

last-byte-pos   = 1*DIGIT

the first-byte-pos value in a byte-range-spec gives the byte-offset of the first byte in a range ๐ŸŽ€. the last-byte-pos value gives the byte-offset of the last byte in the range, which means the byte positions specified are inclusive ๐Ÿ’œ. byte offsets start at zero ๐Ÿงš.

if the last-byte-pos value is present, it must be greater than or equal to the first-byte-pos in that byte-range-spec, or the byte-range-spec is invalid ๐Ÿ™…โ€โ™€๏ธ. the recipient of an invalid byte-range-spec must ignore it ๐Ÿ—‘๏ธ.

if the last-byte-pos value is absent, or if the value is greater than or equal to the current length of the entity-body, last-byte-pos is taken to be equal to one less than the current length of the entity-body in bytes ๐Ÿ‘‘.

by choosing its last-byte-pos, a client can limit how many bytes it retrieves without knowing the size of the entity ๐Ÿซถ.

suffix-byte-range-spec = "-" suffix-length

suffix-length = 1*DIGIT

a suffix-byte-range-spec specifies the suffix of the entity-body, with a length given by the suffix-length value ๐ŸŒˆ. (in other words, this form asks for the last N bytes of an entity-body.) if the entity is shorter than the specified suffix-length, the entire entity-body is used ๐Ÿฆ‹.

examples of byte-ranges-specifier values (assuming an entity-body of length 10000):

  • the first 500 bytes (byte offsets 0-499, inclusive):
bytes=0-499
  • the second 500 bytes (byte offsets 500-999, inclusive):
bytes=500-999
  • the final 500 bytes (byte offsets 9500-9999, inclusive):
bytes=-500
  • or:
bytes=9500-
  • the first and last bytes only (bytes 0 and 9999):
bytes=0-0,-1
  • several legal but not canonical specifications of the second 500 bytes (byte offsets 500-999, inclusive):
bytes=500-600,601-999

bytes=500-700,601-999

14.36.2 Range Retrieval Requests ๐Ÿ“

HTTP retrieval requests using conditional or unconditional GET methods may ask for one or more sub-ranges of the entity, instead of the whole thing ๐Ÿง. they do this with the Range request header, which applies to the entity returned as the result of the request ๐Ÿ’–:

Range = "Range" ":" ranges-specifier

a server MAY ignore the Range header ๐Ÿ™ˆ. however, HTTP/1.1 origin servers and intermediate caches SHOULD support byte ranges when possible, since Range supports efficient recovery from partially failed transfers and efficient partial retrieval of large entities ๐Ÿ”ฅ.

if the server supports the Range header and the specified range or ranges are appropriate for the entity:

  • the presence of a Range header in an unconditional GET changes what gets returned if the GET is otherwise successful. in other words, the response carries a status code of 206 (Partial Content) instead of 200 (OK) โœจ.
  • the presence of a Range header in a conditional GET (a request using one or both of If-Modified-Since and If-None-Match, or one or both of If-Unmodified-Since and If-Match) changes what gets returned if the GET is otherwise successful and the condition is true. it doesn't affect the 304 (Not Modified) response returned if the conditional is false ๐ŸŒธ.

in some cases, it may be more appropriate to use the If-Range header (see section 14.27) in addition to the Range header ๐Ÿฆ‹.

if a proxy that supports ranges receives a Range request, forwards the request to an inbound server, and receives an entire entity in reply, it SHOULD only return the requested range to its client ๐Ÿซถ. it SHOULD store the entire received response in its cache, if that's consistent with its cache allocation policies ๐Ÿ’….

14.37 Referer โœจ

okay bestie, so the Referer request-header field lets the client tell the server (for the server's benefit ๐Ÿ’…) the address (URI) of the resource the Request-URI was obtained from. that's the "referrer" ๐Ÿฆ‹ yes the header is misspelled, and no we are not fixing it, it's iconic actually ๐Ÿ˜ญ servers can use it to make lists of back-links for interest, logging, optimized caching, etc. ๐ŸŒธ it also helps trace obsolete or mistyped links for maintenance. the big rule is that the Referer field MUST NOT be sent if the Request-URI came from a source with no URI of its own, like input from the user's keyboard โŒจ๏ธ no URI, no referer, periodt ๐Ÿ™…โ€โ™€๏ธ

Referer        = "Referer" ":" ( absoluteURI | relativeURI )

Example:

Referer: http://www.w3.org/hypertext/DataSources/Overview.html

so if the field value is a partial URI, it SHOULD be interpreted relative to the Request-URI ๐Ÿงš and the URI MUST NOT include a fragment โœจ

Note: Because the source of a link may be private information or may reveal an otherwise private information source, it is strongly recommended that the user be able to select whether or not the Referer field is sent. For example, a browser client could have a toggle switch for browsing openly/anonymously, which would respectively enable/disable the sending of Referer and From information. ๐Ÿ™ˆ๐Ÿ”’

14.38 Retry-After ๐ŸŽ€

the Retry-After response-header field can be used with a 503 (Service Unavailable) response to say how long the service is expected to be unavailable to the requesting client โณ the value can be either an HTTP-date or an integer number of seconds (in decimal) after the time of the response. very organized, very mature ๐Ÿ’…

Retry-After  = "Retry-After" ":" ( HTTP-date | delta-seconds )

two examples of its use:

Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120

in the latter example, the delay is 2 minutes โฐ literally just wait 2 minutes bestie ๐Ÿซถ


14.39 Server ๐Ÿ“

the Server response-header field contains info about the software the origin server used to handle the request ๐Ÿ‘€ the field can hold multiple product tokens (section 3.8) and comments that identify the server and any significant subproducts. the product tokens are listed in order of how significant they are for identifying the application, so the most important one goes first ๐Ÿ‘‘

Server         = "Server" ":" 1*( product | comment )

Example:

Server: CERN/3.0 libwww/2.17

if the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server response-header ๐Ÿ™…โ€โ™€๏ธ instead, it SHOULD include a Via field (as described in section 14.44) ๐Ÿฆ‹

Note: Revealing the specific software version of the server may allow the server machine to become more vulnerable to attacks against software that is known to contain security holes. Server implementers are encouraged to make this field a configurable option. ๐Ÿ’€๐Ÿšจ this one is serious bestie, don't just leave the version lying around for hackers to find ๐Ÿ˜ญ

14.40 Transfer-Encoding ๐ŸŒˆ

the Transfer-Encoding general-header field tells you what (if any) kind of transformation has been applied to the message body so it can be sent safely between the sender and the recipient โœจ this is different from Content-Encoding, because the transfer coding is a property of the message, not of the entity ๐Ÿ’œ

Transfer-Encoding       = "Transfer-Encoding" ":" 1#transfer-
coding

transfer codings are defined in section 3.6 ๐ŸŽ€ an example:

Transfer-Encoding: chunked

fair warning though: a lot of older HTTP/1.0 applications don't understand the Transfer-Encoding header ๐Ÿ˜ญ


14.41 Upgrade ๐Ÿš€

the Upgrade general-header lets the client say which additional communication protocols it supports and would like to use, if the server finds it appropriate to switch protocols ๐Ÿฆ‹ the server MUST use the Upgrade header field within a 101 (Switching Protocols) response to show which protocol(s) are being switched to โœจ

Upgrade        = "Upgrade" ":" 1#product

for example:

Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

the Upgrade header field is meant to be a simple way to transition from HTTP/1.1 to some other, incompatible protocol ๐ŸŒธ the client advertises that it wants another protocol, like a later version of HTTP with a higher major version number, even though the current request is made using HTTP/1.1. so it starts the request in the more commonly supported protocol while telling the server it'd love a "better" protocol if one is available ๐Ÿ’– (where "better" is decided by the server, maybe based on the method and/or resource being requested) main character energy, honestly ๐Ÿ‘‘

the Upgrade header field only applies to switching application-layer protocols on the existing transport-layer connection ๐Ÿ”Œ Upgrade can't be used to insist on a protocol change, since accepting and using it is optional for the server ๐Ÿ™…โ€โ™€๏ธ the capabilities and nature of the application-layer communication after the change depend entirely on the new protocol chosen, although the first action after changing protocols MUST be a response to the initial HTTP request containing the Upgrade header field ๐Ÿซถ

the Upgrade header field only applies to the immediate connection. so the upgrade keyword MUST be supplied within a Connection header field (section 14.10) whenever Upgrade is present in an HTTP/1.1 message ๐Ÿ”‘

the Upgrade header field cannot be used to switch to a protocol on a different connection ๐Ÿ™…โ€โ™€๏ธ for that, it's more appropriate to use a 301, 302, 303, or 305 redirection response ๐Ÿฆ‹

this spec only defines the protocol name "HTTP" for use by the family of Hypertext Transfer Protocols, as defined by the HTTP version rules of section 3.1 and future updates to this specification ๐Ÿ’… any token can be used as a protocol name, but it's only useful if both the client and server associate that name with the same protocol ๐Ÿงš


14.42 User-Agent ๐ŸŒธ

the User-Agent request-header field has info about the user agent that's sending the request ๐Ÿ‘€ it's for statistics, tracing protocol violations, and automatically recognizing user agents so responses can be tailored to avoid particular user agent limitations ๐ŸŽ€ user agents SHOULD include this field with requests ๐Ÿ’– it can hold multiple product tokens (section 3.8) and comments identifying the agent and any subproducts that form a significant part of it. by convention, the product tokens are listed in order of significance for identifying the application ๐Ÿ‘‘

User-Agent     = "User-Agent" ":" 1*( product | comment )

Example:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

14.43 Vary ๐Ÿฆ‹

the Vary response-header field is how a server signals that the response entity was picked from the available representations using server-driven negotiation (section 12) ๐Ÿงš field-names listed in Vary headers are request-headers. the Vary value either says the listed header fields cover all the dimensions the representation might vary over, or that the dimensions are unspecified ("*"), which means they can vary over any aspect of future requests ๐ŸŒˆ

Vary  = "Vary" ":" ( "*" | 1#field-name )

an HTTP/1.1 server MUST include an appropriate Vary header field with any cachable response that is subject to server-driven negotiation โœจ doing so lets a cache correctly interpret future requests on that resource, and tells the user agent that negotiation is happening on it ๐Ÿซถ a server SHOULD include an appropriate Vary header field with a non-cachable response that is subject to server-driven negotiation too, since it might give the user agent useful info about the dimensions the response could vary over ๐Ÿ’œ

the set of header fields named by the Vary value is known as the "selecting" request-headers ๐ŸŽ€

when a cache gets a later request whose Request-URI matches one or more cache entries with a Vary header, the cache MUST NOT use that cache entry to build a response to the new request unless all of the headers named in the cached Vary header are present in the new request, and all the stored selecting request-headers from the previous request match the corresponding headers in the new request ๐Ÿ™…โ€โ™€๏ธ it's giving strict bouncer energy ๐Ÿ˜ญ

the selecting request-headers from two requests match if and only if the ones in the first request can be turned into the ones in the second request by adding or removing linear whitespace (LWS) where the corresponding BNF allows it, and/or by combining multiple message-header fields with the same field name following the rules about message headers in section 4.2 ๐ŸŒธ

a Vary value of "*" means unspecified parameters play a role in picking the response representation, possibly other than the request-header contents (like the client's network address) ๐Ÿ‘€ later requests on that resource can only be properly interpreted by the origin server, so a cache MUST forward a (possibly conditional) request even when it has a fresh response cached for the resource ๐Ÿงš see section 13.6 for how caches use the Vary header ๐Ÿฆ‹

a Vary value that's a list of field-names means the representation was chosen with a selection algorithm that considers ONLY the listed request-header field values ๐Ÿ’… a cache MAY assume the same selection will be made for future requests with the same values for those listed field names, for as long as the response is fresh โœจ

the field-names given aren't limited to the standard request-header fields defined by this spec ๐ŸŒˆ and field names are case-insensitive ๐Ÿ’–

14.44 Via ๐Ÿฆ‹

okay bestie, the Via general-header is how gateways and proxies MUST leave a trail of every middleman between the user agent and the server (on requests) and between the origin server and the client (on responses) ๐Ÿ•ต๏ธโ€โ™€๏ธ. It's basically the "Received" energy from RFC 822 โœจ. The point is tracking where messages have been forwarded, avoiding request loops, and seeing what protocol capabilities every sender along the chain had ๐Ÿ’….

Via =  "Via" ":" 1#( received-protocol received-by [ comment ] )

received-protocol = [ protocol-name "/" ] protocol-version
protocol-name     = token
protocol-version  = token
received-by       = ( host [ ":" port ] ) | pseudonym
pseudonym         = token

The received-protocol tells you which protocol version the message arrived with at each hop ๐ŸŒธ. Every time a message gets forwarded, that version gets tacked onto the Via value, so the upstream capabilities stay visible to everyone downstream ๐Ÿ‘‘.

The protocol-name is optional if and only if it would be "HTTP" ๐ŸŽ€. The received-by field is usually the host (plus optional port) of the server or client that forwarded the message onward ๐Ÿ’–. But if the real host is sensitive info, it MAY be swapped out for a pseudonym ๐Ÿซถ. And if the port isn't given, it MAY be assumed to be the default port of the received-protocol ๐Ÿ“.

Multiple Via values represent each proxy or gateway that forwarded the message ๐Ÿงš. Each recipient MUST append its own info so the final list is in the exact order the messages were forwarded ๐Ÿ“œ.

Comments MAY be used in Via to identify the software of the recipient proxy or gateway, kind of like the User-Agent and Server headers ๐Ÿ’œ. BUT all comments in Via are optional and MAY be removed by any recipient before forwarding ๐Ÿ™ˆ.

Here's a cute example. A request goes from an HTTP/1.0 user agent to an internal proxy code-named "fred", which uses HTTP/1.1 to forward it to a public proxy at nowhere.com, which finishes the job by forwarding it to the origin server at www.ics.uci.edu. The request that www.ics.uci.edu receives would then have this Via header field:

Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)

Proxies and gateways used as a portal through a network firewall SHOULD NOT, by default, forward the names and ports of hosts inside the firewall region ๐Ÿ”ฅ. That info SHOULD only get propagated if it's explicitly enabled ๐Ÿ”. If it's not enabled, the received-by host of any host behind the firewall SHOULD be replaced by an appropriate pseudonym for that host ๐ŸŒˆ.

For orgs with strong privacy needs about hiding their internal structure, a proxy MAY combine an ordered subsequence of Via entries that share identical received-protocol values into one entry โœจ. For example, this:

Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

could be collapsed to this:

Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
Applications SHOULD NOT combine multiple entries unless they're all under the same organizational control AND the hosts have already been replaced by pseudonyms. Applications MUST NOT combine entries that have different received-protocol values. Don't get creative with this, bestie ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’€

14.45 Warning โš ๏ธ

The Warning response-header is extra info about a response's status that the status code doesn't show ๐Ÿ‘€. It's usually (not always) about a possible lack of semantic transparency from caching operations ๐Ÿง.

Warning headers get sent with responses using this grammar:

Warning    = "Warning" ":" 1#warning-value

warning-value = warn-code SP warn-agent SP warn-text
warn-code  = 2DIGIT
warn-agent = ( host [ ":" port ] ) | pseudonym
                ; the name or pseudonym of the server adding
                ; the Warning header, for use in debugging
warn-text  = quoted-string

A response may carry more than one Warning header ๐Ÿ’–.

The warn-text should be in a natural language and character set that a human reading the response is most likely to understand ๐ŸŒ. You can base that on any info you have, like where the cache or user is, the Accept-Language field in a request, the Content-Language field in a response, etc. The default language is English and the default character set is ISO-8859-1 ๐Ÿ‡ฌ๐Ÿ‡ง.

If a character set other than ISO-8859-1 is used, it MUST be encoded in the warn-text using the method described in RFC 1522 [14] ๐Ÿช„.

Any server or cache can add Warning headers to a response. New ones should be added after any existing Warning headers ๐Ÿ“. A cache MUST NOT delete any Warning header it received with a response ๐Ÿ™…โ€โ™€๏ธ. BUT if a cache successfully validates a cache entry, it SHOULD remove any Warning headers previously attached to that entry, except as specified for specific Warning codes ๐Ÿงน. It MUST then add any Warning headers received in the validating response ๐Ÿ’…. In other words, Warning headers are the ones that would be attached to the most recent relevant response ๐Ÿ‘‘.

When multiple Warning headers are attached to a response, the user agent SHOULD display as many as possible, in the order they appear in the response ๐Ÿซง. If it's not possible to display all the warnings, the user agent should follow these heuristics:

  • Warnings that appear early in the response take priority over those appearing later in the response.
  • Warnings in the user's preferred character set take priority over warnings in other character sets, but only with identical warn-codes and warn-agents.

Systems that generate multiple Warning headers should order them with this user agent behavior in mind ๐Ÿง .

This is the list of currently-defined warn-codes, each with a recommended warn-text in English and a description of what it means ๐Ÿ“‹:

  • 10 Response is stale: MUST be included whenever the returned response is stale. A cache may add this warning to any response, but may never remove it until the response is known to be fresh. ๐Ÿฅ€
  • 11 Revalidation failed: MUST be included if a cache returns a stale response because an attempt to revalidate the response failed, due to an inability to reach the server. A cache may add this warning to any response, but may never remove it until the response is successfully revalidated. ๐Ÿ”Œ
  • 12 Disconnected operation: SHOULD be included if the cache is intentionally disconnected from the rest of the network for a period of time. ๐Ÿ“ด
  • 13 Heuristic expiration: MUST be included if the cache heuristically chose a freshness lifetime greater than 24 hours and the response's age is greater than 24 hours. โฐ
  • 14 Transformation applied: MUST be added by an intermediate cache or proxy if it applies any transformation changing the content-coding (as specified in the Content-Encoding header) or media-type (as specified in the Content-Type header) of the response, unless this Warning code already appears in the response. MUST NOT be deleted from a response even after revalidation. ๐ŸŽจ
  • 99 Miscellaneous warning: The warning text may include arbitrary information to be presented to a human user, or logged. A system receiving this warning MUST NOT take any automated action. ๐Ÿคทโ€โ™€๏ธ

14.46 WWW-Authenticate ๐Ÿ”‘

The WWW-Authenticate response-header MUST be included in 401 (Unauthorized) response messages ๐Ÿšช. Its field value is at least one challenge that tells you which authentication scheme(s) and parameters apply to the Request-URI ๐Ÿ—๏ธ.

WWW-Authenticate  = "WWW-Authenticate" ":" 1#challenge

The HTTP access authentication process is described in section 11 ๐Ÿ“–. User agents MUST take special care when parsing the WWW-Authenticate field value if it has more than one challenge, or if more than one WWW-Authenticate header field is provided ๐Ÿง. Why? Because a challenge can itself contain a comma-separated list of authentication parameters, so it gets messy fast ๐Ÿ˜ญ.


15. Security Considerations ๐Ÿ”

this section is here to inform application developers, info providers, and users about the security limitations in HTTP/1.1 as described by this document ๐Ÿ›ก๏ธ. It does NOT have definitive solutions to the problems it reveals, though it does suggest some ways to reduce security risks ๐Ÿซถ.

15.1 Authentication of Clients ๐Ÿชช

ok bestie, real talk: the Basic authentication scheme is NOT a secure way to authenticate users ๐Ÿ’€. It doesn't protect the entity either, which gets sent in clear text across whatever physical network is carrying it ๐Ÿซ . HTTP doesn't stop you from adding extra authentication schemes and encryption to make things safer, or from adding enhancements (like one-time passwords) on top of Basic ๐Ÿ”ฅ.

The most serious flaw in Basic authentication is that it leads to the essentially clear text transmission of the user's password over the physical network ๐Ÿ˜ฑ. That's the exact problem Digest Authentication is trying to fix ๐Ÿฆ‹.

Because Basic authentication involves clear text transmission of passwords, it SHOULD never be used (without enhancements) to protect sensitive or valuable information ๐Ÿšซ.

Basic auth is also commonly used just for identification, like making users type a username and password so the server can gather accurate usage stats ๐Ÿ“Š. When it's used this way, it's super tempting to think there's no danger if illicit access to the protected docs isn't a big deal ๐Ÿ™ƒ. That's only correct if the server issues both the username and password to users, and in particular does NOT let users pick their own password ๐Ÿ™…โ€โ™€๏ธ. The danger is that naive users keep reusing one password to avoid juggling a bunch of them ๐Ÿ.

If a server lets users choose their own passwords, the threat isn't just illicit access to documents on the server. It's illicit access to the accounts of every user who picked the same password for their account ๐Ÿ˜ญ. If users get to choose their own password, the server also has to keep files containing the (presumably encrypted) passwords ๐Ÿ—‚๏ธ. Lots of these may be account passwords of users who are maybe at distant sites ๐ŸŒ. The owner or admin of a system like that could potentially be liable if that info isn't kept secure ๐Ÿ’ผโš–๏ธ.

Basic Authentication is also vulnerable to spoofing by counterfeit servers ๐Ÿ‘ป. If a user is led to believe they're connecting to a host with info protected by basic authentication, when they're actually connecting to a hostile server or gateway, the attacker can request a password, store it for later, and then fake an error ๐Ÿ˜ˆ. This kind of attack is NOT possible with Digest Authentication [32] ๐Ÿ’…. Server implementers SHOULD guard against this sort of counterfeiting by gateways or CGI scripts ๐Ÿšจ. In particular, it's very dangerous for a server to just hand a connection over to a gateway, because that gateway can then use the persistent connection mechanism to run multiple transactions with the client while impersonating the original server in a way the client can't detect ๐Ÿง›โ€โ™€๏ธ๐Ÿ’€

15.2 Offering a Choice of Authentication Schemes ๐ŸŽ€

okay so a server is allowed to send multiple challenges with a 401 (Authenticate) response, and each challenge can use a different scheme ๐Ÿ’… the order they show up in is the order the server would prefer them to be picked. the server should put its "most secure" scheme first ๐Ÿ” and the user agent should pick the first challenge it actually understands to show the user โœจ

bestie, here's the twist ๐Ÿ™ˆ when the server offers a bunch of schemes in the WWW-Authenticate header, the "security" of the whole thing is only as [...] a malicious user could capture the set of challenges and try to log in with the weakest scheme on the list ๐Ÿ’€ so the ordering is really there to protect the user's credentials more than the server's info ๐Ÿซถ

and then there's the sneaky MITM ๐Ÿ•ต๏ธโ€โ™€๏ธ attack where someone slips a weak scheme into the list, hoping the client picks one that exposes the user's credentials (ex. a password). so the client should always use the strongest scheme it understands from the choices it accepted ๐Ÿ’ช

it gets worse!! ๐Ÿ˜ญ an even better MITM attack would be to remove every offered choice and insert a challenge asking for Basic authentication. user agents that care about this kind of attack could remember the strongest scheme a server ever requested, and show a warning that needs the user to confirm before they use a weaker one ๐Ÿ›ก๏ธ and the most iconic (in a terrible way) version of this attack is offering a "free" proxy caching service to gullible users ๐Ÿ™ƒ

15.3 Abuse of Server Log Information ๐Ÿ“œ

a server is literally in the position to save personal data about a user's requests, which can reveal their reading patterns or what they're interested in ๐Ÿ‘€ this info is super confidential, and the law in some countries might limit what can be done with it โš–๏ธ people using HTTP to provide data are responsible for making sure that material isn't distributed without permission from anyone who can be identified in the published results ๐Ÿซถ

15.4 Transfer of Sensitive Information ๐Ÿ”’

HTTP is like any generic data transfer protocol, so it can't control what's inside the data it moves ๐Ÿ™…โ€โ™€๏ธ and there's no built-in way to tell how sensitive a piece of info is within a given request. so applications SHOULD give the info provider as much control over it as possible ๐Ÿ’– four header fields are worth special mention here: Server, Via, Referer and From ๐Ÿ‘‘

first up, Server. revealing the exact software version can make the server machine more vulnerable to attacks on software with known security holes ๐Ÿ’€ so implementers SHOULD make the Server header field a configurable option ๐ŸŽ€

proxies that act as a portal through a network firewall SHOULD take special precautions with header info that identifies the hosts behind the firewall โœจ in particular, they SHOULD remove, or replace with sanitized versions, any Via fields generated behind the firewall ๐Ÿงš

the Referer field lets people study reading patterns and draw reverse links ๐Ÿ” it's super useful, but its power can be abused if user details aren't separated from the info in the Referer. even after personal info is removed, the Referer might still show a private document's URI, and publishing that would be inappropriate ๐Ÿ˜ญ

the From field might clash with the user's privacy or their site's security policy, so it SHOULD NOT be sent unless the user can disable, enable, and modify its contents. the user MUST be able to set the contents of this field in a user preference or application defaults configuration ๐Ÿ”

we suggest (though we don't require it!) that a convenient toggle be provided so users can turn sending From and Referer info on or off ๐ŸŒธ

15.5 Attacks Based On File and Path Names ๐Ÿ“

implementations of HTTP origin servers SHOULD be careful to only return documents that the server administrators actually meant to be returned ๐Ÿ™…โ€โ™€๏ธ if an HTTP server translates HTTP URIs straight into file system calls, the server MUST take special care not to serve files that weren't meant for HTTP clients ๐Ÿšซ for example, UNIX, Microsoft Windows, and other OSes use ".." as a path component to mean one directory level up ๐Ÿ’… so on those systems, an HTTP server MUST disallow any such construct in the Request-URI if it would otherwise allow access to a resource outside what's meant to be reachable through the HTTP server ๐Ÿ˜ค

files meant only for internal reference (like access control files, configuration files, and script code) MUST be protected from inappropriate retrieval, since they might have sensitive info ๐Ÿ”’ and history backs this up: minor bugs in these server implementations have turned into real security risks ๐Ÿ’€

15.6 Personal Information ๐Ÿซฃ

HTTP clients are often holding huge amounts of personal info (ex. the user's name, location, mail address, passwords, encryption keys, etc.) ๐Ÿ˜ณ so they SHOULD be very careful to stop this info from accidentally leaking over HTTP to other sources ๐Ÿ›ก๏ธ we very strongly recommend a convenient interface so the user can control where this info goes, and for designers and implementers to be extra careful here ๐Ÿ’– honestly, history shows that mistakes in this area are often serious security and/or privacy problems, and they tend to bring really bad press for the implementer's company ๐Ÿ“ฐ๐Ÿ’€

15.7 Privacy Issues Connected to Accept Headers ๐ŸŒˆ

Accept request-headers can reveal info about the user to every server that gets accessed ๐Ÿ‘€ the Accept-Language header especially can reveal stuff the user would consider private, since knowing a language is often strongly linked to belonging to a particular ethnic group ๐Ÿซถ user agents that let people configure what goes in Accept-Language on every request are strongly encouraged to include a message in that setup that makes the user aware of the privacy loss ๐Ÿšจ

a way to limit the privacy loss is for the user agent to leave Accept-Language out by default, and only ask the user whether to start sending it to a server if it notices (by looking for Vary response-header fields the server generated) that sending it could improve the quality of service ๐Ÿง 

elaborate, user-customized accept header fields sent with every request, especially ones with quality values, can work as pretty reliable, long-lived user IDs ๐Ÿ†” those IDs let content providers do click-trail tracking, and let collaborating providers match click-trails or form submissions across servers ๐Ÿ˜ฌ also, for lots of users not behind a proxy, the network address of the host running the user agent is also a long-lived user ID ๐Ÿ™ˆ where proxies are used to boost privacy, user agents should be conservative about offering accept header config options to end users โœจ as an extreme privacy move, proxies could filter the accept headers in relayed requests ๐Ÿ›ก๏ธ general purpose user agents with a high degree of header configurability should warn users about the privacy loss that can come with it โš ๏ธ

15.8 DNS Spoofing ๐Ÿ•ธ๏ธ

clients using HTTP rely heavily on the Domain Name Service, so they're generally open to security attacks based on deliberately messing up the mapping between IP addresses and DNS names ๐Ÿ˜ต clients need to be cautious about assuming an IP number/DNS name association stays valid forever ๐Ÿ™ƒ

specifically, HTTP clients SHOULD rely on their name resolver to confirm an IP number/DNS name association, rather than caching the result of earlier host name lookups ๐Ÿ” lots of platforms can already cache host name lookups locally when it makes sense, and they SHOULD be configured to do that ๐Ÿ’… these lookups should only be cached, though, when the TTL (Time To Live) info from the name server makes it likely the cached info will stay useful โณ

if HTTP clients cache host name lookup results to get a performance boost, they MUST observe the TTL info reported by DNS ๐Ÿซถ

if clients don't follow this rule, they could get spoofed when a previously accessed server's IP address changes. network renumbering is expected to get more common, so this kind of attack will only grow ๐Ÿ“ˆ following this requirement cuts down on that potential vulnerability ๐Ÿ”

this requirement also improves load-balancing for clients using replicated servers with the same DNS name, and makes it less likely that a user runs into failures accessing sites that use that strategy ๐ŸŒธ

15.9 Location Headers and Spoofing ๐Ÿ“

if one server supports multiple organizations that don't trust each other, it must check the values of Location and Content-Location headers in responses generated under the control of those organizations ๐Ÿง that way, they can't try to invalidate resources they have no authority over ๐Ÿšซ๐Ÿ‘‘

16. Acknowledgments ๐ŸŽ€

Okay bestie, this spec leans SO hard on the augmented BNF and generic constructs David H. Crocker came up with for RFC 822 ๐Ÿงš And it also reuses a bunch of MIME definitions from Nathaniel Borenstein and Ned Freed. We're hoping that putting them here helps clear up the old confusion about how HTTP and Internet mail message formats relate ๐Ÿ’œ

HTTP has glowed up a LOT over the past four years ๐ŸŒˆ Most of the credit goes to the huge, super active developer community, the many people who hung out on the www-talk mailing list. Honestly, that community is the reason HTTP and the World-Wide Web are such a massive success ๐Ÿ‘‘ Marc Andreessen, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob McCool, Lou Montulli, Dave Raggett, Tony Sanders, and Marc VanHeyningen deserve a special shoutout for their work on the early parts of the protocol ๐Ÿซถ

This document got SO much better thanks to everyone in the HTTP-WG who shared comments ๐Ÿ’… Besides the people already named, these folks also helped shape this specification:

      Gary Adams                  Albert Lunde
      Harald Tveit Alvestrand     John C. Mallery
      Keith Ball                  Jean-Philippe Martin-Flatin
      Brian Behlendorf            Larry Masinter
      Paul Burchard               Mitra
      Maurizio Codogno            David Morris
      Mike Cowlishaw              Gavin Nicol
      Roman Czyborra              Bill Perry
      Michael A. Dolan            Jeffrey Perry
      David J. Fiander            Scott Powers
      Alan Freier                 Owen Rees
      Marc Hedlund                Luigi Rizzo
      Greg Herlihy                David Robinson
      Koen Holtman                Marc Salomon
      Alex Hopmann                Rich Salz
      Bob Jernigan                Allan M. Schiffman
      Shel Kaphan                 Jim Seidman
      Rohit Khare                 Chuck Shotton
      John Klensin                Eric W. Sink
      Martijn Koster              Simon E. Spero
      Alexei Kosut                Richard N. Taylor
      David M. Kristol            Robert S. Thau
      Daniel LaLiberte            Bill (BearHeart) Weinman
      Ben Laurie                  Francois Yergeau
      Paul J. Leach               Mary Ellen Zurko
      Daniel DuBois

The caching design owes a lot of its look and feel to ideas and feedback from Shel Kaphan, Paul Leach, Koen Holtman, David Morris, and Larry Masinter ๐Ÿ“

Most of the range specification is based on work Ari Luotonen and John Franks did originally, plus extra input from Steve Zilles โœจ

Shoutout to the "cave men" of Palo Alto. You know who you are ๐Ÿ˜ญ๐Ÿฆ‹

Jim Gettys (the current editor of this document) especially wants to thank Roy Fielding, the previous editor, along with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Alex Hopmann, and Larry Masinter for their help ๐ŸŒธ


17. References ๐Ÿ“š

[1] Alvestrand, H., "Tags for the identification of languages", RFC 1766, UNINETT, March 1995.

[2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey, D., and B. Alberti. "The Internet Gopher Protocol: (a distributed document search and retrieval protocol)", RFC 1436, University of Minnesota, March 1993.

[3] Berners-Lee, T., "Universal Resource Identifiers in WWW", A Unifying Syntax for the Expression of Names and Addresses of Objects on the Network as used in the World-Wide Web", RFC 1630, CERN, June 1994.

[4] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform Resource Locators (URL)", RFC 1738, CERN, Xerox PARC, University of Minnesota, December 1994.

[5] Berners-Lee, T., and D. Connolly, "HyperText Markup Language Specification - 2.0", RFC 1866, MIT/LCS, November 1995.

[6] Berners-Lee, T., Fielding, R., and H. Frystyk, "Hypertext Transfer Protocol -- HTTP/1.0.", RFC 1945 MIT/LCS, UC Irvine, May 1996.

[7] Freed, N., and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, Innosoft, First Virtual, November 1996.

[8] Braden, R., "Requirements for Internet hosts - application and support", STD 3, RFC 1123, IETF, October 1989.

[9] Crocker, D., "Standard for the Format of ARPA Internet Text Messages", STD 11, RFC 822, UDEL, August 1982.

[10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R., Sui, J., and M. Grinbaum. "WAIS Interface Protocol Prototype Functional Specification", (v1.5), Thinking Machines Corporation, April 1990.

[11] Fielding, R., "Relative Uniform Resource Locators", RFC 1808, UC Irvine, June 1995.

[12] Horton, M., and R. Adams. "Standard for interchange of USENET messages", RFC 1036, AT&T Bell Laboratories, Center for Seismic Studies, December 1987.

[13] Kantor, B., and P. Lapsley. "Network News Transfer Protocol." A Proposed Standard for the Stream-Based Transmission of News", RFC 977, UC San Diego, UC Berkeley, February 1986.

[14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, University of Tennessee, November 1996.

[15] Nebel, E., and L. Masinter. "Form-based File Upload in HTML", RFC 1867, Xerox Corporation, November 1995.

[16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, USC/ISI, August 1982.

[17] Postel, J., "Media Type Registration Procedure", RFC 2048, USC/ISI, November 1996.

[18] Postel, J., and J. Reynolds, "File Transfer Protocol (FTP)", STD 9, RFC 959, USC/ISI, October 1985.

[19] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, USC/ISI, October 1994.

[20] Sollins, K., and L. Masinter, "Functional Requirements for Uniform Resource Names", RFC 1737, MIT/LCS, Xerox Corporation, December 1994.

[21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.

[22] ISO-8859. International Standard -- Information Processing -- 8-bit Single-Byte Coded Graphic Character Sets --

  Part 1: Latin alphabet No. 1, ISO 8859-1:1987.
  Part 2: Latin alphabet No. 2, ISO 8859-2, 1987.
  Part 3: Latin alphabet No. 3, ISO 8859-3, 1988.
  Part 4: Latin alphabet No. 4, ISO 8859-4, 1988.

  Part 5: Latin/Cyrillic alphabet, ISO 8859-5, 1988.
  Part 6: Latin/Arabic alphabet, ISO 8859-6, 1987.
  Part 7: Latin/Greek alphabet, ISO 8859-7, 1987.
  Part 8: Latin/Hebrew alphabet, ISO 8859-8, 1988.
  Part 9: Latin alphabet No. 5, ISO 8859-9, 1990.

[23] Meyers, J., and M. Rose "The Content-MD5 Header Field", RFC 1864, Carnegie Mellon, Dover Beach Consulting, October, 1995.

[24] Carpenter, B., and Y. Rekhter, "Renumbering Needs Work", RFC 1900, IAB, February 1996.

[25] Deutsch, P., "GZIP file format specification version 4.3." RFC 1952, Aladdin Enterprises, May 1996.

[26] Venkata N. Padmanabhan and Jeffrey C. Mogul. Improving HTTP Latency. Computer Networks and ISDN Systems, v. 28, pp. 25-35, Dec. 1995. Slightly revised version of paper in Proc. 2nd International WWW Conf. '94: Mosaic and the Web, Oct. 1994, which is available at http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLatency.html.

[27] Joe Touch, John Heidemann, and Katia Obraczka, "Analysis of HTTP Performance", <URL: http://www.isi.edu/lsam/ib/http-perf/>, USC/Information Sciences Institute, June 1996

[28] Mills, D., "Network Time Protocol, Version 3, Specification, Implementation and Analysis", RFC 1305, University of Delaware, March 1992.

[29] Deutsch, P., "DEFLATE Compressed Data Format Specification version 1.3." RFC 1951, Aladdin Enterprises, May 1996.

[30] Spero, S., "Analysis of HTTP Performance Problems" <URL:http://sunsite.unc.edu/mdma-release/http-prob.html>.

[31] Deutsch, P., and J-L. Gailly, "ZLIB Compressed Data Format Specification version 3.3", RFC 1950, Aladdin Enterprises, Info-ZIP, May 1996.

[32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P., Luotonen, A., Sink, E., and L. Stewart, "An Extension to HTTP : Digest Access Authentication", RFC 2069, January 1997.


18. Authors' Addresses ๐Ÿ’Œ

Roy T. Fielding
Department of Information and Computer Science
University of California
Irvine, CA 92717-3425, USA

Fax: +1 (714) 824-4056
EMail: fielding@ics.uci.edu


Jim Gettys
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA

Fax: +1 (617) 258 8682
EMail: jg@w3.org


Jeffrey C. Mogul
Western Research Laboratory
Digital Equipment Corporation
250 University Avenue
Palo Alto, California, 94305, USA

EMail: mogul@wrl.dec.com


Henrik Frystyk Nielsen
W3 Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA

Fax: +1 (617) 258 8682
EMail: frystyk@w3.org


Tim Berners-Lee
Director, W3 Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA

Fax: +1 (617) 258 8682
EMail: timbl@w3.org

19. Appendices ๐ŸŒˆ

19.1. Internet Media Type message/http ๐Ÿ’–

Besides defining HTTP/1.1, this document is also the spec for the Internet media type "message/http" ๐Ÿฆ‹ This is what gets registered with IANA:

    Media Type name:         message
    Media subtype name:      http
    Required parameters:     none
    Optional parameters:     version, msgtype

     version: The HTTP-Version number of the enclosed message
              (e.g., "1.1"). If not present, the version can be
              determined from the first line of the body.

     msgtype: The message type -- "request" or "response". If not
              present, the type can be determined from the first
              line of the body.

    Encoding considerations: only "7bit", "8bit", or "binary" are
                             permitted

    Security considerations: none

19.2. Internet Media Type multipart/byteranges ๐ŸŽ€

When an HTTP message carries the content of several ranges (like a response to a request for multiple non-overlapping ranges), those ranges get sent as a multipart MIME message ๐Ÿง The multipart media type for this is called "multipart/byteranges" โœจ

The multipart/byteranges media type has two or more parts, and each one has its own Content-Type and Content-Range fields. The parts are split apart using a MIME boundary parameter ๐Ÿ’…

       Media Type name:         multipart
       Media subtype name:      byteranges
       Required parameters:     boundary
       Optional parameters:     none

       Encoding considerations: only "7bit", "8bit", or "binary" are
                                permitted

       Security considerations: none

For example, it looks something like this ๐Ÿ‘€

HTTP/1.1 206 Partial content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 500-999/8000

...the first range...
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 7000-7999/8000

...the second range
--THIS_STRING_SEPARATES--

19.3 Tolerant Applications โœจ

okay so, even though this doc spells out exactly what HTTP/1.1 messages have to look like when you make one, real-world apps aren't always perfect ๐Ÿ™ˆ so the vibe is: be tolerant of little deviations, as long as the meaning is still totally clear ๐Ÿ’–

Clients SHOULD be tolerant when parsing the Status-Line, and servers SHOULD be tolerant when parsing the Request-Line ๐Ÿซถ Basically they SHOULD accept any amount of SP or HT characters between fields, even though only a single SP is really needed ๐Ÿ’…

The line terminator for message-header fields is CRLF ๐ŸŽ€ But applications parsing those headers are encouraged to treat a single LF as a line terminator too, and to ignore the leading CR ๐ŸŒธ

The character set of an entity-body should be labeled as the lowest common denominator of the character codes used inside that body ๐Ÿฆ‹ The one exception: no label is preferred over US-ASCII or ISO-8859-1 โœจ

Now for dates, because dates are chaos ๐Ÿ˜ญ Here are the extra rules for parsing and encoding them, plus a few other date gotchas:

  • HTTP/1.1 clients and caches should assume that an RFC-850 date that looks more than 50 years in the future is actually in the past. This helps solve the "year 2000" problem ๐Ÿ’€
  • An HTTP/1.1 implementation may internally store a parsed Expires date as earlier than the proper value, but it MUST NOT internally store a parsed Expires date as later than the proper value ๐Ÿ™…โ€โ™€๏ธ
  • All expiration-related calculations must be done in GMT. The local time zone MUST NOT influence the calculation or comparison of an age or expiration time ๐ŸŒ
  • If an HTTP header carries a date with a time zone other than GMT, it must be converted into GMT using the most conservative possible conversion ๐Ÿงš

19.4 Differences Between HTTP Entities and MIME Entities ๐ŸŒˆ

okay bestie, so HTTP/1.1 borrows a bunch of stuff from Internet Mail (RFC 822) and MIME so entities can show up in a wide open variety of representations ๐Ÿฆ‹ But MIME is all about mail, and HTTP has some features that are different on purpose. Those differences were picked to make things faster over binary connections, give more freedom with new media types, make date comparisons easier, and also respect what early HTTP servers and clients were already doing ๐Ÿ’œ MIME [7] is the original source for all this, btw โœจ

This appendix lists the spots where HTTP and MIME don't match. Proxies and gateways that sit in front of strict MIME environments SHOULD know about these differences and do the right conversions ๐Ÿงš Proxies and gateways going the other direction, from MIME into HTTP, also need to know about them, since some conversions may be needed ๐Ÿซถ

19.4.1 Conversion to Canonical Form ๐ŸŽ€

MIME says an Internet mail entity has to be converted to canonical form before it gets sent ๐Ÿ“ฌ Section 3.7.1 of this document covers which forms are allowed for the subtypes of the "text" media type when they're sent over HTTP ๐Ÿ’… MIME wants "text" content to show line breaks as CRLF and doesn't allow CR or LF anywhere except in those line break sequences ๐Ÿ˜ญ HTTP, on the other hand, lets CRLF, bare CR, and bare LF all mean a line break inside text content when a message travels over HTTP ๐ŸŒธ

Where it's possible, a proxy or gateway going from HTTP to a strict MIME environment SHOULD translate every line break inside the text media types from section 3.7.1 of this document into the MIME canonical form of CRLF ๐Ÿฆ‹ Heads up though, this can get messy when there's a Content-Encoding involved. It also gets messy because HTTP allows some character sets that don't use octets 13 and 10 to represent CR and LF, which is true for some multi-byte character sets ๐Ÿ™ˆ

19.4.2 Conversion of Date Formats ๐Ÿ“…

HTTP/1.1 only uses a restricted set of date formats (section 3.3.1) so that comparing dates stays simple ๐Ÿ’– Proxies and gateways coming from other protocols SHOULD make sure any Date header field in a message matches one of the HTTP/1.1 formats, and rewrite the date if needed โœจ

19.4.3 Introduction of Content-Encoding ๐Ÿ”ฅ

MIME doesn't have anything like HTTP/1.1's Content-Encoding header field ๐Ÿ˜ณ Since it acts as a modifier on the media type, proxies and gateways going from HTTP to MIME-compliant protocols MUST either change the value of the Content-Type header field or decode the entity-body before forwarding the message. (Some experimental Internet mail apps used a media-type parameter of ;conversions=<content-coding> to do the same job as Content-Encoding, but that parameter isn't part of MIME ๐Ÿ™ƒ)

19.4.4 No Content-Transfer-Encoding ๐Ÿšซ

HTTP doesn't use the Content-Transfer-Encoding (CTE) field from MIME ๐Ÿ™…โ€โ™€๏ธ Proxies and gateways going from MIME-compliant protocols to HTTP MUST remove any non-identity CTE ("quoted-printable" or "base64") encoding before they hand the response message to an HTTP client ๐Ÿงผ

Proxies and gateways going from HTTP to MIME-compliant protocols are responsible for making sure the message is in the right format and encoding for "safe transport" on that protocol, where "safe transport" is defined by whatever limits the protocol has ๐Ÿ›ก๏ธ If labeling the data with an appropriate Content-Transfer-Encoding would make safe transport more likely over the destination protocol, that proxy or gateway SHOULD do it ๐Ÿซถ

19.4.5 HTTP Header Fields in Multipart Body-Parts ๐ŸŽ€

In MIME, most header fields in multipart body-parts get ignored unless the field name starts with "Content-" ๐Ÿฅฑ In HTTP/1.1, multipart body-parts may contain any HTTP header fields that matter to the meaning of that part ๐Ÿ’…

19.4.6 Introduction of Transfer-Encoding ๐ŸŒ€

HTTP/1.1 brings in the Transfer-Encoding header field (section 14.40) ๐ŸŽ‰ Proxies/gateways MUST remove any transfer coding before forwarding a message through a MIME-compliant protocol ๐Ÿงน

Here's a pseudo-code way to think about decoding the "chunked" transfer coding (section 3.6), so you can picture the whole flow:

length := 0
read chunk-size, chunk-ext (if any) and CRLF
while (chunk-size > 0) {
   read chunk-data and CRLF
   append chunk-data to entity-body
   length := length + chunk-size
   read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
   append entity-header to existing header fields
   read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding

19.4.7 MIME-Version ๐Ÿงพ

HTTP isn't a MIME-compliant protocol (see appendix 19.4) ๐Ÿ™ƒ But HTTP/1.1 messages may include a single MIME-Version general-header field to say which version of the MIME protocol was used to build the message ๐Ÿ’œ Using the MIME-Version header field means the message is in full compliance with the MIME protocol. Proxies/gateways are responsible for making sure that compliance happens (where possible) when they export HTTP messages to strict MIME environments ๐ŸŒธ

MIME-Version   = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT

MIME version "1.0" is the default for use in HTTP/1.1 ๐Ÿฆ‹ That said, HTTP/1.1 message parsing and semantics are defined by this document, not by the MIME spec, so don't mix those up ๐Ÿซถ


19.5 Changes from HTTP/1.0 ๐Ÿ”ฅ

okay so this section is the highlight reel of what changed between HTTP/1.0 and HTTP/1.1 ๐Ÿ‘‘ It's a summary of the major differences, so you get the big picture before the details โœจ

19.5.1 Changes to Simplify Multi-homed Web Servers and Conserve IP Addresses ๐ŸŒ

The requirements that clients and servers support the Host request-header, that an error gets reported if the Host request-header (section 14.23) is missing from an HTTP/1.1 request, and that absolute URIs (section 5.1.2) are accepted are among the most important changes in this spec ๐Ÿ’–

Older HTTP/1.0 clients basically assumed one IP address per server ๐Ÿ™ˆ There was no other established way to tell which server a request was meant for besides the IP address it was sent to ๐Ÿ˜ญ These changes mean that, once older HTTP clients stop being common, the Internet can host multiple websites on a single IP address. That makes big operational Web servers way simpler, since giving one host a ton of IP addresses had caused serious problems ๐Ÿงš The Internet will also get back IP addresses that were only handed out so special-purpose domain names could show up in root-level HTTP URLs ๐Ÿฆ‹ With the Web growing so fast and so many servers already out there, it's super important that every HTTP implementation (including updates to existing HTTP/1.0 apps) gets these requirements right ๐Ÿ’…

  • Both clients and servers MUST support the Host request-header.
  • Host request-headers are required in HTTP/1.1 requests.
  • Servers MUST report a 400 (Bad Request) error if an HTTP/1.1 request does not include a Host request-header.
  • Servers MUST accept absolute URIs.

19.6 Additional Features โœจ

this appendix documents protocol bits that some existing HTTP implementations use, but not consistently or correctly across most HTTP/1.1 apps ๐Ÿ™ˆ Implementers should know about these features, but they can't count on them being there, or on working with other HTTP/1.1 apps ๐Ÿฅฒ Some of them are proposed experimental features, and some are features that experimental deployments found lacking and that the base HTTP/1.1 spec now handles ๐Ÿ’œ

19.6.1 Additional Request Methods ๐ŸŽ€

19.6.1.1 PATCH ๐Ÿฉน

the PATCH method is kind of like PUT, except the entity holds a list of differences between the original version of the resource identified by the Request-URI and the version you want after the PATCH is applied ๐Ÿงฉ That list of differences is in a format defined by the media type of the entity (e.g., "application/diff"), and it MUST include enough information for the server to recreate the changes needed to turn the original version into the desired one ๐Ÿ› ๏ธ

If the request goes through a cache and the Request-URI identifies an entity that's currently cached, that entity MUST be removed from the cache ๐Ÿงน Responses to this method are not cachable ๐Ÿ™…โ€โ™€๏ธ

What happens to the patched resource, and to its predecessor, is decided entirely by the origin server ๐Ÿ‘‘ If the original version of the resource being patched had a Content-Version header field, the request entity MUST include a Derived-From header field matching the value of that original Content-Version header field ๐Ÿ”— Applications are encouraged to use these fields to build versioning relationships and to sort out version conflicts ๐ŸŒˆ

PATCH requests must obey the message transmission requirements set out in section 8.2 ๐Ÿ“ฌ

Caches that implement PATCH should invalidate cached responses as defined in section 13.10 for PUT ๐Ÿซถ

Okay bestie, LINK is the method that sets up one or more Link relationships between the existing resource named by the Request-URI and other existing resources. What makes it different from other methods that can create links is that LINK doesn't allow any message-body in the request, and it doesn't directly make brand new resources. It's all about connecting things that already exist ๐Ÿ’…

If the request goes through a cache and the Request-URI points at a currently cached entity, that entity MUST be removed from the cache. Responses to this method are not cachable ๐Ÿ™ˆ

Caches that implement LINK should invalidate cached responses the way section 13.10 defines for PUT โœจ

UNLINK is the opposite energy: it removes one or more Link relationships from the existing resource named by the Request-URI. Those relationships might have been made with LINK, or with any other method that supports the Link header. Removing a link doesn't mean the resource is gone or can't be reached later on. The resource is still there, bestie, it just isn't linked up anymore ๐Ÿฆ‹

If the request goes through a cache and the Request-URI points at a currently cached entity, that entity MUST be removed from the cache. Responses to this method are not cachable ๐Ÿ™ˆ

Caches that implement UNLINK should invalidate cached responses the way section 13.10 defines for PUT ๐Ÿซถ

19.6.2 Additional Header Field Definitions ๐ŸŽ€

19.6.2.1 Alternates ๐ŸŒˆ

Alternates is a response-header field that was proposed so the origin server can tell the client about other representations of the requested resource, along with what makes each one different. That gives the user agent a more reliable way to pick a different representation that fits what its user actually wants. This is the agent-driven negotiation that section 12 talks about, and it's giving very "I can choose for myself" ๐Ÿ’…

Alternates is orthogonal to the Vary header field, which means both can show up in one message without messing with how the response or the available representations get read. Alternates is expected to be a big upgrade over the server-driven negotiation that Vary gives you for resources that vary along common dimensions like type and language โœจ

The Alternates header field will be defined in a future specification ๐Ÿ”ฎ

19.6.2.2 Content-Version ๐Ÿท๏ธ

Content-Version is an entity-header field that holds the version tag for one rendition of an evolving entity. Paired with Derived-From from section 19.6.2.3, it lets a group of people work on the same piece at the same time as an iterative process. This field should be used to let one work evolve down a single path, rather than making derived works or renditions in different representations ๐Ÿ‘‘

       Content-Version = "Content-Version" ":" quoted-string

Here are some examples of the Content-Version field:

       Content-Version: "2.1.2"
       Content-Version: "Fred 19950116-12:26:48"
       Content-Version: "2.5a4-omega7"

19.6.2.3 Derived-From ๐Ÿงฌ

Derived-From is an entity-header field that can tell you which version tag the enclosed entity came from, before the sender modified it. It's there to help merge successive changes to a resource, especially when those changes are happening in parallel and from more than one source. Teamwork makes the dream work ๐Ÿซถ

       Derived-From   = "Derived-From" ":" quoted-string

Here's an example of the field in action:

       Derived-From: "2.1.1"

The Derived-From field is required for PUT and PATCH requests if the entity being sent was previously retrieved from the same URI and a Content-Version header was included with the entity when it was last retrieved ๐ŸŽฏ

Link is an entity-header field that describes a relationship between two resources, usually between the requested resource and some other resource. An entity MAY include multiple Link values. Links at the metainformation level usually show things like hierarchy and navigation paths. Link is semantically equivalent to the <LINK> element in HTML.[5] Iconic crossover moment ๐ŸŒธ

       Link           = "Link" ":" #("<" URI ">" *( ";" link-param )

       link-param     = ( ( "rel" "=" relationship )
                          | ( "rev" "=" relationship )
                          | ( "title" "=" quoted-string )
                          | ( "anchor" "=" <"> URI <"> )
                          | ( link-extension ) )

       link-extension = token [ "=" ( token | quoted-string ) ]

       relationship   = sgml-name
                      | ( <"> sgml-name *( SP sgml-name) <"> )

       sgml-name      = ALPHA *( ALPHA | DIGIT | "." | "-" )

Relationship values are case-insensitive and MAY be extended, as long as they stay within the constraints of the sgml-name syntax. The title parameter MAY be used to label the destination of a link so it can show up as identification in a human-readable menu. The anchor parameter MAY be used to point at a source anchor other than the entire current resource, like a fragment of this resource or a third resource ๐Ÿฆ‹

Here are some examples of how it gets used:

    Link: <http://www.cern.ch/TheBook/chapter2>; rel="Previous"

    Link: <mailto:timbl@w3.org>; rev="Made"; title="Tim Berners-Lee"

The first example says that chapter2 comes before this resource in a logical navigation path. The second says that the person responsible for making the resource available is the one with the given e-mail address. Very organised, very cute ๐Ÿงš

19.6.2.5 URI ๐Ÿ™ƒ

The URI header field was used in earlier versions of this specification as a mashup of the existing Location, Content-Location, and Vary header fields, plus the future Alternates field (see above). Its main job was to carry a list of extra URIs for the resource, like names and mirror locations. But it became clear that cramming so many different jobs into one field made it really hard to implement any of them consistently and correctly ๐Ÿ’€ Also, we think identifying names and mirror locations would be better handled by the Link header field. So the URI header field is deprecated in favor of those other fields. Bye bye, URI ๐Ÿ‘‹

          URI-header    = "URI" ":" 1#( "<" URI ">" )

19.7 Compatibility with Previous Versions ๐Ÿ•ฐ๏ธ

Protocol specs can't really force anyone to stay compatible with older versions. That's beyond their scope. HTTP/1.1 was deliberately designed to make supporting previous versions easy though, and it's worth noting that when this specification was written, we'd expect commercial HTTP/1.1 servers to:

  • recognize the format of the Request-Line for HTTP/0.9, 1.0, and 1.1 requests;
  • understand any valid request in the format of HTTP/0.9, 1.0, or 1.1;
  • respond appropriately with a message in the same major version used by the client.

And we'd expect HTTP/1.1 clients to:

  • recognize the format of the Status-Line for HTTP/1.0 and 1.1 responses;
  • understand any valid response in the format of HTTP/0.9, 1.0, or 1.1.

For most HTTP/1.0 implementations, the client establishes each connection before the request, and the server closes it after sending the response. A few implementations use the Keep-Alive version of persistent connections described in section 19.7.1.1 ๐ŸŒŸ

19.7.1 Compatibility with HTTP/1.0 Persistent Connections ๐Ÿ”

Some clients and servers may want to be compatible with certain older implementations of persistent connections in HTTP/1.0 clients and servers. Persistent connections in HTTP/1.0 must be explicitly negotiated, since they aren't the default behavior. The experimental HTTP/1.0 implementations of persistent connections were faulty, and HTTP/1.1's new facilities were designed to fix those problems ๐Ÿ”ง The trouble was that some existing 1.0 clients might send Keep-Alive to a proxy server that doesn't understand Connection. That proxy would then wrongly forward it to the next inbound server, which would set up the Keep-Alive connection, and the result would be an HTTP/1.0 proxy hung up waiting for the close on the response ๐Ÿ˜ฑ So HTTP/1.0 clients must be prevented from using Keep-Alive when talking to proxies.

But talking to proxies is the most important use of persistent connections, so that prohibition is clearly unacceptable ๐Ÿ™…โ€โ™€๏ธ We need another mechanism for signaling that a persistent connection is wanted, and it has to be safe even when talking to an old proxy that ignores Connection. Persistent connections are the default for HTTP/1.1 messages, and we introduce a new keyword (Connection: close) for declaring non-persistence ๐Ÿ’–

The following describes the original HTTP/1.0 form of persistent connections.

When it connects to an origin server, an HTTP client MAY send the Keep-Alive connection-token in addition to the Persist connection-token:

       Connection: Keep-Alive

An HTTP/1.0 server would then respond with the Keep-Alive connection token, and the client may go ahead with an HTTP/1.0 (or Keep-Alive) persistent connection ๐ŸŽ‰

An HTTP/1.1 server may also set up persistent connections with HTTP/1.0 clients once it receives a Keep-Alive connection token. However, a persistent connection with an HTTP/1.0 client cannot use the chunked transfer-coding, so it MUST use a Content-Length to mark the ending boundary of each message ๐Ÿ“

A client MUST NOT send the Keep-Alive connection token to a proxy server, because HTTP/1.0 proxy servers don't follow the HTTP/1.1 rules for parsing the Connection header field ๐Ÿšซ

19.7.1.1 The Keep-Alive Header ๐Ÿซง

When the Keep-Alive connection-token has been sent with a request or a response, a Keep-Alive header field MAY also be included. The Keep-Alive header field looks like this:

       Keep-Alive-header = "Keep-Alive" ":" 0# keepalive-param

       keepalive-param = param-name "=" value

The Keep-Alive header is optional, and it only gets used if a parameter is being sent. HTTP/1.1 doesn't define any parameters ๐ŸŒท

If the Keep-Alive header is sent, the corresponding connection token MUST be transmitted. The Keep-Alive header MUST be ignored if it's received without the connection token ๐Ÿฅฐ

๐Ÿ“ฆ where this page comes from