RFC 2616

Hypertext Transfer Protocol -- HTTP/1.1

๐Ÿ“… published June 1999, from ietf

Hypertext Transfer Protocol -- HTTP/1.1 ๐Ÿฆ‹

okay bestie, this one is the big one ๐Ÿ’… RFC 2616 from June 1999, and it's a Standards Track doc, so it's the real deal, not a vibe-check draft ๐Ÿ‘‘. It obsoletes RFC 2068 and it's basically the glow-up of that earlier version, aka an update to RFC 2068 [33] ๐ŸŒธ

The authors are a whole squad ๐Ÿซถ: R. Fielding (UC Irvine), J. Gettys (Compaq/W3C), J. Mogul (Compaq), H. Frystyk (W3C/MIT), L. Masinter (Xerox), P. Leach (Microsoft), and T. Berners-Lee (W3C/MIT). Iconic lineup, no notes ๐Ÿ˜ญโœจ

Status of this Memo ๐ŸŽ€

ok so this part is the paperwork, but it matters ๐Ÿ’–. This document is an Internet standards track protocol for the Internet community, and it's basically asking everyone to talk about it and send ideas for making it better ๐Ÿงš. If you want to know where this protocol stands in the official standardization state, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š. And the memo is distributed with unlimited distribution, so anyone can read it ๐ŸŒˆ

Copyright (C) The Internet Society (1999). All Rights Reserved. Legally boring but very much real ๐Ÿ’…

Abstract โœจ

okay the main idea: the Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems ๐Ÿ“ It's a generic, stateless protocol, so it's giving flexible energy. It isn't only for hypertext either. You can stretch it to name servers and distributed object management systems by extending its request methods, error codes and headers [47] ๐Ÿ”ฅ

One of the iconic features is the typing and negotiation of data representation. That means systems can be built independently of the data being transferred, which is so smart and honestly kind of main-character ๐Ÿ‘‘

HTTP has been used by the World-Wide Web global information initiative since 1990 ๐ŸŒ This specification defines the protocol called "HTTP/1.1", and it's the update to RFC 2068 [33] ๐Ÿ’œ


Table of Contents ๐Ÿงš

more of the table of contents is coming up in the next part, so stay tuned, bestie ๐Ÿฆ‹๐Ÿ’–

๐Ÿ’… bestie, this part only has the section headings, because the body text for these sections wasn't in the original I was given. I've kept every heading, number, and name exactly as the table of contents lists them, so the text can slot in once you send the body.

1. Introduction โœจ

1.1. Purpose

1.2. Requirements

1.3. Terminology

1.4. Overall Operation

2. Notational Conventions and Generic Grammar ๐Ÿ“

2.1. Augmented BNF

2.2. Basic Rules

3. Protocol Parameters ๐ŸŽ€

3.1. HTTP Version

3.2. Uniform Resource Identifiers

3.2.1. General Syntax

3.2.2. http URL

3.2.3. URI Comparison

3.3. Date/Time Formats

3.3.1. Full Date

3.3.2. Delta Seconds

3.4. Character Sets

3.4.1. Missing Charset

3.5. Content Codings

3.6. Transfer Codings

3.6.1. Chunked Transfer Coding

3.7. Media Types

3.7.1. Canonicalization and Text Defaults

3.7.2. Multipart Types

3.8. Product Tokens

3.9. Quality Values

3.10. Language Tags

3.11. Entity Tags

3.12. Range Units

4. HTTP Message ๐Ÿ’Œ

4.1. Message Types

4.2. Message Headers

4.3. Message Body

4.4. Message Length

4.5. General Header Fields

5. Request ๐Ÿฆ‹

5.1. Request-Line

5.1.1. Method

5.1.2. Request-URI

5.2. The Resource Identified by a Request

5.3. Request Header Fields

6. Response ๐ŸŒธ

6.1. Status-Line

6.1.1. Status Code and Reason Phrase

6.2. Response Header Fields

7. Entity ๐Ÿงš

7.1. Entity Header Fields

7.2. Entity Body

7.2.1. Type

7.2.2. Entity Length

8. Connections ๐Ÿ”Œ

8.1. Persistent Connections

8.1.1. Purpose

8.1.2. Overall Operation

8.1.3. Proxy Servers

8.1.4. Practical Considerations

8.2. Message Transmission Requirements

8.2.1. Persistent Connections and Flow Control

8.2.2. Monitoring Connections for Error Status Messages

8.2.3. Use of the 100 (Continue) Status

8.2.4. Client Behavior if Server Prematurely Closes Connection

9. Method Definitions ๐Ÿ› ๏ธ

9.1. Safe and Idempotent Methods

9.1.1. Safe Methods

9.1.2. Idempotent Methods

9.2. OPTIONS

9.3. GET

9.4. HEAD

9.5. POST

9.6. PUT

9.7. DELETE

9.8. TRACE

9.9. CONNECT

10. Status Code Definitions ๐Ÿšฆ

10.1. Informational 1xx

10.1.1. 100 Continue

10.1.2. 101 Switching Protocols

10.2. Successful 2xx

10.2.1. 200 OK

10.2.2. 201 Created

10.2.3. 202 Accepted

10.2.4. 203 Non-Authoritative Information

10.2.5. 204 No Content

10.2.6. 205 Reset Content

10.2.7. 206 Partial Content

10.3. Redirection 3xx

10.3.1. 300 Multiple Choices

10.3.2. 301 Moved Permanently

10.3.3. 302 Found

10.3.4. 303 See Other

10.3.5. 304 Not Modified

10.3.6. 305 Use Proxy

10.3.7. 306 (Unused)

10.3.8. 307 Temporary Redirect

10.4. Client Error 4xx

10.4.1. 400 Bad Request

10.4.2. 401 Unauthorized

10.4.3. 402 Payment Required

10.4.4. 403 Forbidden

10.4.5. 404 Not Found

10.4.6. 405 Method Not Allowed

10.4.7. 406 Not Acceptable

10.4.8. 407 Proxy Authentication Required

10.4.9. 408 Request Timeout

10.4.10. 409 Conflict

10.4.11. 410 Gone

10.4.12. 411 Length Required

10.4.13. 412 Precondition Failed

10.4.14. 413 Request Entity Too Large

10.4.15. 414 Request-URI Too Long

10.4.16. 415 Unsupported Media Type

10.4.17. 416 Requested Range Not Satisfiable

10.4.18. 417 Expectation Failed

10.5. Server Error 5xx

10.5.1. 500 Internal Server Error

10.5.2. 501 Not Implemented

10.5.3. 502 Bad Gateway

10.5.4. 503 Service Unavailable

10.5.5. 504 Gateway Timeout

10.5.6. 505 HTTP Version Not Supported

11. Access Authentication ๐Ÿ”

12. Content Negotiation ๐ŸŒˆ

12.1. Server-driven Negotiation

12.2. Agent-driven Negotiation

12.3. Transparent Negotiation

13. Caching in HTTP ๐Ÿ—„๏ธ

13.1.1. Cache Correctness

13.1.2. Warnings

13.1.3. Cache-control Mechanisms

13.1.4. Explicit User Agent Warnings

13.1.5. Exceptions to the Rules and Warnings

13.1.6. Client-controlled Behavior

13.2. Expiration Model

13.2.1. Server-Specified Expiration

13.2.2. Heuristic Expiration

13.2.3. Age Calculations

13.2.4. Expiration Calculations

13.2.5. Disambiguating Expiration Values

13.2.6. Disambiguating Multiple Responses

13.3. Validation Model

13.3.1. Last-Modified Dates

13.3.2. Entity Tag Cache Validators

13.3.3. Weak and Strong Validators

13.3.4. Rules for When to Use Entity Tags and Last-Modified Dates

13.3.5. Non-validating Conditionals

13.4. Response Cacheability

13.5. Constructing Responses From Caches

13.5.1. End-to-end and Hop-by-hop Headers

13.5.2. Non-modifiable Headers

13.5.3. Combining Headers

13.5.4. Combining Byte Ranges

13.6. Caching Negotiated Responses

13.7. Shared and Non-Shared Caches

13.8. Errors or Incomplete Response Cache Behavior

13.9. Side Effects of GET and HEAD

13.10. Invalidation After Updates or Deletions

13.11. Write-Through Mandatory

13.12. Cache Replacement

13.13. History Lists

14. Header Field Definitions ๐Ÿ“ฌ

14.1. Accept

14.2. Accept-Charset

14.3. Accept-Encoding

   14.4  Accept-Language ............................................104
   14.5  Accept-Ranges ..............................................105
   14.6  Age ........................................................106
   14.7  Allow ......................................................106
   14.8  Authorization ..............................................107
   14.9  Cache-Control ..............................................108
   14.9.1   What is Cacheable .......................................109
   14.9.2   What May be Stored by Caches ............................110
   14.9.3   Modifications of the Basic Expiration Mechanism .........111
   14.9.4   Cache Revalidation and Reload Controls ..................113
   14.9.5   No-Transform Directive ..................................115
   14.9.6   Cache Control Extensions ................................116
   14.10   Connection ...............................................117
   14.11   Content-Encoding .........................................118
   14.12   Content-Language .........................................118
   14.13   Content-Length ...........................................119
   14.14   Content-Location .........................................120
   14.15   Content-MD5 ..............................................121
   14.16   Content-Range ............................................122
   14.17   Content-Type .............................................124
   14.18   Date .....................................................124
   14.18.1   Clockless Origin Server Operation ......................125
   14.19   ETag .....................................................126
   14.20   Expect ...................................................126
   14.21   Expires ..................................................127
   14.22   From .....................................................128
   14.23   Host .....................................................128
   14.24   If-Match .................................................129
   14.25   If-Modified-Since ........................................130
   14.26   If-None-Match ............................................132
   14.27   If-Range .................................................133
   14.28   If-Unmodified-Since ......................................134
   14.29   Last-Modified ............................................134
   14.30   Location .................................................135
   14.31   Max-Forwards .............................................136
   14.32   Pragma ...................................................136
   14.33   Proxy-Authenticate .......................................137
   14.34   Proxy-Authorization ......................................137
   14.35   Range ....................................................138
   14.35.1    Byte Ranges ...........................................138
   14.35.2    Range Retrieval Requests ..............................139
   14.36   Referer ..................................................140
   14.37   Retry-After ..............................................141
   14.38   Server ...................................................141
   14.39   TE .......................................................142
   14.40   Trailer ..................................................143
   14.41  Transfer-Encoding..........................................143
   14.42   Upgrade ..................................................144
   14.43   User-Agent ...............................................145
   14.44   Vary .....................................................145
   14.45   Via ......................................................146
   14.46   Warning ..................................................148
   14.47   WWW-Authenticate .........................................150
   15 Security Considerations .......................................150
   15.1      Personal Information....................................151
   15.1.1   Abuse of Server Log Information .........................151
   15.1.2   Transfer of Sensitive Information .......................151
   15.1.3   Encoding Sensitive Information in URI's .................152
   15.1.4   Privacy Issues Connected to Accept Headers ..............152
   15.2  Attacks Based On File and Path Names .......................153
   15.3  DNS Spoofing ...............................................154
   15.4  Location Headers and Spoofing ..............................154
   15.5  Content-Disposition Issues .................................154
   15.6  Authentication Credentials and Idle Clients ................155
   15.7  Proxies and Caching ........................................155
   15.7.1    Denial of Service Attacks on Proxies....................156
   16   Acknowledgments .............................................156
   17   References ..................................................158
   18   Authors' Addresses ..........................................162
   19   Appendices ..................................................164
   19.1  Internet Media Type message/http and application/http ......164
   19.2  Internet Media Type multipart/byteranges ...................165
   19.3  Tolerant Applications ......................................166
   19.4  Differences Between HTTP Entities and RFC 2045 Entities ....167
   19.4.1   MIME-Version ............................................167
   19.4.2   Conversion to Canonical Form ............................167
   19.4.3   Conversion of Date Formats ..............................168
   19.4.4   Introduction of Content-Encoding ........................168
   19.4.5   No Content-Transfer-Encoding ............................168
   19.4.6   Introduction of Transfer-Encoding .......................169
   19.4.7   MHTML and Line Length Limitations .......................169
   19.5  Additional Features ........................................169
   19.5.1   Content-Disposition .....................................170
   19.6  Compatibility with Previous Versions .......................170
   19.6.1   Changes from HTTP/1.0 ...................................171
   19.6.2   Compatibility with HTTP/1.0 Persistent Connections ......172
   19.6.3   Changes from RFC 2068 ...................................172
   20   Index .......................................................175
   21   Full Copyright Statement ....................................176

1. Introduction โœจ

1.1. Purpose

okay so HTTP (the Hypertext Transfer Protocol) is an application-level protocol ๐Ÿ’– built for distributed, collaborative, hypermedia information systems. It's been in use by the World-Wide Web global information initiative since 1990, so it's literally been the backbone of the web for ages ๐ŸŒ๐Ÿฆ‹. The very first version, called HTTP/0.9, was a simple protocol for raw data transfer across the Internet. Super basic, but it started the whole thing ๐ŸŒธ.

Then came HTTP/1.0, defined in RFC 1945 [6] ๐ŸŽ€. It leveled up by letting messages look like MIME-like messages, which means they could carry metainformation about the data being transferred plus modifiers on the request/response semantics. Iconic glow-up โœจ. BUT ngl, HTTP/1.0 didn't fully think about hierarchical proxies, caching, the need for persistent connections, or virtual hosts ๐Ÿ’€. On top of that, a bunch of half-finished apps were calling themselves "HTTP/1.0" ๐Ÿ™ˆ, which meant a protocol version change was needed so two apps could figure out each other's true capabilities. Bestie, the drama is real ๐Ÿ˜ญ.

So this specification defines the protocol known as "HTTP/1.1" ๐Ÿ‘‘. It comes with more stringent requirements than HTTP/1.0 so that its features actually get implemented reliably. No more vibes-based implementations, we want receipts ๐Ÿ’….

Real-world information systems need way more than simple retrieval. Think search, front-end update, and annotation ๐Ÿ”ฅ. HTTP lets you use an open-ended set of methods and headers that show the purpose of a request [47] ๐Ÿงš. It leans on the discipline of reference from the Uniform Resource Identifier (URI) [3], which can act as a location (URL) [4] or a name (URN) [20] to say which resource a method should be applied to ๐Ÿ’œ. Messages are passed in a format that's similar to Internet mail [9], as defined by the Multipurpose Internet Mail Extensions (MIME) [7] ๐Ÿ’Œ.

HTTP is also used as a generic protocol for talking between user agents and proxies/gateways to other Internet systems ๐ŸŒˆ. That includes the SMTP [16], NNTP [13], FTP [18], Gopher [2], and WAIS [10] protocols. So HTTP gives you basic hypermedia access to resources from all kinds of diverse applications, which is so main character energy ๐Ÿฆ‹โœจ.

1.2. Requirements

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [34] ๐ŸŽ€. These are the official capitalised vibes, so pay attention to them ๐Ÿ‘€.

An implementation is not compliant if it fails to satisfy one or more of the MUST or REQUIRED level requirements for the protocols it implements ๐Ÿšซ. An implementation that satisfies all the MUST or REQUIRED level and all the SHOULD level requirements for its protocols is said to be "unconditionally compliant" ๐Ÿ‘‘โœจ. One that satisfies all the MUST level requirements but not all the SHOULD level requirements for its protocols is said to be "conditionally compliant." ๐Ÿซถ Still valid, just not the full glam.

1.3 Terminology โœจ

okay bestie, this part is basically the glossary ๐Ÿ“š the spec uses a bunch of terms for the roles everyone plays in HTTP communication, plus the stuff they're passing around. let's go ๐Ÿ’…

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

message ๐Ÿ’Œ The basic unit of HTTP communication, consisting of 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, and resolutions) or vary in other ways. the main character of the whole spec, honestly ๐Ÿ‘‘

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). even the error responses get a say, iykyk ๐Ÿ™ˆ

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 varriant'. 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 being performed by the program 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. so a program isn't stuck as one thing forever, it just depends on which connection we're talking about โœจ

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. A "transparent proxy" is a proxy that does not modify the request or response beyond what is required for proxy authentication and identification. A "non-transparent proxy" is a proxy that modifies the request or response in order to provide some added service to the user agent, such as group annotation services, media type transformation, protocol reduction, or anonymity filtering. Except where either transparent or non-transparent behavior is explicitly stated, the HTTP proxy requirements apply to both types of proxies.

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 be aware that it is communicating with a gateway. sneaky, but make it make sense ๐Ÿ•ต๏ธโ€โ™€๏ธ

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 cacheable responses in order to reduce the 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.

cacheable ๐Ÿ’พ A response is cacheable if a cache is allowed to store a copy of the response message for use in answering subsequent requests. The rules for determining the cacheability of HTTP responses are defined in section 13. Even if a resource is cacheable, there may be additional constraints on whether a cache can use the cached copy for a particular request. "allowed to" is doing a lot of work here ๐Ÿ˜ญ

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. still good, no cap โœจ

stale ๐Ÿฅ€ A response is stale if its age has passed its freshness lifetime. rip ๐Ÿ’€

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. the cache is basically a ghost, but a fast one ๐Ÿ‘ป

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.

upstream/downstream โฌ†๏ธ Upstream and downstream describe the flow of a message: all messages flow from upstream to downstream.

inbound/outbound โ†ฉ๏ธ Inbound and outbound refer to the request and response paths for messages: "inbound" means "traveling toward the origin server", and "outbound" means "traveling toward the user agent"

1.4 Overall Operation โœจ

okay so HTTP is a request/response protocol ๐Ÿ’– A client sends a request to the server. The request has a request method, a URI, and a protocol version, then a MIME-like message with request modifiers, client info, and maybe a body ๐ŸŽ€ The server answers with a status line that has its protocol version and a success or error code, then its own MIME-like message with server info, entity metainformation, and maybe entity-body content ๐Ÿฆ‹ The relationship between HTTP and MIME is described in appendix 19.4 ๐ŸŒธ

Most HTTP communication starts with a user agent asking for something to be applied to a resource on some origin server ๐Ÿ’… In the simplest case it's one single connection (v) between the user agent (UA) and the origin server (O) โœจ

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

it gets more interesting when there are one or more intermediaries in the chain ๐Ÿ‘‘ There are three common kinds. A proxy is a forwarding agent ๐Ÿงš It gets requests for a URI in its absolute form, rewrites all or part of the message, then forwards the reformatted request toward the server the URI names. A gateway is a receiving agent that acts as a layer above some other server(s) and, if needed, 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 has to pass through an intermediary, like a firewall, even when that intermediary can't understand what's inside the messages ๐Ÿ™ˆ

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

this diagram has three intermediaries (A, B, and C) between the user agent and origin server ๐ŸŒˆ A request or response that travels the whole chain goes through four separate connections, and that distinction is a big deal ๐Ÿ˜ญ Some HTTP options might only apply to the connection with the nearest, non-tunnel neighbor, some only to the end-points of the chain, and some to every connection along the chain ๐Ÿ”ฅ The diagram is linear, but everybody 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 same time it's handling A's request ๐Ÿ’…

Any party in the communication that isn't acting as a tunnel may use an internal cache to handle requests โœจ The cache effect is that the request/response chain gets shorter if one of the participants has a cached response that applies to that request ๐Ÿฆ‹ This shows the resulting chain if B has a cached copy of an earlier response from O (via C) for a request that UA or A hasn't cached ๐Ÿซถ

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

not every response is worth caching, and some requests come with modifiers that put special demands on cache behavior ๐Ÿ™ˆ HTTP requirements for cache behavior and cacheable responses are defined in section 13 ๐Ÿ“š

there's a huge variety of cache and proxy setups being experimented with or deployed across the World Wide Web right now ๐ŸŒ That includes national hierarchies of proxy caches to save transoceanic bandwidth, systems that broadcast or multicast cache entries, organizations that hand out subsets of cached data on CD-ROM, and so on ๐Ÿ’ฟ HTTP systems run in corporate intranets over high-bandwidth links, and also for access from PDAs with low-power radio links and on-and-off connectivity ๐Ÿ“ฑ The goal of HTTP/1.1 is to support all that existing diversity while adding protocol constructs for people building web applications who need high reliability and, when that isn't possible, at least reliable indications of failure ๐Ÿ’–

HTTP usually runs over TCP/IP connections ๐ŸŽ€ The default port is TCP 80 [19], but other ports can be used ๐Ÿฆ‹ That doesn't stop HTTP from being implemented on top of any other protocol on the Internet, or on other networks ๐ŸŒธ HTTP only assumes a reliable transport, so any protocol that gives 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 โœจ

in HTTP/1.0, most implementations opened a new connection for each request/response exchange ๐Ÿ˜ญ In HTTP/1.1, a connection can be used for one or more request/response exchanges, although connections may get closed for a variety of reasons (see section 8.1) ๐Ÿ”ฅ


2 Notational Conventions and Generic Grammar โœจ

2.1 Augmented BNF โœจ

okay this part is the notation, so you'll need to know it to read the rest ๐Ÿค“ 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] ๐Ÿ’œ The augmented BNF has these constructs ๐Ÿงš

  • 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. White space only matters because indenting a continuation line shows that a rule definition spans more than one line. Certain basic rules are in uppercase, like SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle brackets are used inside definitions whenever their presence helps you tell which rule names are being used ๐ŸŽ€
  • "literal" Quotation marks surround literal text. Unless stated otherwise, the text is case-insensitive ๐ŸŒธ
  • rule1 | rule2 Elements separated by a bar ("|") are alternatives, e.g., "yes | no" will accept yes or no ๐Ÿฆ‹
  • (rule1 rule2) Elements enclosed in 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 element. The defaults 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 Specific repetition: "<n>(element)" is equivalent to "<n>*<n>(element)", which means exactly <n> occurrences of (element) ๐Ÿ’– So 2DIGIT is a 2-digit number, and 3ALPHA is a string of three alphabetic characters ๐Ÿ”ฅ
  • #rule A construct "#" is defined, similar to "*", for 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 white space (LWS) ๐Ÿ“ This makes the usual form of lists super easy. A rule like
( *LWS element *( *LWS "," *LWS element ))

can be written 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 it 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 defaults 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 rule text, starts a comment that runs to the end of the line ๐Ÿงš It's a simple way to put useful notes right next to the specs โœจ
  • implied *LWS The grammar in this specification is word-based ๐Ÿ’œ Except where noted otherwise, linear white space (LWS) can go between any two adjacent words (token or quoted-string), and between adjacent words and separators, without changing how a field is interpreted ๐ŸŒธ At least one delimiter (LWS and/or separators) MUST exist between any two tokens (for the definition of "token" below), because otherwise they'd be read as one single token ๐ŸŽ€

2.2. Basic Rules โœจ

Okay bestie, this is the vocab list everything else in the spec is built on ๐Ÿค“ These are the basic parsing building blocks, and the US-ASCII character set they use 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)>

HTTP/1.1 defines CR LF as the end-of-line marker for all protocol elements except the entity-body (see appendix 19.3 for tolerant applications). The end-of-line marker within an entity-body is defined by its associated media type, as described in section 3.7. ๐ŸŒธ

CRLF           = CR LF

HTTP/1.1 header field values can be folded onto multiple lines if the continuation line begins with a space or horizontal tab. All linear white space, including folding, has the same semantics as SP. A recipient MAY replace any linear white space with a single SP before interpreting the field value or forwarding the message downstream. ๐Ÿฆ‹

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

The TEXT rule is only used for descriptive field contents and values that are not intended to be interpreted by the message parser. Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22] only when encoded according to the rules of RFC 2047 [14]. ๐Ÿงš

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

A CRLF is allowed in the definition of TEXT only as part of a header field continuation. It is expected that the folding LWS will be replaced with a single SP before interpretation of the TEXT value.

Hexadecimal numeric characters are used in several protocol elements. ๐Ÿ“

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

Many HTTP/1.1 header field values consist of words separated by LWS or special characters. These special characters MUST be in a quoted string to be used within a parameter value (as defined in section 3.6). ๐ŸŽ€

token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@"
               | "," | ";" | ":" | "\" | <">
               | "/" | "[" | "]" | "?" | "="
               | "{" | "}" | SP | HT

Comments can be included in some HTTP header fields by surrounding the comment text with parentheses. Comments are only allowed in fields containing "comment" as part of their field value definition. In all other fields, parentheses are considered part of the field value. ๐Ÿ’œ

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

A string of text is parsed as a single word if it is quoted using double-quote marks. ๐Ÿซถ

quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext         = <any TEXT except <">>

The backslash character "\" MAY be used as a single-character quoting mechanism only within quoted-string and comment constructs. ๐Ÿ”ฅ

quoted-pair    = "\" CHAR

3. Protocol Parameters โœจ

3.1. HTTP Version ๐ŸŒˆ

HTTP uses a "<major>.<minor>" numbering scheme to indicate versions of the protocol. The versioning policy is there so the sender can show the format of a message and how much it can understand of further HTTP communication, rather than the features it gets from that communication. No change is made to the version number for the addition of message components which do not affect communication behavior or which only add to extensible field values. ๐Ÿฆ‹

The <minor> number goes up when the protocol changes add features that don't change the general message parsing algorithm, but that may add to the message semantics and imply additional capabilities of the sender. The <major> number goes up when the format of a message within the protocol changes. See RFC 2145 [36] for a fuller explanation. ๐ŸŒธ

The version of an HTTP message is indicated by an HTTP-Version field in the first line of the message.

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

Note that the major and minor numbers MUST be treated as separate integers and that each MAY be incremented higher than a single digit. Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and MUST NOT be sent. ๐Ÿ“

An application that sends a request or response message that includes HTTP-Version of "HTTP/1.1" MUST be at least conditionally compliant with this specification. Applications that are at least conditionally compliant with this specification SHOULD use an HTTP-Version of "HTTP/1.1" in their messages, and MUST do so for any message that is not compatible with HTTP/1.0. For more details on when to send specific HTTP-Version values, see RFC 2145 [36]. ๐Ÿ’…

The HTTP version of an application is the highest HTTP version for which the application is at least conditionally compliant. โญ

Proxy and gateway applications need to be careful when forwarding messages in protocol versions different from that of the application. Since the protocol version indicates the protocol capability of the sender, a proxy/gateway MUST NOT send a message with a version indicator which is greater than its actual version. If a higher version request is received, the proxy/gateway MUST either downgrade the request version, or respond with an error, or switch to tunnel behavior. ๐Ÿ‘‘

Due to interoperability problems with HTTP/1.0 proxies discovered since the publication of RFC 2068[33], caching proxies MUST, gateways MAY, and tunnels MUST NOT upgrade the request to the highest version they support. The proxy/gateway's response to that request MUST be in the same major version as the request. ๐Ÿ™ˆ

Note: Converting between versions of HTTP may involve modification of header fields required or forbidden by the versions involved.

3.2. Uniform Resource Identifiers ๐Ÿฆ‹

URIs have been known by many names: WWW addresses, Universal Document Identifiers, Universal Resource Identifiers [3], and finally the combination of Uniform Resource Locators (URL) [4] and Names (URN) [20]. As far as HTTP is concerned, Uniform Resource Identifiers are simply formatted strings which identify (via name, location, or any other characteristic) a resource. ๐Ÿงš

3.2.1. General Syntax ๐Ÿ’–

URIs in HTTP can be represented in absolute form or relative to some known base URI [11], depending upon the context of their use. The two forms are differentiated by the fact that absolute URIs always begin with a scheme name followed by a colon. For definitive information on URL syntax and semantics, see "Uniform Resource Identifiers (URI): Generic Syntax and Semantics," RFC 2396 [42] (which replaces RFCs 1738 [4] and RFC 1808 [11]). This specification adopts the definitions of "URI-reference", "absoluteURI", "relativeURI", "port", "host", "abs_path", "rel_path", and "authority" from that specification. ๐ŸŒˆ

The HTTP protocol does not place any a priori limit on the length of a URI. 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 ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.

3.2.2. http URL ๐ŸŒธ

The "http" scheme is used to locate network resources via the HTTP protocol. This section defines the scheme-specific syntax and semantics for http URLs. ๐Ÿ“

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

If the port is empty or not given, port 80 is assumed. The semantics are that the identified resource is located at the server listening for TCP connections on that port of that host, and the Request-URI for the resource is abs_path (section 5.1.2). The use of IP addresses in URLs SHOULD be avoided whenever possible (see RFC 1900 [24]). If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource (section 5.1.2). If a proxy receives a host name which is not a fully qualified domain name, it MAY add its domain to the host name it received. If a proxy receives a fully qualified domain name, the proxy MUST NOT change the host name. ๐ŸŽ€

3.2.3. URI Comparison ๐Ÿ”ฅ

When comparing two URIs to decide if they match or not, a client SHOULD use a case-sensitive octet-by-octet comparison of the entire URIs, with these exceptions:

  • A port that is empty or not given is equivalent to the default port for that URI-reference;
  • 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 other than those in the "reserved" and "unsafe" sets (see RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding. ๐Ÿ’œ

For example, the following 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 so HTTP apps have historically let people write date/time stamps in three different formats ๐Ÿ•ฐ๏ธ ๐Ÿ˜ญ

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 one is the fave โœจ It's the preferred Internet standard, and it's a fixed-length subset of what RFC 1123 [8] defines (RFC 1123 is an update to RFC 822 [9]). The second one is super common in the wild, but it's built on the outdated RFC 850 [12] date format and it doesn't 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. See section 19.3 for further information. ๐ŸŽ€

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. ๐ŸŒˆ For the purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal Time). This is indicated in the first two formats by the inclusion of "GMT" as the three-letter abbreviation for time zone, and MUST be assumed when reading the asctime format. HTTP-date is case sensitive and MUST NOT include additional LWS beyond that specifically included as SP in the grammar. no extra spaces, we are being precise bestie ๐Ÿ’…

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. so your logs can look however you want ๐Ÿฆ‹

3.3.2. Delta Seconds

some HTTP header fields let you give a time value as a whole number of seconds (written in decimal) counted from the moment the message was received โฑ๏ธ โœจ

delta-seconds  = 1*DIGIT

3.4. Character Sets

HTTP uses the exact same definition of "character set" that MIME uses ๐Ÿงš Here's how the spec puts it:

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 encoding, 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

Although HTTP allows an arbitrary token to be used as a charset value, any token that has a predefined value within the IANA Character Set registry [19] MUST represent the character set defined by that registry. Applications SHOULD limit their use of character sets to those defined by the IANA registry. keep it in the lane, babe ๐Ÿ›ฃ๏ธ

Implementors should be aware of IETF character set requirements [38] [41]. ๐Ÿซถ

3.4.1. Missing Charset

some HTTP/1.0 software read a Content-Type header with no charset parameter as "recipient should guess" ๐Ÿ™ˆ Senders who want to defeat that behavior MAY include a charset parameter even when the charset is ISO-8859-1, and SHOULD do so when it is known that it will not confuse the recipient.

ngl, some older HTTP/1.0 clients didn't handle an explicit charset parameter properly either ๐Ÿ’€ So HTTP/1.1 recipients MUST respect the charset label provided by the sender. And any user agents that have a provision to "guess" a charset MUST use the charset from the content-type field if they support that charset, rather than the recipient's preference, when initially displaying a document. See section 3.7.1. ๐Ÿ‘‘


3.5. Content Codings

content coding values name an encoding transformation that has been applied (or could be applied) to an entity ๐ŸŽ The whole point is to let a document get compressed or otherwise 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.11) header fields. Even though the value describes the content coding, 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. Initially, 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).
  • deflate: The "zlib" format defined in RFC 1950 [31] in combination with the "deflate" compression mechanism described in RFC 1951 [29].
  • identity: The default (identity) encoding; the use of no transformation whatsoever. This content-coding is used only in the Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding header.

Quick heads-up on compress: using program names to identify encoding formats is not desirable, and it's 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.

New content-coding value tokens SHOULD be registered. To allow interoperability between clients and servers, the specifications of the content coding algorithms needed to implement a new value SHOULD be publicly available and adequate for independent implementation, and conform to the purpose of content coding defined in this section. the interop goals are literally everything ๐ŸŒโœจ


3.6. Transfer Codings

transfer-coding values are used to indicate an encoding transformation that has been, can be, or may need to be applied to an entity-body in order to ensure "safe transport" through the network ๐Ÿšš This is different from a content coding, because the transfer-coding is a property of the message, not of the original entity. main character energy for the message ๐Ÿ’œ

transfer-coding         = "chunked" | transfer-extension
transfer-extension      = token *( ";" parameter )

Parameters are in the form of attribute/value pairs.

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

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

Whenever a transfer-coding is applied to a message-body, the set of transfer-codings MUST include "chunked", unless the message is terminated by closing the connection. When the "chunked" transfer-coding is used, it MUST be the last transfer-coding applied to the message-body. The "chunked" transfer-coding MUST NOT be applied more than once to a message-body. These rules let the recipient figure out the transfer-length of the message (section 4.4). ๐Ÿงฉ

Transfer-codings are analogous to the Content-Transfer-Encoding values of MIME [7], which were designed to enable safe transport of binary data over a 7-bit transport service. However, "safe transport" means something different for an 8bit-clean transfer protocol. In HTTP, the only unsafe characteristic of message-bodies is the difficulty in determining the exact body length (section 7.2.2), or the desire to encrypt data over a shared transport. ๐Ÿ”’

The Internet Assigned Numbers Authority (IANA) acts as a registry for transfer-coding value tokens. Initially, the registry contains the following tokens: "chunked" (section 3.6.1), "identity" (section 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate" (section 3.5).

New transfer-coding value tokens SHOULD be registered in the same way as new content-coding value tokens (section 3.5). ๐Ÿ“

A server which receives an entity-body with a transfer-coding it does not understand SHOULD return 501 (Unimplemented), and close the connection. A server MUST NOT send transfer-codings to an HTTP/1.0 client. ๐Ÿšซ๐Ÿ’…

3.6.1 Chunked Transfer Coding

okay so chunked encoding is literally the best way to send a body in pieces ๐ŸŽ€ each chunk gets its own size label, and you can add an OPTIONAL trailer full of entity-header fields at the end. It's perfect for stuff that gets made on the fly, because the receiver can still check that the whole message showed up โœจ

    Chunked-Body   = *chunk
                     last-chunk
                     trailer
                     CRLF

    chunk          = chunk-size [ chunk-extension ] CRLF
                     chunk-data CRLF
    chunk-size     = 1*HEX
    last-chunk     = 1*("0") [ chunk-extension ] CRLF

    chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
    chunk-ext-name = token
    chunk-ext-val  = token | quoted-string
    chunk-data     = chunk-size(OCTET)
    trailer        = *(entity-header CRLF)

So chunk-size is a string of hex digits that tells you how big the chunk is ๐Ÿฆ‹ The whole thing ends when you hit a chunk with size zero, then the trailer, and then an empty line to close it out ๐Ÿ’…

The trailer lets the sender tack extra HTTP header fields onto the very end of the message ๐ŸŒธ The Trailer header field is how you say which header fields are sitting in the trailer (see section 14.40), so people know what to expect.

Now here's the rule that matters ๐Ÿ™ˆ A server using chunked transfer-coding in a response MUST NOT put any header fields in the trailer unless at least one of these is true:

  • a) the request had a TE header field that says "trailers" is acceptable in the transfer-coding of the response, as described in section 14.39; or,
  • b) the server is the origin server for the response, the trailer fields are entirely optional metadata, and the recipient could still use the message (in a way the origin server is fine with) without getting that metadata. Basically, the origin server is cool with the trailer fields maybe getting silently dropped on the way to the client.

Why does this rule exist? ๐Ÿฅบ It stops an interop disaster when an HTTP/1.1 (or later) proxy gets a message and forwards it to an HTTP/1.0 recipient. Without it, following the protocol could force the proxy to keep a possibly infinite buffer, and nobody wants that bestie ๐Ÿ˜ญ

An example process for decoding a Chunked-Body is in appendix 19.4.6, so go peek at that if you want to see it in action ๐Ÿงš

Okay, the big one: all HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding, and they MUST ignore any chunk-extension extensions they don't understand ๐Ÿซถ no drama, just skip what you don't know, periodt ๐Ÿ’€


3.7 Media Types

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

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

Parameters MAY follow the type/subtype as attribute/value pairs (as defined in section 3.6) โœจ

The type, subtype, and parameter attribute names are case-insensitive ๐Ÿ’œ Parameter values might or might not be case-sensitive, depending on what the parameter name means. Linear white space (LWS) MUST NOT show up between the type and subtype, or between an attribute and its value ๐Ÿ™…โ€โ™€๏ธ Whether a parameter is there or not might matter for how a media-type gets processed, depending on how it's defined in the media type registry.

Heads up though: some older HTTP apps don't even recognize media type parameters ๐Ÿ‘€ So when you're sending data to those older apps, implementations SHOULD only use media type parameters when that type/subtype definition actually requires them.

Media-type values are registered with the Internet Assigned Number Authority (IANA [19]) ๐Ÿ“ The registration process is outlined in RFC 1590 [17]. Using non-registered media types is discouraged, so maybe don't ๐Ÿ™ƒ

3.7.1 Canonicalization and Text Defaults

Internet media types get registered with a canonical form ๐ŸŽ€ An entity-body sent over HTTP MUST be in the right canonical form before it's transmitted, except for "text" types (more on that in the next paragraph).

When it's in canonical form, media subtypes of the "text" type use CRLF as the text line break ๐Ÿ’… HTTP relaxes this a bit and lets text media use plain CR or plain LF as a line break, but only if 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 where octets 13 and 10 don't mean CR and LF (which happens with some multi-byte character sets), HTTP lets you use whatever octet sequences that character set defines as the equivalent of CR and LF for line breaks โœจ This flexibility only covers 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 is encoded with a content-coding, the underlying data MUST be in one of the forms above before it gets encoded ๐ŸŒธ

The "charset" parameter is used with some media types to say what character set the data is in ๐Ÿ’œ When the sender doesn't give an explicit charset parameter, media subtypes of the "text" type default to a charset value of "ISO-8859-1" when they come in over HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value ๐Ÿท๏ธ Check section 3.4.1 for compatibility problems, because there are some.

3.7.2 Multipart Types

MIME has a bunch of "multipart" types ๐Ÿงš they're encapsulations of one or more entities packed into a single message-body. All multipart types share the same syntax, defined in section 5.1.1 of RFC 2046 [40], and they MUST include a boundary parameter as part of the media type value ๐Ÿ’– The message body is a protocol element itself, so it MUST use only CRLF for line breaks between body-parts ๐ŸŽ€

Here's the twist: unlike in RFC 2046, the epilogue of any multipart message MUST be empty, and HTTP applications MUST NOT transmit the epilogue, even if the original multipart had one ๐Ÿ™ˆ These rules keep the multipart message-body self-delimiting, which means the "end" of the body is marked by the ending multipart boundary โœจ

Generally, HTTP treats a multipart message-body like any other media type, which is to say purely as payload ๐ŸŒˆ The one exception is the "multipart/byteranges" type (appendix 19.2) when it shows up in a 206 (Partial Content) response. Some HTTP caching mechanisms will interpret that one, as described in sections 13.5.4 and 14.16 ๐Ÿ‘€ In every other case, an HTTP user agent SHOULD act the same as, or very similar to, a MIME user agent would when it gets a multipart type. The MIME header fields inside each body-part don't mean anything to HTTP beyond what their MIME semantics already say ๐Ÿ’…

Again, an HTTP user agent SHOULD follow the same or similar behavior as a MIME user agent would upon receiving a multipart type ๐Ÿฆ‹ And if an application gets a multipart subtype it doesn't recognize, it MUST treat it as equivalent to "multipart/mixed" ๐Ÿซถ

Note: The "multipart/form-data" type was specifically defined for carrying form data meant for processing via the POST request method, as described in RFC 1867 [15]. ๐Ÿ“

3.8 Product Tokens

Product tokens let apps say who they are by software name and version ๐ŸŒธ Most fields that use product tokens also let you list sub-products that make up a big part of the app, separated by white space. By convention, the products get listed in order of how much they matter for identifying the application ๐Ÿ‘‘

    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 ๐Ÿ’– They MUST NOT be used for advertising or other non-essential info, so no ads in your User-Agent, bestie ๐Ÿ™…โ€โ™€๏ธ Any token character MAY appear in a product-version, but this token SHOULD only be used for a version identifier. Basically, 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 various negotiable parameters are, aka their "weight" ๐Ÿ’œ A weight gets normalized to a real number from 0 through 1, where 0 is the minimum and 1 is the maximum. If a parameter has a quality value of 0, then content with that parameter is `not acceptable' for the client ๐Ÿ™…โ€โ™€๏ธ HTTP/1.1 applications MUST NOT generate more than three digits after the decimal point ๐Ÿ”ฅ User configuration of these values SHOULD also be limited in that same way ๐Ÿงš

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

"Quality values" is kind of a misnomer, tbh ๐Ÿ’€ These values really just represent 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 other humans ๐ŸŒธ Computer languages are explicitly excluded, sorry coders ๐Ÿ™ˆ 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 one or more parts: a primary language tag, then a possibly empty series of subtags ๐Ÿฆ‹

     language-tag  = primary-tag *( "-" subtag )
     primary-tag   = 1*8ALPHA
     subtag        = 1*8ALPHA

White space 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

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 are examples of tags that could be registered in the future ๐Ÿ’…)

3.11 Entity Tags ๐Ÿท๏ธ

Okay bestie, entity tags are how we compare two or more entities that come from the same requested resource ๐Ÿ’… HTTP/1.1 uses them in the ETag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. How they get used and compared as cache validators is covered in section 13.3.3. An entity tag is an opaque quoted string, and it can have a weakness indicator stuck on the front โœจ

entity-tag = [ weak ] opaque-tag
weak       = "W/"
opaque-tag = quoted-string

A "strong entity tag" MAY be shared by two entities of a resource, but only if they are equivalent by octet equality. Strong and exact, no cap ๐Ÿ”ฅ

A "weak entity tag," marked with the "W/" prefix, MAY be shared by two entities of a resource, but 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, so it's giving "close enough, not identical" ๐Ÿ’œ

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. Still, using the same entity tag value with entities from different URIs does not imply that those entities are equivalent. Don't assume a match just because the tags look the same ๐Ÿ™ˆ


3.12 Range Units ๐ŸŒธ

So this is the part where a client can ask for just a slice (a range) of the response entity instead of the whole thing ๐Ÿ“ HTTP/1.1 uses range units in the Range (section 14.35) and Content-Range (section 14.16) header fields. An entity can be split 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 that are specified using other units, so they don't have to care about those ๐Ÿงš

HTTP/1.1 was designed so that applications which don't depend on knowing about ranges can still be built and work just fine ๐Ÿซถ


4 HTTP Message ๐Ÿ’Œ

4.1 Message Types ๐Ÿ’ฌ

HTTP messages are made of requests going from client to server, and responses going from server to client. Simple ๐Ÿ˜Œ

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] to carry entities (the payload of the message) ๐Ÿ“ฆ Both kinds of message have a start-line, zero or more header fields (also called "headers"), an empty line (meaning a line with nothing before the CRLF) that marks the end of the header fields, and possibly a message-body.

generic-message = start-line
                  *(message-header CRLF)
                  CRLF
                  [ message-body ]
start-line      = Request-Line | Status-Line

For robustness, servers SHOULD ignore any empty line(s) they get where a Request-Line is expected ๐Ÿฅน In other words, if a server is reading the protocol stream at the start of a message and gets a CRLF first, it should just ignore that CRLF.

Some buggy HTTP/1.0 client implementations send extra CRLFs after a POST request ๐Ÿ˜ญ To restate what the BNF already explicitly forbids: an HTTP/1.1 client MUST NOT preface or follow a request with an extra CRLF. No extra CRLFs, periodt ๐Ÿ’…

4.2 Message Headers ๐ŸŽ€

HTTP header fields are the general-header (section 4.5), request-header (section 5.3), response-header (section 6.2), and entity-header (section 7.1) fields ๐Ÿง They all follow the same generic format as the one in Section 3.1 of RFC 822 [9]. Each header field is a name, then a colon (":"), then the field value. Field names are case-insensitive ๐Ÿ™Œ The field value MAY be preceded by any amount of LWS, although a single SP is preferred. Header fields can be extended over multiple lines by starting each extra line with at least one SP or HT. When you're generating HTTP constructs, applications ought to follow "common form" where one is known or indicated, because some implementations might fail to accept anything beyond the common forms ๐Ÿซ 

message-header = field-name ":" [ field-value ]
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, separators, and quoted-string>

The field-content doesn't include any leading or trailing LWS ๐Ÿ’– That's linear white space before the first non-whitespace character of the field-value, or after the last non-whitespace character of it. Such leading or trailing LWS MAY be removed without changing the semantics of the field value โœจ Any LWS that appears between field-content MAY be replaced with a single SP before the field value is interpreted or the message is forwarded downstream.

The order of header fields with different field names doesn't matter ๐ŸŒˆ However, it's "good practice" to send general-header fields first, then request-header or response-header fields, and to end with the entity-header fields ๐Ÿ“‹

Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list (that is, #(values)) ๐Ÿงฉ It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each later field-value to the first one, each separated by a comma. The order of header fields with the same field-name is therefore significant to how the combined field value is interpreted, so a proxy MUST NOT change the order of these field values when it forwards a message ๐Ÿšซ Order matters, bestie ๐Ÿ‘‘

4.3 Message Body ๐Ÿฐ

The message-body (if there is one) of an HTTP message carries the entity-body associated with the request or response ๐ŸŽ The message-body only differs from the entity-body when a transfer-coding has been applied, as shown by the Transfer-Encoding header field (section 14.41).

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

Transfer-Encoding MUST be used to indicate any transfer-codings an application has applied to make sure the message gets transferred safely and properly ๐Ÿ›ก๏ธ Transfer-Encoding is a property of the message, not of the entity, so ANY application along the request/response chain MAY add or remove it. (Section 3.6 does place restrictions on when certain transfer-codings may be used, so check that too ๐Ÿค“)

The rules for when a message-body is allowed in a message are different for requests and responses ๐Ÿ™ƒ

The presence of a message-body in a request is signaled by including a Content-Length or Transfer-Encoding header field in the request's message-headers ๐Ÿ“ฎ A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) doesn't allow sending an entity-body in requests ๐Ÿšท A server SHOULD read and forward a message-body on any request. If the request method has no defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

For response messages, whether or not a message-body is included depends on both the request method and the response status code (section 6.1.1) ๐ŸŽญ All responses to the HEAD request method MUST NOT include a message-body, even though the presence of entity-header fields might make you think they should ๐Ÿ™ˆ All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body. Every other response does include a message-body, although it MAY be of zero length ๐Ÿซง

4.4 Message Length ๐Ÿ“

The transfer-length of a message is the length of the message-body as it appears in the message, meaning after any transfer-codings have been applied ๐Ÿงฎ When a message-body is included with a message, the transfer-length of that body is determined by one of the following, listed in order of precedence:

  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 terminated by the first empty line after the header fields, regardless of which entity-header fields are present in the message ๐Ÿ›‘
  2. If a Transfer-Encoding header field (section 14.41) is present and has any value other than "identity", then the transfer-length is defined by use of the "chunked" transfer-coding (section 3.6), unless the message is terminated by closing the connection ๐Ÿงธ
  3. If a Content-Length header field (section 14.13) is present, its decimal value in OCTETs represents both the entity-length and the transfer-length ๐Ÿ”ข The Content-Length header field MUST NOT be sent if these two lengths are different (that is, if a Transfer-Encoding header field is present). If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored ๐Ÿ™…โ€โ™€๏ธ
  4. If the message uses the media type "multipart/byteranges", and the transfer-length is not otherwise specified, then this self-delimiting media type defines the transfer-length ๐Ÿงต This media type MUST NOT be used unless the sender knows that the recipient can parse it. The presence of a Range header with multiple byte-range specifiers in a request from a 1.1 client implies that the client can parse multipart/byteranges responses ๐Ÿง 
A Range header might be forwarded by a 1.0 proxy that doesn't understand multipart/byteranges. In that case, the server MUST delimit the message using the methods defined in items 1, 3, or 5 of this section ๐Ÿšฆ
  1. By the server closing the connection. (Closing the connection can't be used to mark the end of a request body, since that would leave no way for the server to send back a response ๐Ÿ”š)

For compatibility with HTTP/1.0 applications, HTTP/1.1 requests containing 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 contains a message-body and no Content-Length is given, the server SHOULD respond with 400 (bad request) if it can't determine the length of the message, or with 411 (length required) if it wants to insist on receiving a valid Content-Length ๐Ÿšซ

All HTTP/1.1 applications that receive entities MUST accept the "chunked" transfer-coding (section 3.6), which lets this mechanism be used for messages whose length can't be determined in advance ๐Ÿญ

Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding. If the message does include a non-identity transfer-coding, the Content-Length MUST be ignored ๐Ÿ™ƒ

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 ๐ŸŽฏ HTTP/1.1 user agents MUST notify the user when an invalid length is received and detected. So if the length is wrong, the user finds out, no cap ๐Ÿ‘€

4.5 General Header Fields ๐Ÿ’Œ

okay so there are a few header fields that are relevant for BOTH requests and responses ๐Ÿซถ but they don't describe the entity being transferred at all. they only apply to the message being sent right now โœจ no cap, it's giving separate lane energy ๐Ÿฆ‹

       general-header = Cache-Control            ; Section 14.9
                      | Connection               ; Section 14.10
                      | Date                     ; Section 14.18
                      | Pragma                   ; Section 14.32
                      | Trailer                  ; Section 14.40
                      | Transfer-Encoding        ; Section 14.41
                      | Upgrade                  ; Section 14.42
                      | Via                      ; Section 14.45
                      | Warning                  ; Section 14.46

general-header field names can only be extended reliably together with a change in the protocol version ๐Ÿ’œ but, bestie, new or experimental header fields may be given the semantics of general header fields if every party in the conversation recognizes them as general header fields ๐Ÿงš and anything nobody recognizes gets treated as an entity-header field ๐Ÿ’…

5 Request ๐Ÿ“ฎ

okay the request is the message a client sends to a server ๐Ÿซถ and in its very first line it has to spill three things: the method to apply, the identifier of the resource, and the protocol version it's using ๐Ÿ’–

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

5.1 Request-Line ๐ŸŽ€

the Request-Line starts with a method token, then the Request-URI, then the protocol version, and it ends with CRLF โœจ everything is split up by SP characters, and no CR or LF is allowed anywhere except in that final CRLF sequence ๐Ÿ™ˆ

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

5.1.1 Method ๐ŸŒธ

the Method token tells the server what to do to the resource named in the Request-URI, and it is case-sensitive, so capitalisation matters, periodt ๐Ÿ’…

       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
                      | "CONNECT"                ; Section 9.9
                      | extension-method
       extension-method = token

the list of methods a resource allows can be spelled out in an Allow header field (section 14.7) ๐Ÿ“ and the status code in the response always tells the client whether a method is allowed on that resource right now, since the allowed set can change on the fly ๐Ÿฆ‹ an origin server SHOULD send back 405 (Method Not Allowed) when it knows the method but the requested resource doesn't allow it, and 501 (Not Implemented) when the method is unrecognized or the origin server just doesn't implement it ๐Ÿ˜ญ GET and HEAD MUST be supported by every general-purpose server ๐Ÿ‘‘ all the other methods are OPTIONAL ๐Ÿ“ but if the methods above are implemented, they MUST be implemented with the same semantics as the ones in section 9 ๐Ÿ”ฅ

5.1.2 Request-URI ๐Ÿฆ‹

the Request-URI is a Uniform Resource Identifier (section 3.2) and it names the resource the request should be applied to ๐ŸŒˆ

       Request-URI    = "*" | absoluteURI | abs_path | authority

there are four options for the Request-URI and which one you get depends on what kind of request it is ๐Ÿงš the asterisk "*" means the request isn't about a particular resource, it's about the server itself, and it's only allowed when the method doesn't have to apply to a resource ๐Ÿ’€ one example is

OPTIONS * HTTP/1.1

the absoluteURI form is REQUIRED when the request is going to a proxy ๐Ÿซถ the proxy is asked to forward the request, or to serve it from a valid cache, and then return the response โœจ the proxy MAY forward the request on to another proxy, or straight to the server named in the absoluteURI ๐Ÿ’œ and 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 looks like this:

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 authority form is only used by the CONNECT method (section 9.9) ๐ŸŽ€

now the most common form, which identifies a resource on an origin server or gateway ๐ŸŒˆ here the absolute path of the URI MUST be sent (see section 3.2.1, abs_path) as the Request-URI, and the network location of the URI (the authority) MUST be sent in a Host header field โœจ say a client wants that resource straight from the origin server, it opens a TCP connection to port 80 of the host "www.w3.org" and sends these lines:

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

and then the rest of the request follows ๐Ÿงš the absolute path can't be empty, so if the original URI doesn't have one, it MUST be given as "/" (the server root) ๐Ÿ‘‘

the Request-URI gets transmitted in the format from section 3.2.1 ๐Ÿ’– if it's encoded with the "% HEX HEX" encoding [42], the origin server MUST decode the Request-URI to properly interpret the request ๐Ÿ”ฅ servers SHOULD respond to invalid Request-URIs with a suitable status code ๐Ÿ˜ญ

a transparent proxy MUST NOT rewrite the "abs_path" part of the Request-URI it receives when it forwards it to the next inbound server, except for the one exception above, where a null abs_path gets replaced 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 URI character for a reserved purpose. Implementors 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 ๐Ÿ”

the exact resource an Internet request identifies is worked out by looking at BOTH the Request-URI and the Host header field ๐Ÿซถ

an origin server that doesn't let resources differ by the requested host MAY ignore the Host header field value when it works out which resource an HTTP/1.1 request is for ๐ŸŒธ (but check out section 19.6.1.1 for the other Host support requirements in HTTP/1.1 ๐Ÿ“)

an origin server that DOES tell resources apart by the host requested (you might hear these called virtual hosts or vanity host names โœจ) MUST use the following rules to work out the requested resource on an HTTP/1.1 request ๐Ÿ‘‘

  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 attempt to use heuristics (for example, looking at the URI path for something unique to a particular host) to figure out exactly which resource is being requested ๐Ÿงš detective era ๐Ÿ•ต๏ธโ€โ™€๏ธ

5.3 Request Header Fields ๐ŸŽ€

the request-header fields let the client pass along extra info about the request, and about the client itself, to the server ๐Ÿ’– they act as request modifiers, kinda like the parameters you'd 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
                      | Expect                   ; Section 14.20
                      | From                     ; Section 14.22
                      | Host                     ; Section 14.23
                      | If-Match                 ; Section 14.24
                      | If-Modified-Since        ; 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.35
                      | Referer                  ; Section 14.36
                      | TE                       ; Section 14.39
                      | User-Agent               ; Section 14.43

request-header field names can only be extended reliably together with a change in the protocol version ๐ŸŒˆ however, new or experimental header fields MAY be given the semantics of request-header fields if every party in the communication recognizes them as request-header fields ๐Ÿฆ‹ and anything unrecognized gets treated as an entity-header field ๐Ÿ’…

6 Response ๐ŸŒŸ

once a server has received and understood a request message, it replies with an HTTP response message ๐Ÿ’Œ

       Response      = Status-Line               ; Section 6.1
                       *(( general-header        ; Section 4.5
                        | response-header        ; Section 6.2
                        | entity-header ) CRLF)  ; Section 7.1
                       CRLF
                       [ message-body ]          ; Section 7.2

6.1 Status-Line ๐Ÿ“

the first line of a Response message is the Status-Line ๐Ÿซถ it's made of the protocol version, then a numeric status code, then its textual phrase, with each part separated by SP characters โœจ and again, 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 โœจ

okay so 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 a short textual description of the Status-Code ๐ŸŒธ. the Status-Code is for automata (aka machines) and the Reason-Phrase is for the human user ๐Ÿงš, and the client is not required to examine or display the Reason-Phrase ๐Ÿซถ.

the first digit of the Status-Code tells you the class of the response, and the last two digits don't do any categorizing at all ๐Ÿ“. there are 5 possible 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 ๐Ÿ˜ญ

the individual values of the numeric status codes defined for HTTP/1.1 are listed below, along with an example set of matching Reason-Phrases ๐Ÿ’œ. the reason phrases are only recommendations, so they MAY be replaced by local equivalents without affecting the protocol ๐Ÿ‘‘.

Status-Code    =
      "100"  ; Section 10.1.1: Continue
    | "101"  ; Section 10.1.2: Switching Protocols
    | "200"  ; Section 10.2.1: OK
    | "201"  ; Section 10.2.2: Created
    | "202"  ; Section 10.2.3: Accepted
    | "203"  ; Section 10.2.4: Non-Authoritative Information
    | "204"  ; Section 10.2.5: No Content
    | "205"  ; Section 10.2.6: Reset Content
    | "206"  ; Section 10.2.7: Partial Content
    | "300"  ; Section 10.3.1: Multiple Choices
    | "301"  ; Section 10.3.2: Moved Permanently
    | "302"  ; Section 10.3.3: Found
    | "303"  ; Section 10.3.4: See Other
    | "304"  ; Section 10.3.5: Not Modified
    | "305"  ; Section 10.3.6: Use Proxy
    | "307"  ; Section 10.3.8: Temporary Redirect
    | "400"  ; Section 10.4.1: Bad Request
    | "401"  ; Section 10.4.2: Unauthorized
    | "402"  ; Section 10.4.3: Payment Required
    | "403"  ; Section 10.4.4: Forbidden
    | "404"  ; Section 10.4.5: Not Found
    | "405"  ; Section 10.4.6: Method Not Allowed
    | "406"  ; Section 10.4.7: Not Acceptable
    | "407"  ; Section 10.4.8: Proxy Authentication Required
    | "408"  ; Section 10.4.9: Request Time-out
    | "409"  ; Section 10.4.10: Conflict
    | "410"  ; Section 10.4.11: Gone
    | "411"  ; Section 10.4.12: Length Required
    | "412"  ; Section 10.4.13: Precondition Failed
    | "413"  ; Section 10.4.14: Request Entity Too Large
    | "414"  ; Section 10.4.15: Request-URI Too Large
    | "415"  ; Section 10.4.16: Unsupported Media Type
    | "416"  ; Section 10.4.17: Requested range not satisfiable
    | "417"  ; Section 10.4.18: Expectation Failed
    | "500"  ; Section 10.5.1: Internal Server Error
    | "501"  ; Section 10.5.2: Not Implemented
    | "502"  ; Section 10.5.3: Bad Gateway
    | "503"  ; Section 10.5.4: Service Unavailable
    | "504"  ; Section 10.5.5: Gateway Time-out
    | "505"  ; Section 10.5.6: HTTP Version not supported
    | extension-code

extension-code = 3DIGIT
Reason-Phrase  = *<TEXT, excluding CR, LF>

HTTP status codes are extensible ๐Ÿงฉ. HTTP applications are not required to understand the meaning of all registered status codes, though such understanding is obviously desirable ๐Ÿค“. however, applications MUST understand the class of any status code, as indicated by the first digit, and treat any unrecognized response as being equivalent to the x00 status code of that class ๐Ÿ”ฅ, with the exception that an unrecognized response MUST NOT be cached ๐Ÿ™ˆ. for example, if an unrecognized status code of 431 is received by the client, it can safely assume that there was something wrong with its request and treat the response as if it had received a 400 status code ๐Ÿ’…. in such cases, user agents SHOULD present to the user the entity returned with the response, since that entity is likely to include human-readable information which will explain the unusual status ๐Ÿซถ.


6.2. Response Header Fields โœจ

the response-header fields let the server pass along extra information about the response that can't fit in the Status-Line ๐ŸŽ€. these header fields give information about the server and about further access to the resource identified by the Request-URI ๐Ÿงš.

response-header = Accept-Ranges           ; Section 14.5
                | Age                     ; Section 14.6
                | ETag                    ; Section 14.19
                | Location                ; Section 14.30
                | Proxy-Authenticate      ; Section 14.33
                | Retry-After             ; Section 14.37
                | Server                  ; Section 14.38
                | Vary                    ; Section 14.44
                | WWW-Authenticate        ; Section 14.47

response-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 response-header fields if all parties in the communication recognize them to be response-header fields ๐ŸŒˆ. unrecognized header fields are treated as entity-header fields ๐Ÿฆ‹.


7. Entity ๐ŸŒธ

Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code ๐Ÿซถ. an entity is made up of entity-header fields and an entity-body, although some responses will only include the entity-headers ๐Ÿ“.

in this section, both sender and recipient refer to either the client or the server, depending on who sends and who receives the entity ๐Ÿงš.

7.1. Entity Header Fields ๐Ÿ’…

entity-header fields define metainformation about the entity-body or, if no body is present, about the resource identified by the request ๐ŸŽ€. some of this metainformation is OPTIONAL, and some might be REQUIRED by portions of this specification ๐Ÿ‘‘.

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

extension-header = message-header

the extension-header mechanism lets you define extra entity-header fields without changing the protocol, but those fields can't be assumed to be recognizable by the recipient ๐Ÿฆ‹. unrecognized header fields SHOULD be ignored by the recipient and MUST be forwarded by transparent proxies ๐Ÿ”ฅ.

7.2. Entity Body ๐ŸŒˆ

the entity-body (if there is one) sent with an HTTP request or response is in a format and encoding defined by the entity-header fields โœจ.

entity-body    = *OCTET

an entity-body only shows up in a message when a message-body is present, as described in section 4.3 ๐Ÿงฉ. the entity-body is obtained from the message-body by decoding any Transfer-Encoding that might have been applied to keep the transfer safe and proper ๐Ÿซถ.

7.2.1. Type ๐Ÿ’–

when an entity-body comes along with a message, its data type is determined by the header fields Content-Type and Content-Encoding ๐Ÿ“. together they make a two-layer, ordered encoding model ๐Ÿ”ฅ:

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

Content-Type specifies the media type of the underlying data ๐ŸŽ€. Content-Encoding can be used to indicate any additional content codings applied to the data, usually for compression, that are a property of the requested resource ๐Ÿงš. there is no default encoding ๐Ÿ™ˆ.

any HTTP/1.1 message containing an entity-body SHOULD include a Content-Type header field defining the media type of that body ๐Ÿ’…. if and only if the media type is not given by a Content-Type field, the recipient MAY attempt to guess the media type by inspecting its content and/or the name extension(s) of the URI used to identify the resource ๐Ÿ”. if the media type stays unknown, the recipient SHOULD treat it as type "application/octet-stream" ๐ŸŒธ.

7.2.2. Entity Length ๐Ÿฆ‹

the entity-length of a message is the length of the message-body before any transfer-codings have been applied ๐Ÿซถ. section 4.4 explains how the transfer-length of a message-body is determined ๐Ÿ’œ.


8. Connections ๐ŸŒˆ

8.1. Persistent Connections โœจ

8.1.1. Purpose ๐Ÿงš

prior to persistent connections, a separate TCP connection was established to fetch each URL ๐Ÿ˜ญ, which increased the load on HTTP servers and caused congestion on the Internet ๐Ÿ’€. inline images and other associated data often mean a client has to make multiple requests to the same server in a short amount of time ๐Ÿ“. analysis of these performance problems and results from a prototype implementation are available [26] [30] ๐ŸŽ€. implementation experience and measurements of actual HTTP/1.1 (RFC 2068) implementations show good results [39] ๐Ÿ‘‘. alternatives have also been explored, for example, T/TCP [27] ๐ŸŒธ.

persistent HTTP connections have a number of advantages ๐Ÿ”ฅ:

  • by opening and closing fewer TCP connections, CPU time is saved in routers and hosts (clients, servers, proxies, gateways, tunnels, or caches), and memory used for TCP protocol control blocks can be saved in hosts ๐Ÿ’….
  • 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 much more efficiently, with much lower elapsed time ๐Ÿฆ‹.
  • network congestion goes down by reducing the number of packets caused by TCP opens, and by giving TCP enough time to figure out the congestion state of the network ๐ŸŒˆ.
  • latency on subsequent requests is reduced, since there's no time spent in TCP's connection opening handshake โญ.
  • 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, but if they're talking to an older server, they retry with old semantics after an error is reported ๐Ÿงฉ.

HTTP implementations SHOULD implement persistent connections ๐Ÿ’–.

8.1.2. Overall Operation ๐Ÿ’œ

a big difference between HTTP/1.1 and earlier versions of HTTP is that persistent connections are the default behavior of any HTTP connection ๐Ÿ‘‘. that means, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server ๐Ÿ™ˆ.

persistent connections give a client and a server a way to signal the close of a TCP connection ๐Ÿ“. this signaling happens using the Connection header field (section 14.10) ๐ŸŽ€. once a close has been signaled, the client MUST NOT send any more requests on that connection ๐Ÿ’….

8.1.2.1 Negotiation โœจ

okay so an HTTP/1.1 server MAY assume that an HTTP/1.1 client wants to keep the connection persistent ๐Ÿฆ‹, unless the request had a Connection header with the connection-token "close" in it ๐Ÿ™ˆ. 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 the connection to stay open ๐Ÿ‘€, but it decides whether to keep it open by checking if the server's response has a Connection header with the connection-token "close" in it. If the client doesn't want the connection to go on past 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.6.2 for more on backward compatibility with HTTP/1.0 clients ๐Ÿ“š.

to stay persistent, all messages on the connection MUST have a self-defined message length (one not defined by closure of the connection) ๐ŸŽ€, as described in section 4.4 ๐Ÿ’œ.

8.1.2.2 Pipelining ๐Ÿš€

a client that supports persistent connections MAY "pipeline" its requests, meaning it sends several 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 that first pipelined attempt fails ๐Ÿ˜ญ. If a client does retry, it MUST NOT pipeline before 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 matching responses ๐Ÿ’€.

clients SHOULD NOT pipeline requests using non-idempotent methods, or non-idempotent sequences of methods (see section 9.1.2) ๐Ÿ™…โ€โ™€๏ธ. Otherwise, a premature termination of the transport connection could lead to indeterminate results ๐Ÿ˜ต. A client wishing to send a non-idempotent request SHOULD wait to send that request until it has received the response status for the previous request โณ.

8.1.3 Proxy Servers ๐Ÿ‘‘

it is especially important that proxies correctly implement the properties of the Connection header field as specified in section 14.10 ๐Ÿ’….

the proxy server MUST signal persistent connections separately with its clients and with the origin servers (or other proxy servers) that it connects to ๐Ÿงš. Each persistent connection applies to only one transport link ๐Ÿ”—.

a proxy server MUST NOT establish an HTTP/1.1 persistent connection with an HTTP/1.0 client (but see RFC 2068 [33] for information and discussion of the problems with the Keep-Alive header implemented by many HTTP/1.0 clients) ๐Ÿ’€.

8.1.4 Practical Considerations โฐ

servers will usually have some time-out value beyond which they stop maintaining an inactive connection ๐Ÿ•ฐ๏ธ. Proxy servers might make this a higher value, since the client is likely to be making more connections through the same server ๐ŸŒธ. Using persistent connections places no requirements on the length (or existence) of this time-out, for either the client or the server โœจ.

when a client or server wishes to time out, it SHOULD issue a graceful close on the transport connection ๐Ÿซถ. Clients and servers SHOULD both constantly watch for the other side of the transport close, and respond to it as appropriate ๐Ÿ‘€. If a client or server does not detect 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 might have started to send a new request at the same time that the server has decided to close the "idle" connection. From the server's point of view, the connection is being closed while it was idle, but from the client's point of view, a request is in progress ๐Ÿ˜ณ.

this means clients, servers, and proxies MUST be able to recover from asynchronous close events ๐Ÿ’ช. Client software SHOULD reopen the transport connection and retransmit the aborted sequence of requests without user interaction, so long as the request sequence is idempotent (see section 9.1.2) ๐Ÿ”. Non-idempotent methods or sequences MUST NOT be automatically retried, although user agents MAY offer a human operator the choice of retrying the request(s) ๐Ÿ™‹โ€โ™€๏ธ. Confirmation by user-agent software with semantic understanding of the application MAY substitute for user confirmation ๐Ÿค–. The automatic retry SHOULD NOT be repeated if the second sequence of requests 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 the number of simultaneous connections that they maintain to a given server ๐ŸŽ€. A single-user client SHOULD NOT maintain more than 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 are intended to improve HTTP response times and avoid congestion ๐ŸŒธ.

8.2 Message Transmission Requirements ๐Ÿ’…

8.2.1 Persistent Connections and Flow Control ๐ŸŒŠ

HTTP/1.1 servers SHOULD maintain persistent connections and use TCP's flow control mechanisms to resolve temporary overloads, rather than terminating connections with the expectation that clients will retry ๐Ÿ™Œ. The latter technique can make network congestion even worse ๐Ÿ’€.

8.2.2 Monitoring Connections for Error Status Messages ๐Ÿ‘€

an HTTP/1.1 (or later) client sending a message-body SHOULD monitor the network connection for an error status while it is transmitting the request ๐Ÿ•ต๏ธโ€โ™€๏ธ. If the client sees an error status, it SHOULD immediately cease transmitting the body ๐Ÿ›‘. If the body is being sent using a "chunked" encoding (section 3.6), a zero length chunk and empty trailer 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 ๐Ÿ”’.

8.2.3 Use of the 100 (Continue) Status ๐ŸŽ€

the whole purpose of the 100 (Continue) status (see section 10.1.1) is to let a client that's sending a request message with a request body figure out whether the origin server is willing to accept the request (based on the request headers) before the client sends the request body ๐Ÿซง. In some cases, it might be either inappropriate or highly inefficient for the client to send the body if the server will reject the message without looking at the body ๐Ÿ™ˆ.

Requirements for HTTP/1.1 clients:

  • If a client will wait for a 100 (Continue) response before sending the request body, it MUST send an Expect request-header field (section 14.20) with the "100-continue" expectation ๐Ÿ’–.
  • A client MUST NOT send an Expect request-header field (section 14.20) with the "100-continue" expectation if it does not intend to send a request body ๐Ÿ™…โ€โ™€๏ธ.

because of older implementations, the protocol allows ambiguous situations in which a client may send Expect: 100-continue without receiving either a 417 (Expectation Failed) status or a 100 (Continue) status ๐Ÿคทโ€โ™€๏ธ. Therefore, when a client sends this header field to an origin server (possibly via a proxy) from which it has never seen a 100 (Continue) status, the client SHOULD NOT wait for an indefinite period before sending the request body โณ.

Requirements for HTTP/1.1 origin servers:

  • Upon receiving a request which includes an Expect request-header field with the "100-continue" expectation, an origin server MUST either respond with 100 (Continue) status and continue to read from the input stream, or respond with a final status code. The origin server MUST NOT wait for the request body before sending the 100 (Continue) response. If it responds with a final status code, it MAY close the transport connection or it MAY continue to read and discard the rest of the request. It MUST NOT perform the requested method if it returns a final status code ๐Ÿ›‘.
  • An origin server SHOULD NOT send a 100 (Continue) response if the request message does not include an Expect request-header field with the "100-continue" expectation, and MUST NOT send a 100 (Continue) response if such a request comes from an HTTP/1.0 (or earlier) client. There is an exception to this rule: for compatibility with RFC 2068, a server MAY send a 100 (Continue) status in response to an HTTP/1.1 PUT or POST request that does not include an Expect request-header field with the "100-continue" expectation. This exception, the purpose of which is to minimize any client processing delays associated with an undeclared wait for 100 (Continue) status, applies only to HTTP/1.1 requests, and not to requests with any other HTTP-version value ๐Ÿง.
  • An origin server MAY omit a 100 (Continue) response if it has already received some or all of the request body for the corresponding request ๐Ÿ™ƒ.
  • An origin server that sends a 100 (Continue) response MUST ultimately send a final status code, once the request body is received and processed, unless it terminates the transport connection prematurely ๐Ÿ.
  • If an origin server receives a request that does not include an Expect request-header field with the "100-continue" expectation, the request includes a request body, and the server responds with a final status code before reading the entire request body from the transport connection, then the server SHOULD NOT close the transport connection until it has read the entire request, or until the client closes the connection. Otherwise, the client might not reliably receive the response message. However, this requirement is not be construed as preventing a server from defending itself against denial-of-service attacks, or from badly broken client implementations ๐Ÿ›ก๏ธ.

Requirements for HTTP/1.1 proxies:

  • If a proxy receives a request that includes an Expect request-header field with the "100-continue" expectation, and the proxy either knows that the next-hop server complies with HTTP/1.1 or higher, or does not know the HTTP version of the next-hop server, it MUST forward the request, including the Expect header field ๐Ÿšš.
  • If the proxy knows that the version of the next-hop server is HTTP/1.0 or lower, it MUST NOT forward the request, and it MUST respond with a 417 (Expectation Failed) status ๐Ÿ™…โ€โ™€๏ธ.
  • Proxies SHOULD maintain a cache recording the HTTP version numbers received from recently-referenced next-hop servers ๐Ÿ—‚๏ธ.
  • A proxy MUST NOT forward a 100 (Continue) response if the request message was received from an HTTP/1.0 (or earlier) client and did not include an Expect request-header field with the "100-continue" expectation. This requirement overrides the general rule for forwarding of 1xx responses (see section 10.1) ๐Ÿ‘‘.

8.2.4. Client Behavior if Server Prematurely Closes Connection ๐Ÿ’”๐Ÿ”

okay bestie, picture this: an HTTP/1.1 client sends a request with a body ๐Ÿ“ฆ, but it doesn't include an Expect header with the "100-continue" expectation ๐Ÿ™ˆ. The client also isn't directly connected to an HTTP/1.1 origin server. Then the connection gets slammed shut before the client hears a single status from the server ๐Ÿ˜ญ. In that situation the client SHOULD retry the request. ๐Ÿ”

If the client does retry, it MAY use this "binary exponential backoff" algorithm to make sure it gets a reliable response โœจ:

  1. Open a new connection to the server ๐Ÿ”Œ
  2. Send the request-headers
  3. Set a variable R to the estimated round-trip time to the server (e.g., based on how long it took to establish the connection), or to a constant value of 5 seconds if the round-trip time isn't available โฑ๏ธ
  4. Compute T = R * (2**N), where N is the number of previous retries of this request ๐Ÿงฎ
  5. Wait for either an error response from the server or for T seconds, whichever comes first ๐Ÿ‘€
  6. If no error response arrives, send the body of the request once T seconds have passed ๐Ÿ“ค
  7. If the client sees the connection closed prematurely again, repeat from step 1 until the request is accepted, an error response is received, or the user gets impatient and ends the retry process ๐Ÿ˜ค
If at any point an error status is received, the client: - SHOULD NOT continue, and - SHOULD close the connection if it has not completed sending the request message.

9. Method Definitions ๐ŸŽ€

Here's the squad of common methods for HTTP/1.1 ๐Ÿ’œ. The set can be expanded, but you can't assume that additional methods share the same semantics across 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 ๐Ÿ›ก๏ธ

Implementors need to remember that the software is representing the user when they interact over the Internet ๐Ÿงโ€โ™€๏ธ. So be careful to let the user know about any action that might have an unexpected significance to them or to others ๐Ÿ‘€.

The convention is that GET and HEAD SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe" ๐Ÿซง. That way user agents can show other methods, like POST, PUT and DELETE, in a special way, so the user knows a possibly unsafe action is being requested ๐Ÿšฉ.

Obviously, nobody can guarantee the server won't generate side-effects while handling a GET request. Some dynamic resources actually consider that a feature โœจ. The important distinction is that the user didn't ask for those side-effects, so the user can't be held accountable for them ๐Ÿ™Œ.

9.1.2. Idempotent Methods ๐Ÿ”

Methods can also be "idempotent" ๐Ÿ’…. Aside from error or expiration issues, the side-effects of N > 0 identical requests are the same as for a single request. GET, HEAD, PUT and DELETE all share this property. The methods OPTIONS and TRACE SHOULD NOT have side effects, so they're inherently idempotent ๐ŸŒธ.

Here's the twist ๐ŸŒ€: a sequence of several requests can still be non-idempotent, even if every method in that sequence is idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that isn't changed by re-executing all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that gets modified later in the same sequence ๐Ÿ˜ญ.

A sequence that never has side effects is idempotent by definition, provided that no concurrent operations are running on the same set of resources ๐Ÿงš.

9.2. OPTIONS ๐Ÿ”

The OPTIONS method is a request for information about the communication options available on the request/response chain identified by the Request-URI. It lets the client figure out the options and/or requirements for a resource, or a server's capabilities, without implying a resource action or starting a resource retrieval ๐Ÿ•ต๏ธโ€โ™€๏ธ.

Responses to this method are not cacheable. ๐Ÿšซ

If the OPTIONS request includes an entity-body (shown by the presence of Content-Length or Transfer-Encoding), the media type MUST be indicated by a Content-Type field ๐Ÿ“ฆ. This specification doesn't define any use for such a body, but future extensions to HTTP might use it to make more detailed queries on the server ๐Ÿ”ฎ. A server that doesn't support such an extension MAY discard the request body ๐Ÿ—‘๏ธ.

If the Request-URI is an asterisk (""), the OPTIONS request is meant for the server in general, not one specific resource ๐ŸŒ. Since a server's communication options usually depend on the resource, the "" request is only useful as a "ping" or "no-op" type of method ๐Ÿ“. It does nothing beyond letting the client test the server's capabilities. For example, it can test a proxy for HTTP/1.1 compliance (or lack thereof) ๐Ÿงช.

If the Request-URI is not an asterisk, the OPTIONS request applies only to the options available when communicating with that resource ๐ŸŽฏ.

A 200 response SHOULD include any header fields that indicate optional features the server implements and that apply to that resource (e.g., Allow), possibly including extensions this specification doesn't define ๐ŸŽ. The response body, if there is one, SHOULD also include information about the communication options ๐Ÿ“. This specification doesn't define the format for such a body, but future extensions to HTTP might ๐ŸŒˆ. Content negotiation MAY be used to pick the right response format ๐Ÿ’–. If no response body is included, the response MUST include a Content-Length field with a field-value of "0" 0๏ธโƒฃ.

The Max-Forwards request-header field MAY be used to target a specific proxy in the request chain ๐ŸŽฏ. When a proxy receives an OPTIONS request on an absoluteURI for which request forwarding is permitted, the proxy MUST check for a Max-Forwards field ๐Ÿ”Ž. If the Max-Forwards field-value is zero ("0"), the proxy MUST NOT forward the message. Instead, the proxy SHOULD respond with its own communication options ๐Ÿ™‹โ€โ™€๏ธ. If the Max-Forwards field-value is an integer greater than zero, the proxy MUST decrement the field-value when it forwards the request โž–. If no Max-Forwards field is present in the request, then the forwarded request MUST NOT include a Max-Forwards field ๐Ÿšซ.

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, the produced data is what gets returned as the entity in the response, not the source text of the process ๐Ÿญ, unless that text happens to be the output of the process ๐Ÿคทโ€โ™€๏ธ.

GET changes into 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 asks for the entity to be transferred only under the circumstances described by the conditional header field(s) ๐Ÿง. The point is to cut down on unnecessary network usage by letting cached entities get refreshed without multiple requests or re-transferring data the client already has ๐Ÿ’พ.

GET also changes into a "partial GET" if the request message includes a Range header field โœ‚๏ธ. A partial GET asks that only part of the entity be transferred, as described in section 14.35 ๐Ÿงฉ. Again, the goal is to reduce unnecessary network usage by letting partially-retrieved entities be completed without transferring data the client already holds ๐Ÿซถ.

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

See section 15.1.3 for security considerations when this is used for forms ๐Ÿ”.

9.4. HEAD ๐Ÿง 

HEAD is identical to GET, except that the server MUST NOT return a message-body in the response ๐Ÿ™…โ€โ™€๏ธ. The metainformation in the HTTP headers of a HEAD response SHOULD be identical to the information sent for a GET request ๐Ÿ‘ฏ. This method is great for getting metainformation about the entity implied by the request without transferring the entity-body itself ๐Ÿ“Š. It's often used for testing hypertext links for validity, accessibility, and recent modification ๐Ÿ”—.

The response to a HEAD request MAY be cacheable, in the sense that its information MAY be used to update a previously cached entity from that resource ๐Ÿ”„. If the new field values show that the cached entity differs from the current entity (as a change in Content-Length, Content-MD5, ETag or Last-Modified would indicate), then the cache MUST treat the cache entry as stale ๐Ÿฅ€.

9.5. POST ๐Ÿ“ฎ

POST is used to ask the origin server to accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line โœ‰๏ธ. It's designed to be a uniform method covering these functions:

  • Annotating existing resources ๐Ÿ“Œ;
  • Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles ๐Ÿ“ฐ;
  • Providing a block of data, such as the result of submitting a form, to a data-handling process ๐Ÿ“‹;
  • Extending a database through an append operation ๐Ÿ—„๏ธ.

The server decides what POST actually does, and that usually depends on the Request-URI ๐Ÿงญ. The posted entity is subordinate to that URI the same way a file is subordinate to the directory containing it, a news article is subordinate to the newsgroup it's posted to, or a record is subordinate to a database ๐Ÿ—‚๏ธ.

POST might not result in a resource that can be identified by a URI. In that case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity describing 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) ๐Ÿ“.

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields ๐Ÿ™…. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource ๐Ÿ‘‰.

POST requests MUST obey the message transmission requirements set out in section 8.2 ๐Ÿซก.

See section 15.1.3 for security considerations ๐Ÿ”.

9.6. PUT โœจ

okay so PUT is the method that says "hey, please store this enclosed entity under the Request-URI I'm giving you" ๐Ÿ’– If the Request-URI already points at a resource, the enclosed entity SHOULD be considered as a modified version of the one living on the origin server ๐Ÿฆ‹ If nothing lives there yet and the user agent is able to define that URI as a brand-new resource, the origin server can create it ๐ŸŒธ If a new resource really does get created, the origin server MUST inform the user agent with a 201 (Created) response ๐ŸŽ€ If an existing resource gets modified instead, a 200 (OK) or 204 (No Content) response code SHOULD be sent to show the request went through โœจ And if the resource couldn't be created or modified at that Request-URI, an appropriate error response SHOULD be given that reflects what went wrong ๐Ÿ˜ญ The recipient of the entity MUST NOT ignore any Content-* headers (like Content-Range) that it doesn't understand or implement, and it MUST return a 501 (Not Implemented) response in those cases ๐Ÿ’…

If the request goes through a cache and the Request-URI identifies one or more entries that are currently cached, those entries SHOULD be treated as stale ๐Ÿงš Responses to this method are not cacheable, so don't even try ๐Ÿ™ˆ

Now the big POST vs PUT difference, bestie ๐Ÿ‘‘ It's all about what the Request-URI means. In a POST, the URI identifies the resource that will handle the enclosed entity, and that could 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 that's enclosed with the request. The user agent already knows which URI it means, so the server MUST NOT attempt 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, and then the user agent MAY make its own decision about whether or not to redirect the request ๐Ÿ”ฅ

A single resource MAY be identified by many different URIs, and that's so iconic ๐ŸŒˆ For example, an article might have one URI for "the current version" that's separate from the URI for each particular version. In that setup, a PUT on a general URI might result in several other URIs being defined by the origin server ๐Ÿฆ‹

HTTP/1.1 does not 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 ๐Ÿ’–

Unless a particular entity-header says otherwise, the entity-headers in the PUT request SHOULD be applied to the resource created or modified by the PUT โœจ


9.7. DELETE ๐Ÿ—‘๏ธ

okay the DELETE method 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, so it's not always the final word ๐Ÿซถ The client can't be guaranteed that the operation was actually carried out, even if the status code returned by the origin server says it was completed successfully ๐Ÿ˜ญ That's why the server SHOULD NOT indicate success unless, at the time it gives the response, it intends to delete the resource or move it to an inaccessible location ๐Ÿ™…โ€โ™€๏ธ

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action hasn't been enacted yet, or 204 (No Content) if the action has been enacted but the response doesn't include an 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 cacheable ๐Ÿ™ˆ


9.8. TRACE ๐Ÿ”

The TRACE method is used to invoke a remote, application-layer loop-back of the request message ๐Ÿชž The final recipient of the request 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 being received at the other end of the request chain, and then use that data for testing or diagnostics ๐Ÿง The value of the Via header field (section 14.45) is of particular interest, since it acts as a trace of the request chain ๐Ÿฆ‹ Using the Max-Forwards header field lets the client limit how long the request chain gets, which is super useful for testing a chain of proxies that's forwarding messages in an infinite loop ๐Ÿ”๐Ÿ˜ญ

If the request is valid, 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 ๐Ÿ™ˆ


9.9. CONNECT ๐Ÿ”Œ

This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a tunnel (e.g. SSL tunneling [44]) ๐Ÿš‡ That's a whole main character moment for the proxy ๐Ÿ‘‘


10. Status Code Definitions โœจ

Each Status-Code is described below, including a description of which method(s) it can follow and any metainformation required in the response ๐Ÿ“‹ So for every code, you get the full tea ๐Ÿซ–

10.1. Informational 1xx ๐Ÿ’ฌ

This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and it's terminated by an empty line ๐ŸŒธ There are no required headers for this class of status code ๐Ÿ™Œ 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 ๐Ÿงช Not allowed, bestie ๐Ÿ™…โ€โ™€๏ธ

A client MUST be prepared to accept one or more 1xx status responses before a regular response, even if the client doesn't expect a 100 (Continue) status message ๐Ÿซถ Unexpected 1xx status responses MAY be ignored by a user agent ๐Ÿ’…

Proxies MUST forward 1xx responses, unless the connection between the proxy and its client has been closed, or unless the proxy itself requested the generation of the 1xx response ๐Ÿ” (For example, if a proxy adds an Expect: 100-continue field when it forwards a request, then it doesn't need to forward the corresponding 100 (Continue) response(s) ๐Ÿง )

10.1.1. 100 Continue ๐ŸŸข

The client SHOULD 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 remainder of the request or, if the request has already been completed, ignore this response ๐Ÿ’… The server MUST send a final response after the request has been completed ๐ŸŽ€ See section 8.2.3 for the detailed discussion of how this status code gets used and handled ๐Ÿ“–

10.1.2. 101 Switching Protocols ๐Ÿ”€

The server understands and is willing to comply with the client's request, via the Upgrade message header field (section 14.42), for a change in the application protocol being used on this connection ๐Ÿค The server will switch protocols to the ones defined by the response's Upgrade header field immediately after the empty line that terminates the 101 response ๐Ÿฆ‹

The protocol SHOULD be switched only when it's advantageous to do so ๐Ÿง  For example, switching to a newer version of HTTP is advantageous over older versions, and switching to a real-time, synchronous protocol might be advantageous when delivering resources that use such features โšก

10.2. Successful 2xx ๐ŸŽ‰

This class of status code indicates that the client's request was successfully received, understood, and accepted ๐Ÿฅณ We love a request that gets the green light ๐Ÿ’š

10.2.1. 200 OK โœ…

The request has succeeded ๐ŸŒŸ The information returned with the response 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 resulted in a new resource being created ๐ŸŒฑ The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field ๐Ÿ“ The response SHOULD include an entity containing a list of resource characteristics and location(s) so the user or user agent can choose the one that's most appropriate ๐Ÿ’– The entity format is specified by the media type given in the Content-Type header field ๐Ÿ“„ The origin server MUST create the resource before returning the 201 status code ๐ŸŽ€ If the action can't be carried out immediately, the server SHOULD respond with a 202 (Accepted) response instead โณ

A 201 response MAY contain an ETag response header field indicating the current value of the entity tag for the requested variant that was just created, see section 14.19 ๐Ÿท๏ธ

10.2.3. 202 Accepted ๐Ÿ“ฌ

The request has been accepted for processing, but the processing hasn't been completed yet ๐Ÿ•ฐ๏ธ The request might or might not eventually be acted upon, since it might be disallowed when processing actually takes place ๐Ÿคž There's no facility for re-sending 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 (perhaps a batch-oriented process that only runs once per day) without requiring the user agent's connection to the server to stick around until the process is completed ๐ŸŒ™ The entity returned with this response SHOULD include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled ๐Ÿ“Š

10.2.4. 203 Non-Authoritative Information ๐Ÿชช

The returned metainformation in the entity-header is not the definitive set available from the origin server, but was gathered from a local or third-party copy ๐Ÿ” The set presented MAY be a subset or a superset of the original version ๐Ÿงฉ For example, including local annotation information about the resource might 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 be 200 (OK) ๐Ÿ’…

10.2.5. 204 No Content ๐Ÿซ™

The server has fulfilled the request but doesn't need to return an entity-body, and might want to return updated metainformation ๐Ÿง The response MAY include new or updated metainformation in the form of entity-headers, and if they're present, they SHOULD be associated with the requested variant ๐ŸŽ€

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 ๐Ÿช„ Any new or updated metainformation SHOULD still be applied to the document currently in the user agent's active view โœจ

The 204 response MUST NOT include a message-body, so it's always terminated by the first empty line after the header fields ๐Ÿ”š

10.2.6. 205 Reset Content ๐Ÿงผ

The server has fulfilled the request, and the user agent SHOULD reset the document view that caused the request to be sent ๐Ÿ’ซ This response is mainly meant to let input for actions take place via user input, followed by clearing the form the input was given in, so the user can easily start another input action ๐Ÿ“ The response MUST NOT include an entity ๐Ÿ™…โ€โ™€๏ธ

10.2.7 206 Partial Content โœจ

okay bestie, 206 is the server being like "I got you, here's just the slice you asked for" ๐ŸŽ€๐Ÿ’–. The server has fulfilled the partial GET request for the resource. The request MUST have included a Range header field (section 14.35) indicating the desired range, and MAY have included an If-Range header field (section 14.27) to make the request conditional.

The response MUST include the following header fields:

  • Either a Content-Range header field (section 14.16) indicating the range included with this response, or a multipart/byteranges Content-Type including Content-Range fields for each part. If a Content-Length header field is present in the response, its value MUST match the actual number of OCTETs transmitted in the message-body. ๐Ÿ“
  • 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 206 response is the result of an If-Range request that used a strong cache validator (see section 13.3.3), the response SHOULD NOT include other entity-headers. If the response is the result of an If-Range request that used a weak validator, the response MUST NOT include other entity-headers, because this keeps cached entity-bodies and updated headers from getting into a mess with each other ๐Ÿ™…โ€โ™€๏ธ. Otherwise, the response MUST include all of the entity-headers that would have been returned with a 200 (OK) response to the same request. ๐Ÿ’…

A cache MUST NOT combine a 206 response with other previously cached content if the ETag or Last-Modified headers do not match exactly, see 13.5.4. ๐Ÿšซ

A cache that does not support the Range and Content-Range headers MUST NOT cache 206 (Partial) responses. ๐Ÿ™ˆ


10.3 Redirection 3xx ๐Ÿงญ

this class of status code means the user agent still has some work to do before the request is fulfilled ๐Ÿƒโ€โ™€๏ธ. 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 client SHOULD detect infinite redirection loops, since such loops generate network traffic for each redirection. ๐Ÿ”

Note: previous versions of this specification recommended a maximum of five redirections. Content developers should be aware that there might be clients that implement such a fixed limitation.

10.3.1 300 Multiple Choices ๐ŸŽ€

the requested resource corresponds to any one of a set of representations. Each one has its own specific location, and agent-driven negotiation information (section 12) is being provided so that the user (or user agent) can pick a preferred representation and redirect its request to that location ๐Ÿ›๏ธ.

Unless it was a HEAD request, the response SHOULD include an entity containing a list of resource characteristics and location(s) the user or user agent can choose from, the one most appropriate being the goal. The entity format is specified by the media type given in the Content-Type header field. Depending upon the format and the capabilities of the user agent, selection of the most appropriate choice MAY be performed automatically. However, this specification does not define any standard for such automatic selection. ๐Ÿค–

If the server has a preferred choice of representation, it SHOULD include the specific URI for that representation in the Location field; user agents MAY use the Location field value for automatic redirection. This response is cacheable unless indicated otherwise. ๐Ÿ’œ

10.3.2 301 Moved Permanently ๐Ÿก

The requested resource has been assigned a new permanent URI, and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise. โœ๏ธ

The new permanent URI 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 the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this 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 Found ๐Ÿ”

The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field. โณ

The temporary URI 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 the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued. ๐Ÿ™…โ€โ™€๏ธ

Note: RFC 1945 and RFC 2068 specify that the client is not allowed to change the method on the redirected request. However, most existing user agent implementations treat 302 as if it were a 303 response, performing a GET on the Location field-value regardless of the original request method. The status codes 303 and 307 have been added for servers that wish to make unambiguously clear which kind of reaction is expected of the client. ๐Ÿซ 

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 method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable. ๐ŸŒˆ

The different URI 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). ๐Ÿ“Ž

Note: many pre-HTTP/1.1 user agents do not understand the 303 status. When interoperability with such clients is a concern, the 302 status code may be used instead, since most user agents react to a 302 response as described here for 303. ๐Ÿงธ

10.3.5 304 Not Modified ๐Ÿ’ค

If the client has performed a conditional GET request and access is allowed, but the document has not been modified, the server SHOULD respond with this status code. The 304 response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields. ๐Ÿซ™

The response MUST include the following header fields:

  • Date, unless its omission is required by section 14.18.1 ๐Ÿ—“๏ธ

If a clockless origin server obeys these rules, and proxies and clients add their own Date to any response received without one (as already specified by [RFC 2068], section 14.19), caches will operate correctly. โฐ

  • 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 (i.e., the conditional GET used a weak validator), the response MUST NOT include other entity-headers, because this keeps cached entity-bodies and updated headers from getting into a mess with each other ๐Ÿ™…โ€โ™€๏ธ.

If a 304 response indicates an entity not currently cached, then 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. โœจ

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 URI of the proxy. The recipient is expected to repeat this single request via the proxy. 305 responses MUST only be generated by origin servers. ๐Ÿ›ก๏ธ

Note: RFC 2068 was not clear that 305 was intended to redirect a single request, and to be generated by origin servers only. Not observing these limitations has significant security consequences. ๐Ÿšจ๐Ÿ’€

10.3.7 306 (Unused) ๐Ÿซฅ

The 306 status code was used in a previous version of the specification, is no longer used, and the code is reserved. ๐Ÿ•ฐ๏ธ

10.3.8 307 Temporary Redirect ๐Ÿฆ‹

The requested resource resides temporarily under a different URI. Since the redirection MAY be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field. ๐ŸŒท

The temporary URI 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), since many pre-HTTP/1.1 user agents do not understand the 307 status. Therefore, the note SHOULD contain the information necessary for a user to repeat the original request on the new URI. ๐Ÿ—บ๏ธ

If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued. ๐Ÿ›‘


10.4 Client Error 4xx ๐Ÿ™‹โ€โ™€๏ธ

the 4xx class of status code is for when the client seems to have messed up somewhere ๐Ÿ˜…. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included entity to the user. ๐Ÿ“ฃ

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 request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. ๐Ÿง

10.4.2 401 Unauthorized ๐Ÿ”

okay so 401 is the server going "hold up, who are you?" ๐Ÿ™ˆ The request needs user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) with 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 had Authorization credentials, then the 401 is basically saying those credentials got refused ๐Ÿ’€. If the 401 has the same challenge as the previous response, and the user agent already tried authenticating at least once, then the user SHOULD be shown the entity from the response, since it might have useful diagnostic info โœจ. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43] ๐ŸŽ€.

10.4.3 402 Payment Required ๐Ÿ’ธ

this one is reserved for future use ๐Ÿซ  so nothing to see here yet, bestie.

10.4.4 403 Forbidden ๐Ÿšซ

the server understood the request, but it's refusing to fulfill it ๐Ÿ™…โ€โ™€๏ธ. Authorization will not help, so 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. If the server doesn't want to share that info with the client, the status code 404 (Not Found) can be used instead ๐Ÿ™ˆ๐Ÿ’….

10.4.5 404 Not Found ๐Ÿงญ

the server hasn't found anything matching the Request-URI ๐Ÿ‘€. There's no indication of whether the condition is temporary or permanent. 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 ๐Ÿชฆ. This code is commonly used when the server doesn't want to reveal exactly why the request was refused, or when no other response is applicable ๐Ÿคทโ€โ™€๏ธ.

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 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 with a list of available entity characteristics and location(s) the user or user agent can pick the most appropriate one from ๐Ÿ“. 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, picking the best choice 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 might even be preferable to sending a 406 response. User agents are encouraged to inspect the headers of an incoming response to decide if it's acceptable ๐Ÿ’–.

If the response could be unacceptable, a user agent SHOULD temporarily stop receiving more data and ask the user what to do next ๐Ÿ›‘.

10.4.8 407 Proxy Authentication Required ๐Ÿงฑ

this is basically the 401 cousin, but it means the client has to authenticate itself with the proxy first ๐Ÿ•ต๏ธโ€โ™€๏ธ. The proxy MUST return a Proxy-Authenticate header field (section 14.33) with a challenge that applies to the proxy for the requested resource. The client MAY repeat the request with a suitable Proxy-Authorization header field (section 14.34). HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43] ๐ŸŽ€.

10.4.9 408 Request Timeout โฐ

the client didn't send a request in the time the server was ready to wait ๐Ÿ˜ญ. 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 current state of the resource ๐Ÿ˜ฌ. This code is only allowed when the user will probably be able to resolve 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 entity would have enough info for the user or user agent to fix the problem, but that might not be possible and is not required ๐ŸŒธ.

Conflicts happen most often in response to a PUT request ๐Ÿ’…. For example, if versioning were being used and the entity being PUT had changes that conflict with changes made by an earlier (third-party) request, the server might use the 409 response to say it can't complete the request. In that case, the response entity would probably 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 requested resource isn't available on the server anymore, and no forwarding address is known ๐Ÿ˜ข. This condition is expected to 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, the status code 404 (Not Found) SHOULD be used instead ๐Ÿ™ƒ. This response is cacheable unless indicated otherwise ๐Ÿ’พ.

The 410 response is mostly meant to help with web maintenance ๐Ÿ› ๏ธ. It tells the recipient the resource is intentionally unavailable and that the server owners want remote links to it removed. This is common for limited-time promo stuff, and for resources belonging to people who no longer work at the server's site ๐Ÿฅ€. You don't have to mark every permanently gone resource as "gone", and you don't have to keep the mark for any particular length of time. 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 ๐Ÿšง

a precondition in one or more of the request-header fields evaluated to false when the server tested it ๐Ÿ™ƒ. This response code lets the client set preconditions on the current resource metainformation (header field data), so the requested method can't be applied to 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 process ๐Ÿ˜. The server MAY close the connection to stop the client from continuing the request ๐Ÿ”Œ.

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 MAY 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's only likely when a client has improperly turned a POST request into a GET request with long query info ๐Ÿ“ฎ, when the client has fallen into a URI "black hole" of redirection (for example, a redirected URI prefix that points to a suffix of itself) ๐Ÿ•ณ๏ธ, or when a client is attacking the server by trying to exploit security holes in servers that use fixed-length buffers for reading or manipulating the Request-URI ๐Ÿšจ๐Ÿ˜ญ.

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

the server won't service the request because the entity of the request is in a format the requested resource doesn't support for that method ๐Ÿ™…โ€โ™€๏ธ.

10.4.17 416 Requested Range Not Satisfiable ๐Ÿ“

A server SHOULD return a response with this status code if a request included a Range request-header field (section 14.35), none of the range-specifier values in that field overlap the current extent of the selected resource, and the request did not include an If-Range request-header field. (For byte-ranges, this means that the first-byte-pos of all of the byte-range-spec values were greater than the current length of the selected resource.) ๐Ÿงฎ๐Ÿ’€

When this status code is returned for a byte-range request, the response SHOULD include a Content-Range entity-header field saying the current length of the selected resource (see section 14.16) ๐Ÿ“โœจ. This response MUST NOT use the multipart/byteranges content-type ๐Ÿšซ๐ŸŽ€.

10.4.18 417 Expectation Failed ๐Ÿ™…โ€โ™€๏ธ

the expectation given in an Expect request-header field (see section 14.20) couldn't be met by this server. Or, if the server is a proxy, it has unambiguous evidence that the request couldn't be met by the next-hop server ๐Ÿงƒ.


10.5 Server Error 5xx ๐Ÿ”ฅ

status codes starting with the digit "5" mean the server knows it messed up, or it can't do the request ๐Ÿ˜ญ๐Ÿงฏ. 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 needed to fulfill the request ๐Ÿ™ˆ. 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 ๐ŸŒ‰

the server, while acting as a gateway or proxy, got an invalid response from the upstream server it reached out to 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 ๐Ÿงนโœจ. The implication is that this is temporary and will get better after some delay. If it's known, the length of the delay 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 might just prefer to refuse the connection ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–.

10.5.5 504 Gateway Timeout โŒ›

the server, while acting as a gateway or proxy, didn't get a timely response from the upstream server specified by the URI (for example, HTTP, FTP, LDAP) or from some other auxiliary server (for example, DNS) it needed to reach in order to complete the request ๐ŸŒ๐Ÿ˜ฉ.

Note: Note to implementors: some deployed proxies are known to return 400 or 500 when DNS lookups time out. ๐Ÿซถ๐Ÿงš

10.5.6 505 HTTP Version Not Supported ๐Ÿ’€

okay so the server is looking at the HTTP version the client sent and going "nah, not today" ๐Ÿ™…โ€โ™€๏ธ it either doesn't support that version or refuses to. it's basically saying it can't or won't finish the request using the same major version as the client (see section 3.1), so this error message is all you get ๐Ÿ˜ญ. the response SHOULD contain an entity explaining why that version isn't supported and which other protocols that server does speak ๐Ÿซถ


11 Access Authentication โœจ

okay bestie, HTTP has a few OPTIONAL challenge-response auth mechanisms ๐Ÿ”. the server can challenge a client request, and the client can answer with its auth info. the whole general framework, plus the "basic" and "digest" schemes, lives in "HTTP Authentication: Basic and Digest Access Authentication" [43] ๐Ÿ“–. this spec just borrows the definitions of "challenge" and "credentials" from that doc, no need to reinvent the wheel ๐Ÿ›ž๐Ÿ’…


12 Content Negotiation ๐ŸŒˆ

so most HTTP responses carry an entity meant for a human to read ๐Ÿง‘โ€๐Ÿ’ป. naturally you want to hand them the "best available" version, but here's the drama: not everyone agrees on what "best" means, and not every user agent can render every entity type ๐Ÿ’€. that's why HTTP has a bunch of "content negotiation" mechanisms, which is basically the process of picking the best representation for a response when there are several options ๐ŸŽ€

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 with an entity-body MAY be subject to negotiation, and yes, that includes error responses ๐Ÿ˜ญ

there are two flavours of negotiation: server-driven and agent-driven ๐Ÿ“. they're orthogonal, which means you can use them separately or stack them together ๐Ÿงš. one combo is called transparent negotiation, and it happens when a cache takes the agent-driven info the origin server gave it and uses that to do server-driven negotiation for later requests ๐Ÿ‘‘

12.1 Server-driven Negotiation

if the server's own algorithm picks the best representation for a response, that's server-driven negotiation ๐Ÿ–ฅ๏ธ. the pick is based on the representations available (the dimensions they can vary over, like language, content-coding, etc.) and on the contents of certain request header fields, or on other stuff about the request, like the client's network address ๐ŸŒ

server-driven negotiation is great when the selection algorithm would be hard to explain to the user agent, or when the server wants to send its "best guess" with the very first response, hoping the client is happy with it and no extra round trip is needed โœจ. to help the server guess better, the user agent MAY include request header fields like Accept, Accept-Language, Accept-Encoding, and so on, describing what it prefers ๐ŸŽ€

but server-driven negotiation has some downsides, bestie ๐Ÿ˜ฌ:

  1. the server can never really know what's "best" for a given user, since that would need full info about the user agent's capabilities and what the response is for (like, does the user want to read it on screen or print it on paper? ๐Ÿ–จ๏ธ).
  2. making the user agent describe its capabilities in every request can be super inefficient (since only a small percentage of responses have multiple representations) and can also be a privacy concern ๐Ÿ™ˆ.
  3. it makes the origin server harder to build, along with the algorithms that generate responses ๐Ÿ› ๏ธ.
  4. it may limit a public cache's ability to reuse the same response for different users' requests ๐Ÿซ .

HTTP/1.1 has these request header fields for server-driven negotiation, which describe user agent capabilities and 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.43). but an origin server isn't stuck with those dimensions ๐Ÿ’…. it MAY vary the response based on any aspect of the request, including stuff outside the request-header fields or inside extension header fields not defined by this spec ๐Ÿฆ‹

the Vary header field is how you express which parameters the server used to pick a representation that's subject to server-driven negotiation ๐Ÿงฉ. see section 13.6 for how caches use Vary, and section 14.44 for how servers use it ๐Ÿ’œ

12.2 Agent-driven Negotiation

with agent-driven negotiation, the user agent does the picking ๐Ÿ™Œ. it gets an initial response from the origin server first, then chooses the best representation from a list of available ones. that list is included in the header fields or entity-body of the initial response, and each representation has its own URI ๐Ÿ”—. the user agent can choose automatically (if it's capable) or the user can pick manually from a generated (possibly hypertext) menu ๐Ÿฝ๏ธ

agent-driven negotiation shines when the response varies over common dimensions (like type, language, or encoding), when the origin server can't figure out the user agent's capabilities from the request, and generally when public caches are used to spread out server load and cut down network usage ๐ŸŒธ

the downside? it needs a second request to get the best alternate representation ๐Ÿ˜ฉ. that second request is only efficient when caching is in play โœจ. also, this spec doesn't define any mechanism for automatic selection, though it doesn't stop anyone from building one as an extension and using it within HTTP/1.1 ๐Ÿงš

HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable) status codes to enable agent-driven negotiation when the server can't or won't provide a varying response using server-driven negotiation ๐Ÿ’…

12.3 Transparent Negotiation

transparent negotiation is the combo of server-driven and agent-driven negotiation ๐Ÿซถ. when a cache gets some form of the list of available representations (like in agent-driven negotiation) and the cache fully understands the dimensions of variance, the cache can do server-driven negotiation on the origin server's behalf for later requests on that resource ๐Ÿง 

the perks: it spreads out the negotiation work that would otherwise land on the origin server, and it gets rid of the second-request delay of agent-driven negotiation when the cache guesses the right response right ๐ŸŽฏ

this spec doesn't define any mechanism for transparent negotiation, but it doesn't block anyone from building one as an extension that could be used within HTTP/1.1 ๐Ÿฆ‹


13 Caching in HTTP ๐Ÿ—„๏ธ

HTTP is usually used for distributed information systems, where performance can get a huge boost from response caches ๐Ÿš€. HTTP/1.1 has a bunch of elements designed to make caching work as well as possible ๐Ÿ’–. they're totally intertwined with the rest of the protocol and they interact with each other, so it helps to describe the basic caching design separately from the detailed bits about methods, headers, response codes, and so on ๐Ÿ“š

caching is pointless if it doesn't actually improve performance, obviously ๐Ÿ™„. 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 round trips for many operations, and that's handled by an "expiration" mechanism (see section 13.2) โฐ. the second one saves bandwidth, and that's handled by a "validation" mechanism (see section 13.3) ๐Ÿซง

now here's the tea โ˜•: performance, availability, and disconnected operation requirements mean we have to be able to relax the goal of semantic transparency ๐Ÿ˜ค. HTTP/1.1 lets origin servers, caches, and clients explicitly reduce transparency when needed. but non-transparent operation can confuse non-expert users, and it might not work with certain server applications (like ones for ordering merchandise ๐Ÿ›’). so the protocol says transparency can only 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 you these important elements ๐Ÿ’…:

  1. protocol features that give full semantic transparency when everyone needs 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 keep the requested level of semantic transparency โš ๏ธ.

a basic principle here is that clients have to be able to detect any potential relaxation of semantic transparency ๐Ÿ•ต๏ธโ€โ™€๏ธ

Note: The server, cache, or client implementor might face design decisions not explicitly discussed in this specification. If a decision might affect semantic transparency, the implementor ought to err on the side of maintaining transparency unless a careful and complete analysis shows significant benefits in breaking transparency. ๐Ÿ™

13.1.1. Cache Correctness โœจ

Okay so bestie, a correct cache MUST respond to a request with the most up-to-date response it's holding that's actually appropriate for that request (see sections 13.2.5, 13.2.6, and 13.12) ๐Ÿ’…. It only gets to do that if the response meets one of these 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) ๐ŸŒธ. By default, that means it meets the least restrictive freshness requirement of the client, origin server, and cache (see section 14.9). If the origin server says so, it only has to meet the origin server's own freshness requirement ๐Ÿ‘‘.

If a stored response isn't "fresh enough" by the most restrictive freshness requirement of both the client and the origin server, the cache MAY still return it in carefully considered circumstances, with the appropriate Warning header (see sections 13.1.5 and 14.46) ๐Ÿงš. The exception is when the response is prohibited, like by a "no-store" cache-directive or a "no-cache" cache-request-directive (see section 14.9) ๐Ÿ™…โ€โ™€๏ธ.

  1. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect), or error (4xx or 5xx) response message ๐ŸŽ€.

If the cache can not communicate with the origin server, a correct cache SHOULD respond as above if the response can be correctly served from the cache ๐Ÿซถ. If it can't do that, it MUST return an error or warning saying there was a communication failure ๐Ÿ˜ญ.

If a cache receives 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 to the requesting client anyway. It shouldn't add a new Warning, but it also shouldn't remove any existing Warning headers ๐Ÿฆ‹. A cache SHOULD NOT try to revalidate a response just because it went stale in transit, since that could lead to an infinite loop ๐ŸŒ€. A user agent that gets a stale response with no Warning MAY display 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 general-header ๐Ÿšจ. The Warning header and the currently defined warnings are described in section 14.46. The warning lets clients take appropriate action ๐Ÿ’–.

Warnings MAY 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 get three digit warn-codes. The first digit tells you whether the Warning MUST or MUST NOT be deleted from a stored cache entry after a successful revalidation ๐Ÿ“‹:

  • 1xx Warnings describe the freshness or revalidation status of the response, so they MUST be deleted after a successful revalidation. 1XX warn-codes MAY be generated by a cache only when validating a cached entry. It MUST NOT be generated by clients ๐Ÿ”„.
  • 2xx Warnings describe some aspect of the entity body or entity headers that revalidation doesn't fix (for example, a lossy compression of the entity bodies). These MUST NOT be deleted after a successful revalidation ๐Ÿ“.

See section 14.46 for the definitions of the codes themselves ๐Ÿ“–.

HTTP/1.0 caches will cache all Warnings in responses, and they won't delete the ones in the first category ๐Ÿ•ฐ๏ธ. Warnings in responses passed to HTTP/1.0 caches carry an extra warning-date field. That field stops a future HTTP/1.1 recipient from believing a Warning that was cached in error ๐Ÿ›ก๏ธ.

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

Multiple warnings MAY be attached to a response, either by the origin server or by a cache. That includes multiple warnings with the same code number. For example, a server might send the same warning with texts in both English and Basque ๐Ÿ‡ฌ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ธ.

When a response has multiple warnings attached, showing all of them to the user might not be practical or reasonable ๐Ÿ™ˆ. This version of HTTP doesn't specify strict priority rules for deciding which warnings to display and in what order, but it does suggest some heuristics ๐Ÿ’….

13.1.3. Cache-control Mechanisms

The basic cache mechanisms in HTTP/1.1 (server-specified expiration times and validators) are 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 usually override the default caching algorithms. As a general rule, if there's any apparent conflict between header values, the most restrictive interpretation is applied (the one most likely to preserve semantic transparency) ๐Ÿ”’. But some cache-control directives are explicitly specified as weakening that approximation of semantic transparency, like 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, the user agent might let the user say that cached entities (even explicitly stale ones) are never validated. Or the user agent might habitually add Cache-Control: max-stale=3600 to every request ๐Ÿ‘€. The user agent SHOULD NOT default to either non-transparent behavior, or behavior that results in abnormally ineffective caching. It MAY be explicitly configured to do so by an explicit action of the user ๐Ÿ™…โ€โ™€๏ธ.

If the user has overridden the basic caching mechanisms, the user agent SHOULD explicitly indicate it whenever that results in displaying information that might not meet the server's transparency requirements. This is especially true 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 show up 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 indicator ๐Ÿคข.

If the user has overridden the caching mechanisms in a way that would abnormally reduce the effectiveness of caches, the user agent SHOULD continually indicate this state to the user ๐Ÿ”ฅ. For example, it could show a picture of currency in flames, so the user doesn't accidentally burn through excess resources or suffer from excessive latency ๐Ÿ’ธ.

13.1.5. Exceptions to the Rules and Warnings

Sometimes the operator of a cache MAY choose to configure it to return stale responses even when clients didn't ask for them ๐Ÿง‘โ€๐Ÿ’ป. This decision ought not be made 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), so the client software can 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 that 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 main source of expiration information, with intermediate caches playing a smaller role through their contribution to the age of a response ๐Ÿ . But sometimes the client needs a say in whether a cache returns a cached response without validating it. Clients do this with several directives of the Cache-Control header ๐ŸŽ›๏ธ.

A client's request MAY 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 0๏ธโƒฃ. A client MAY 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 MAY also say it will accept stale responses, up to some maximum amount of staleness. This loosens the constraints on caches, so it might break the origin server's specified constraints on semantic transparency. It might still be necessary for disconnected operation, or for high availability when connectivity is poor ๐Ÿ“ด.


13.2. Expiration Model

13.2.1. Server-Specified Expiration

HTTP caching works best when caches can completely avoid sending requests to the origin server ๐Ÿ†. The main way to avoid requests is for an origin server to give an explicit expiration time in the future, saying that a response MAY be used to satisfy later requests. In other words, a cache can return a fresh response without asking the server first ๐Ÿงšโ€โ™€๏ธ.

The idea is that servers will give future explicit expiration times to responses because they believe the entity won't change in a semantically significant way before that time ๐Ÿ”ฎ. This normally preserves semantic transparency, as long as the server picks its expiration times carefully ๐Ÿง.

The expiration mechanism only applies to responses taken from a cache. It doesn't apply to first-hand responses forwarded right away to the requesting client ๐Ÿƒโ€โ™€๏ธ.

If an origin server wants to force a semantically transparent cache to validate every request, it MAY assign 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. See section 14.9.4 for a more restrictive way to force revalidation ๐Ÿ”’.

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) ๐Ÿ’ช.

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 force a user agent to refresh its display or reload a resource. Its semantics only apply to caching mechanisms, and those mechanisms only need to check a resource's expiration status when a new request for that resource starts. See section 13.13 for the difference between caches and history mechanisms ๐Ÿ“œ.

13.2.2. Heuristic Expiration

Origin servers don't always give explicit expiration times, so HTTP caches usually assign heuristic expiration times ๐ŸŽฒ. They use algorithms that look at other header values (like the Last-Modified time) to guess a plausible expiration time ๐Ÿ”. The HTTP/1.1 specification doesn't give specific algorithms, but it does put worst-case constraints on their results ๐Ÿšง. Heuristic expiration times might compromise semantic transparency, so they ought to be used cautiously. We really encourage origin servers to give explicit expiration times as much as they can ๐Ÿ’–โœจ.

13.2.3 Age Calculations โœจ

okay so, a cache needs to know if its age is bigger than its freshness lifetime to decide if an entry is still fresh ๐Ÿซถ we'll do the freshness lifetime math in section 13.2.4 ๐Ÿฆ‹. this section is all about working out the age of a response or cache entry ๐Ÿ’…

when we say "now" we just mean "whatever the clock on this host says right this second" โฐ hosts using HTTP, and especially origin servers and caches, SHOULD use NTP [28] or something similar to sync their clocks to a globally accurate time standard. clock vibes matter, bestie ๐Ÿ•ฐ๏ธ

HTTP/1.1 requires origin servers to send a Date header, if they can, with every response. it tells you when the response was generated (see section 14.18) ๐Ÿ“… we'll call the value of that header "date_value," in a form that works for math ๐Ÿ”ข

HTTP/1.1 uses the Age response-header to say how old a response is when it comes from a cache ๐Ÿ‘ต the Age value is the cache's guess for how long it's been since the origin server generated or revalidated the response โŒ›

basically, the Age value is all the time the response has chilled inside each cache along the way from the origin server, plus all the time it spent traveling over the network ๐Ÿš‚๐ŸŒธ we'll call the value of that header "age_value," also in math-friendly form ๐Ÿงฎ

there are two totally independent ways to figure out a response's age ๐Ÿ‘€

  1. now minus date_value, if your local clock is reasonably in sync with the origin server's clock. if that comes out negative, you just use zero instead ๐Ÿ™ƒ
  2. age_value, but only if every cache on the response path is running HTTP/1.1 ๐Ÿ’…

since we have two separate ways to get the age, we can combine them like this ๐ŸŒˆ

corrected_received_age = max(now - date_value, age_value)

and as long as we've got either nearly synced clocks or an all-HTTP/1.1 path, you get a reliable (conservative) result ๐Ÿ”ฅ

here's the tea ๐Ÿต some real time can pass between the server generating a response and the next cache or client actually receiving it, because of network delays ๐Ÿข if we don't correct for that, the age comes out too low, and that's not it ๐Ÿ˜ญ

the fix is to record the time the request was started. the request that got back that Age value had to be sent before the value was created, so when an Age value shows up, it MUST be interpreted relative to the time the request was initiated, not the time the response arrived ๐ŸŽฏ this keeps things conservative no matter how much delay happened, which is so iconic ๐Ÿ‘‘ so we compute:

corrected_initial_age = corrected_received_age

  • (now - request_time)

where "request_time" is the time (by the local clock) when the request that got this response was sent โฑ๏ธ

here's the full age calculation summary for 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;

the current_age of a cache entry is the corrected initial age plus how many seconds have passed since the origin server last validated the entry ๐Ÿง when a cache builds a response from one of its entries, it MUST include a single Age header field in that response, and its value MUST be the entry's current_age ๐Ÿ’– (okay, it's MUST, not vibes, sorry ๐Ÿ˜…)

having an Age header in a response means the response is not first-hand ๐Ÿ™…โ€โ™€๏ธ the reverse isn't guaranteed though. no Age header doesn't automatically mean it's first-hand, unless every cache on the request path is HTTP/1.1 compliant, because older caches never learned how to do Age ๐Ÿ‘ด

13.2.4 Expiration Calculations ๐ŸŒธ

so to figure out if a response is fresh or stale, we compare its freshness lifetime to its age ๐Ÿ•ต๏ธโ€โ™€๏ธ the age part is in section 13.2.3, and this section is where we figure out the freshness lifetime and decide whether the response has expired ๐Ÿ“ in the math below, the values can be stored however is easiest for arithmetic ๐Ÿงฎ

we'll call the value of the Expires header "expires_value," and "max_age_value" is the number of seconds in the "max-age" directive of a Cache-Control header in a response (see section 14.9.3) ๐Ÿซง

max-age takes priority over Expires, so if max-age is in the response, the math is just:

freshness_lifetime = max_age_value

otherwise, if Expires is in the response, it's:

freshness_lifetime = expires_value - date_value

and fun fact, neither of these is affected by clock skew, since all the info comes straight from the origin server ๐Ÿง โœจ

if none of Expires, Cache-Control: max-age, or Cache-Control: s-maxage (see section 14.9.3) show up in the response, and the response doesn't have any other caching restrictions, the cache MAY work out a freshness lifetime using a heuristic ๐Ÿค” the cache MUST attach Warning 113 to any response whose age is more than 24 hours, if that 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 fraction might be 10% ๐Ÿ’…

figuring out whether a response has expired is honestly super simple ๐Ÿ˜Œ

response_is_fresh = (freshness_lifetime > current_age)

13.2.5 Disambiguating Expiration Values ๐Ÿ’œ

expiration values get assigned optimistically, so two caches can each have fresh copies of the same resource that are totally different ๐Ÿ˜ฌ that's a whole mess, bestie ๐Ÿซ 

if a client doing a retrieval gets a response that isn't first-hand, for a request its own cache already had fresh, and the Date header in its existing entry is newer than the Date on the new response, then the client MAY ignore the new response ๐Ÿ™ˆ if it does, 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 but 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 revalidation of an entry that looked fresh ๐Ÿ”„

13.2.6 Disambiguating Multiple Responses ๐Ÿฆ‹

clients can get responses through multiple paths, so some responses might come through one set of caches and others through a different set ๐Ÿ›ฃ๏ธ that means a client could receive responses in a different order than the origin server sent them ๐Ÿ˜ต we really want the client to use the most recently generated response, even if older ones still look fresh ๐Ÿ’–

neither the entity tag nor the expiration value can set an order for responses, because a later response can totally intentionally have an earlier expiration time ๐Ÿ™ƒ Date values are ordered to a granularity of one second โณ

when a client tries to revalidate a cache entry and the response has a Date that looks older than the one on the existing entry, the client SHOULD repeat the request unconditionally, and include

Cache-Control: max-age=0

to make any intermediate caches check their copies directly with the origin server, or

Cache-Control: no-cache

to make any intermediate caches 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 fresh response too ๐Ÿง and servers MUST NOT depend on clients being able to pick deterministically between responses generated during the same second, if their expiration times overlap ๐Ÿšซ that's a no-no, bestie ๐Ÿ˜ค


13.3 Validation Model ๐ŸŽ€

when a cache has a stale entry it wants to use as a response to a client's request, it first has to check with the origin server (or maybe an intermediate cache with a fresh response) to see if the entry is still usable ๐Ÿ”Ž we call this "validating" the entry โœ… we don't want to pay the cost of resending the whole response if the cached entry is still good, and we don't want to pay for an extra round trip if the entry is invalid, so HTTP/1.1 supports conditional methods ๐ŸŒˆ

the key features for conditional methods are the "cache validators" ๐Ÿ—๏ธ when an origin server generates a full response, it attaches some kind of validator to it, which 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, and if they match (see section 13.3.3), it responds with a special status code (usually 304 (Not Modified)) and no entity-body ๐Ÿ™Œ otherwise, it returns a full response, including the entity-body ๐Ÿ“จ so we skip resending the full response when the validator matches, and we skip an extra round trip when it doesn't ๐Ÿซถ

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 one ๐Ÿช„

the protocol has both positive and negative cache-validating conditions ๐Ÿ”€ that means you can ask for a method to run only if a validator matches, or only if no validators match ๐Ÿ’…

Note: a response without a validator can still be cached and served from cache until it expires, unless a cache-control directive explicitly forbids it ๐Ÿ“ but a cache can't do a conditional retrieval without a validator for the entity, so it can't be refreshed once 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 counts as valid if the entity hasn't been modified since the Last-Modified value ๐Ÿ’– no drama, just vibes ๐ŸŒธ

13.3.2. Entity Tag Cache Validators โœจ

okay so the ETag response-header field value, an entity tag ๐Ÿท๏ธ, gives you an "opaque" cache validator ๐Ÿ”. this can be super helpful when storing modification dates is a hassle ๐Ÿ“…, when the one-second resolution of HTTP date values just isn't precise enough โฑ๏ธ, or when the origin server wants to dodge certain paradoxes that can pop up with modification dates ๐ŸŒ€. it's giving "no tangles" energy ๐Ÿ’…

Entity Tags are described in section 3.11. The headers used with entity tags are described in sections 14.19, 14.24, 14.26 and 14.44.

13.3.3. Weak and Strong Validators ๐Ÿ‘‘

okay this one's a big deal ๐Ÿง. origin servers AND caches both compare two validators to figure out if they're the same or different entities, so you'd normally expect that if the entity (the entity-body or any entity-headers) changes in any way, the validator changes too. if that's true, we call it a "strong validator" ๐Ÿ’ช.

BUT sometimes a server would rather only change the validator on semantically significant changes, and not when insignificant aspects of the entity shift around ๐Ÿซง. 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 ๐Ÿง . or another way to see it: a strong validator is part of an identifier for one specific entity, and 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.
Note: An entity's modification time, if represented with one-second resolution, could be a weak validator, since it is possible that the resource might be modified twice during a single second.
Note: 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 is 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 do not depend on exact equality of an entity ๐Ÿ™ˆ. for example, either kind is usable for a conditional GET of a full entity. however, only a strong validator is usable for a sub-range retrieval, since otherwise the client might end up with an internally inconsistent entity ๐Ÿ’€.

Clients MAY issue simple (non-subrange) GET requests with either weak validators or strong validators. Clients MUST NOT use weak validators in other forms of request. ๐Ÿšซ

the only function that the HTTP/1.1 protocol defines on validators is comparison ๐Ÿ”. there are two validator comparison functions, depending on whether the comparison context allows the use of weak validators or not:

  • The strong comparison function: in order to be considered equal, both validators MUST be identical in every way, and both MUST NOT 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.

an entity tag is strong unless it is 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 is possible to deduce that it is 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 are generated from different clocks, or at somewhat different times during the preparation of the response โฐ. an implementation MAY use a value larger than 60 seconds, if it is believed that 60 seconds is too short ๐ŸŒธ.

if a client wishes to perform a sub-range retrieval on a value for which it has only 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 conditional request, other than a full-body GET request, MUST use the strong comparison function to evaluate the condition. ๐Ÿซถ

these rules allow HTTP/1.1 caches and clients to safely perform sub-range retrievals on values that have been obtained from HTTP/1.0 servers ๐Ÿงš.

13.3.4. Rules for When to Use Entity Tags and Last-Modified Dates ๐Ÿ“‹

we adopt a set of rules and recommendations for origin servers, clients, and caches regarding when various validator types ought to be used, and for what purposes ๐Ÿ’–.

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 might persist for arbitrarily long periods, regardless of expiration times, so it might 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 origin server, upon receiving a conditional request that includes both a Last-Modified date (e.g., in an If-Modified-Since or If-Unmodified-Since header field) and one or more entity tags (e.g., in an If-Match, If-None-Match, or If-Range header field) as cache validators, MUST NOT return a response status of 304 (Not Modified) unless doing so is consistent with all of the conditional header fields in the request. ๐Ÿ™…โ€โ™€๏ธ

An HTTP/1.1 caching proxy, upon receiving a conditional request that includes both a Last-Modified date and one or more entity tags as cache validators, MUST NOT return a locally cached response to the client unless that cached response is consistent with all of the conditional header fields in the request. ๐Ÿ™…

Note: 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 principle behind entity tags is that only the service author knows the semantics of a resource well enough to select 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 Cacheability โœจ

Okay bestie, so the default is that a caching system MAY always store a successful response (see section 13.8) as a cache entry ๐Ÿ“ฆ. Unless a cache-control directive (section 14.9) says otherwise, it MAY hand that entry back without validating it if it's still fresh, and it MAY hand it back after a successful validation too ๐Ÿ’…. If a response has neither a cache validator nor an explicit expiration time, we don't expect it to get cached ๐Ÿ™…โ€โ™€๏ธ. But certain caches MAY break that expectation anyway (for example, when there's little or no network connectivity) ๐Ÿ“ถ. A client can usually tell that a response came from a cache by comparing the Date header to the current time โฐ.

๐Ÿ“ Note: some HTTP/1.0 caches are known to break that expectation without providing any Warning. Hmm, sus ๐Ÿ‘€

Sometimes though, it's just not giving for a cache to keep an entity or return it to someone later ๐Ÿ™…โ€โ™€๏ธ. Maybe the service author needs absolute semantic transparency, or there are security or privacy concerns ๐Ÿ”. That's why there are cache-control directives, so the server can say that certain resource entities, or parts of them, are not to be cached no matter what else is going on ๐Ÿ›‘.

Also, section 14.8 usually stops a shared cache from saving and returning a response to a previous request if that request had an Authorization header in it ๐Ÿ™ˆ. Main character energy for privacy, no cap ๐Ÿ‘‘.

A response with a status code of 200, 203, 206, 300, 301 or 410 MAY be stored by a cache and reused for a later request, as long as it follows the expiration mechanism and no cache-control directive says no ๐ŸŽ€. But a cache that doesn't support the Range and Content-Range headers MUST NOT cache 206 (Partial Content) responses ๐Ÿšซ.

Any other status code (like 302 and 307) MUST NOT be returned in reply to a later request unless a cache-control directive or some other header explicitly allows it ๐Ÿ›‘. Examples of that permission include an Expires header (section 14.21), or a max-age, s-maxage, 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 what comes back from requests so it can answer future requests ๐Ÿง . Most of the time, it just passes the right parts of a response along to whoever asked ๐Ÿ“จ. But if the cache already has an entry from an earlier response, it might need to mix bits of the new response with what's already stored ๐Ÿงฉ.

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 buckets ๐Ÿชฃ:

  • End-to-end headers, which get sent all the way to the final recipient of a request or response ๐ŸŽฏ. End-to-end headers in responses MUST be stored as part of a cache entry, and they MUST be sent along in any response built from a cache entry ๐Ÿ’–.
  • Hop-by-hop headers, which only matter for one single transport-level connection ๐Ÿ”—. Caches don't store them and proxies don't forward them ๐Ÿ™…โ€โ™€๏ธ.

These HTTP/1.1 headers are hop-by-hop headers ๐Ÿซถ:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade

Every other header defined by HTTP/1.1 is an end-to-end header ๐ŸŒˆ.

Any other hop-by-hop header MUST be listed in a Connection header (section 14.10) to be introduced into HTTP/1.1 (or later) ๐Ÿ“. Iykyk ๐Ÿ˜ญ.

13.5.2 Non-modifiable Headers ๐Ÿ”’

Some HTTP/1.1 features, like Digest Authentication, depend on the exact value of certain end-to-end headers ๐Ÿ”. So a transparent proxy SHOULD NOT modify an end-to-end header unless that header's definition requires or specifically allows it ๐Ÿ™…โ€โ™€๏ธ.

A transparent proxy MUST NOT modify any of these fields in a request or response, and it MUST NOT add any of them if they're not already there ๐Ÿšซ:

  • Content-Location
  • Content-MD5
  • ETag
  • Last-Modified

A transparent proxy MUST NOT modify this field in a response ๐Ÿ›‘:

  • Expires

...but it MAY add any of these fields if they're not already present ๐ŸŽ. If an Expires header gets added, it MUST be given a field-value identical to the Date header in that same response ๐Ÿ’….

A proxy MUST NOT modify or add any of these fields in a message that contains the no-transform cache-control directive, or in any request ๐Ÿ™…โ€โ™€๏ธ:

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

A non-transparent proxy MAY modify or add these fields to a message that doesn't include no-transform. But if it does, it MUST add a Warning 214 (Transformation applied) if one isn't already in the message (see section 14.46) ๐Ÿท๏ธ.

โš ๏ธ Warning: unnecessary modification of end-to-end headers might cause authentication failures if stronger authentication mechanisms are introduced in later versions of HTTP. Those authentication mechanisms MAY rely on the values of header fields that aren't listed here ๐Ÿ˜ฌ.

The Content-Length field of a request or response gets added or deleted according to the rules in section 4.4 ๐Ÿ“. A transparent proxy MUST preserve the entity-length (section 7.2.2) of the entity-body, though it MAY change the transfer-length (section 4.4) ๐Ÿงš.

13.5.3 Combining Headers ๐Ÿ“

When a cache sends a validating request to a server, and the server answers with a 304 (Not Modified) response or a 206 (Partial Content) response, the cache then builds the response it sends back to the client ๐Ÿ’Œ.

If the status code is 304 (Not Modified), the cache uses the entity-body stored in the cache entry as the entity-body of this outgoing response ๐Ÿ“ฆ. If the status code is 206 (Partial Content) and the ETag or Last-Modified headers match exactly, the cache MAY combine what's stored in the cache entry with the new contents from the response, and use the result as the entity-body of this outgoing response (see 13.5.4) ๐Ÿงฉ.

The end-to-end headers stored in the cache entry get used for the built response, with a few exceptions ๐ŸŽ€:

  • Any stored Warning headers with warn-code 1xx (see section 14.46) MUST be deleted from the cache entry and from the forwarded response ๐Ÿ—‘๏ธ.
  • Any stored Warning headers with warn-code 2xx MUST be kept in the cache entry and in the forwarded response ๐Ÿ’พ.
  • Any end-to-end headers provided in the 304 or 206 response MUST replace the matching 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 the matching headers from the incoming response, except for the Warning headers we just talked about ๐Ÿ”„. If a header field-name in the incoming response matches more than one header in the cache entry, all of those old headers MUST be replaced ๐Ÿ’ฏ.

So basically, the end-to-end headers from the incoming response override all the matching end-to-end headers stored with the cache entry. The exception is stored Warning headers with warn-code 1xx, which get deleted even if nothing overrides them ๐Ÿ’€.

๐Ÿ“ Note: this rule lets an origin server use a 304 (Not Modified) or a 206 (Partial Content) response to update any header that went with an earlier response for the same entity or its sub-ranges. It might not always make sense or be correct to do that, though ๐Ÿค”. This rule does NOT let an origin server use a 304 or 206 response to fully delete a header it sent with an earlier response ๐Ÿ™…โ€โ™€๏ธ.

13.5.4 Combining Byte Ranges ๐Ÿงฉ

A response might only transfer a subrange of the bytes of an entity-body, either because the request had one or more Range specifications, or because a connection broke early ๐Ÿ’”. After a few of these transfers, a cache might have several ranges of the same entity-body ๐Ÿงƒ.

If a cache already 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, but only if both of these are true ๐Ÿซถ:

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

If either requirement isn't met, the cache MUST use only the most recent partial response (based on the Date values sent with every response, and using the incoming response if those values are equal or missing) โณ. It MUST also discard the other partial information ๐Ÿ—‘๏ธ. Periodt ๐Ÿ’…โœจ

13.6. Caching Negotiated Responses โœจ

Okay bestie, so when a server uses server-driven content negotiation (section 12.1), which you can spot by the Vary header field in the response, that changes the rules for when a cache can reuse that response for later requests ๐ŸŽ€. Servers use Vary in a specific way, so peep section 14.44 for those details ๐Ÿ’….

A server SHOULD use the Vary header field to tell a cache which request-header fields were used to pick between multiple representations of a cacheable response that's subject to server-driven negotiation ๐Ÿฆ‹. The header fields named in the Vary value are called the "selecting" request-headers, and they're the main characters here ๐Ÿ‘‘.

When a cache gets a new request whose Request-URI points at one or more cache entries that have a Vary header field, the cache MUST NOT use that entry to build a response unless every selecting request-header in the new request matches the stored request-headers from the original request ๐Ÿ™ˆ. No skipping the check, periodt ๐Ÿ’€.

Two requests have matching selecting request-headers if and only if you can turn the selecting request-headers from the first request into the ones in the second request. You can do that by adding or removing linear white space (LWS) in the spots the corresponding BNF allows, and/or by combining multiple message-header fields that share a field name, following the rules about message headers in section 4.2 ๐ŸŒธ.

A Vary field-value of * always fails to match, so later requests on that resource can only be properly interpreted by the origin server ๐Ÿ˜ญ.

If the selecting request header fields for a cached entry don't match the selecting request header fields of the new request, the cache MUST NOT use the cached entry to satisfy the request. It has to first relay the new request to the origin server as a conditional request, and the server has to respond with 304 (Not Modified), including an entity tag or Content-Location that shows which entity should be used ๐Ÿซถ.

If an entity tag was given to a cached representation, the forwarded request SHOULD be conditional and include the entity tags from all of the cache's entries for the resource in an If-None-Match header field โœจ. This tells the server which entities the cache is currently holding, so if one of them matches the requested entity, the server can use the ETag header field in its 304 (Not Modified) response to tell the cache 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 ๐Ÿ’–.

If any existing cache entry only has partial content for its entity, its entity-tag SHOULD NOT be included in the If-None-Match header field, unless the request is for a range that the entry would fully satisfy ๐Ÿ“.

If a cache receives a successful response whose Content-Location field matches an existing cache entry for the same Request-URI, whose entity-tag is different from the existing entry's, and whose Date is more recent than the existing entry's, the existing entry SHOULD NOT be returned in response to 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 "shared" and "non-shared" ones, and this part is seriously important ๐Ÿซถ. A non-shared cache can only be accessed by a single user. That access SHOULD be enforced by appropriate security mechanisms ๐Ÿ”. Every other cache counts as "shared" ๐Ÿ‘‘. Other sections of this spec limit what shared caches can do, so they don't leak private stuff or break access controls ๐Ÿ˜ญ.


13.8. Errors or Incomplete Response Cache Behavior ๐Ÿ’€

A cache that gets an incomplete response (for example, one with fewer bytes of data than the Content-Length header says) MAY store it ๐Ÿ“. BUT the cache MUST treat it as a partial response ๐Ÿ™ˆ. Partial responses MAY be combined as described in section 13.5.4, and the result could be a full response or could still be partial ๐Ÿงฉ. A cache MUST NOT hand a partial response to a client without clearly marking it as partial, using the 206 (Partial Content) status code โœจ. A cache MUST NOT return a partial response with a status code of 200 (OK) ๐Ÿšซ.

If a cache gets a 5xx response while it's trying to revalidate an entry, it MAY either forward that response to the requesting client, or act as if the server never responded ๐ŸŒธ. 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 bans caching of these responses, using GET and HEAD on any resources SHOULD NOT cause side effects that would lead to messed-up behavior if the responses come from a cache ๐Ÿ™…โ€โ™€๏ธ. The requests MAY still have side effects, but a cache isn't required to think about those side effects when it makes caching decisions ๐Ÿง . Caches are always expected to respect an origin server's explicit caching restrictions, no exceptions ๐Ÿซถ.

There's one exception to this rule ๐Ÿ‘€. Some apps have traditionally used GETs and HEADs with query URLs (the ones with a ? in the rel_path part) to do operations with big side effects ๐Ÿ˜ญ. So caches MUST NOT treat responses to those URIs as fresh unless the server gives an explicit expiration time โฐ. This specifically means that responses from HTTP/1.0 servers for those URIs SHOULD NOT be taken from a cache ๐Ÿšซ. See section 9.1.1 for related info ๐Ÿฆ‹.


13.10. Invalidation After Updates or Deletions ๐Ÿ’ฅ

Certain methods used on a resource at the origin server can make one or more existing cache entries non-transparently invalid ๐Ÿ˜ต. Even if those entries still count as "fresh," they don't accurately show what the origin server would return for a new request on that resource ๐Ÿ™ƒ.

HTTP can't guarantee that every one of those cache entries gets marked invalid ๐Ÿ˜ฌ. For example, the request that made the change at the origin server might never have gone through the proxy where a cache entry lives ๐Ÿƒโ€โ™€๏ธ. Still, a few rules help cut down on messed-up behavior ๐ŸŒŸ.

In this section, "invalidate an entity" means the cache will either remove every instance of that entity from its storage, or mark them as "invalid" and in need of a mandatory revalidation before they can be returned for a later request ๐Ÿงน.

Some HTTP methods MUST make a cache invalidate an entity ๐Ÿ’…. That's either the entity referred to by the Request-URI, or the one from the Location or Content-Location headers (if they're there) ๐Ÿ“. 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 happen if its host part matches the one in the Request-URI ๐Ÿ›ก๏ธ. This one's so important, bestie ๐Ÿ˜ค.

A cache that passes through requests for methods it doesn't understand SHOULD invalidate any entities referred to by the Request-URI ๐Ÿซถ.


13.11. Write-Through Mandatory ๐Ÿ“

Every method that might change the origin server's resources MUST be written through to the origin server ๐Ÿ’Œ. Right now, that's 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 ๐Ÿ™…โ€โ™€๏ธ. This doesn't stop a proxy cache from sending a 100 (Continue) response before the inbound server has sent its final reply ๐ŸŒธ.

The alternative, known as "write-back" or "copy-back" caching, is not allowed in HTTP/1.1 ๐Ÿšซ. That's because it's hard to keep updates consistent, and a server, cache, or network failure before the write-back causes a lot of problems ๐Ÿ˜ญ.


13.12. Cache Replacement ๐Ÿ”„

If a new cacheable response comes in from a resource while existing responses for that same resource are cached (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8), the cache SHOULD use the new response to reply to the current request โœจ. The cache MAY store it, and MAY, if it meets all the other requirements, use it to respond to any future requests that would've gotten the old response before ๐Ÿฆ‹. If the new response does go into cache storage, the rules in section 13.5.3 apply ๐Ÿง .

Note: a new response that has an older Date header value than existing cached responses is not cacheable. ๐Ÿ™ˆ

13.13. History Lists ๐Ÿ“š

User agents often have history features, like "Back" buttons and history lists, that can bring back an entity they fetched earlier in a session ๐Ÿ”™.

History mechanisms and caches are NOT the same thing ๐Ÿ™…โ€โ™€๏ธ. 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 when the resource was retrieved ๐Ÿ“ธ.

By default, expiration times don't apply to history mechanisms โณ. If the entity is still in storage, a history mechanism SHOULD display it even if it has expired, unless the user has specifically configured the agent to refresh expired history documents ๐Ÿ”„.

None of this stops the history mechanism from telling the user that a view might be stale โš ๏ธ.

Note: if history list mechanisms unnecessarily stop users from viewing stale resources, service authors will be tempted 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 don't get error or warning messages when they use navigation controls (such as BACK) to view previously fetched resources ๐Ÿ™. Even if some resources ought not to be cached, or ought to expire quickly, UI considerations may push service authors to use other ways of preventing caching (like "once-only" URLs), so they don't suffer from improperly working history mechanisms ๐Ÿซ .

14. Header Field Definitions โœจ

This section defines the syntax and semantics of all the standard HTTP/1.1 header fields ๐Ÿ“œ. For entity-header fields, "sender" and "recipient" mean 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 if you only want an in-line image, you can say so and keep the request tight ๐ŸŽ€

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 what groups media types into ranges ๐ŸŒธ so "/" means every media type, and "type/" means every subtype of that type โœจ a media-range MAY also include media type parameters that apply to that range ๐Ÿงš

each media-range MAY be followed by one or more accept-params, and the first one is always the "q" parameter ๐Ÿ’… that's the relative quality factor. the first "q" is the dividing line between the media-range parameters and 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 is q=1.

Note: using "q" to split media type parameters from Accept extension parameters is basically historical vibes ๐Ÿ•ฐ๏ธ it does mean a media type parameter named "q" can't be used with a media range, but that's believed to be super unlikely since the IANA media type registry has no "q" parameters and barely anyone uses media type parameters in Accept anyway. future media types are discouraged from registering any parameter named "q" ๐Ÿ™…โ€โ™€๏ธ

here's the example ๐Ÿ‘€

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

this 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 there's no Accept header field, then it's assumed the client accepts all media types ๐ŸŒˆ but if there IS an Accept header and the server can't send anything acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response ๐Ÿ™ˆ

a more elaborate one ๐Ÿ“

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

verbally, that means "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." ๐Ÿ‘‘

media ranges can get overridden by more specific media ranges or specific media types โœจ if more than one media range applies to a type, the most specific one wins. 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 quality factor for a given type comes from the media range with the highest precedence that matches it ๐Ÿ’œ 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 give these values:

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 might come with a default set of quality values for certain media ranges ๐ŸŽ€ unless it's a closed system that can't talk to other rendering agents, that default set ought to be configurable by the user ๐Ÿ’…

14.2 Accept-Charset ๐ŸŒธ

the Accept-Charset request-header field tells the server which character sets are acceptable for the response ๐Ÿ’– it's how clients who understand fancier or more special-purpose character sets can flex that capability on a server that can represent documents in those sets ๐Ÿ’…

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 showing the user's preference for it, and the default is q=1 ๐ŸŽ€ here's an example ๐Ÿ‘€

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

the special "" value, if it's in the Accept-Charset field, matches every character set (including ISO-8859-1) that isn't mentioned elsewhere in that field ๐Ÿฆ‹ if there's no "", then every character set that isn't explicitly mentioned gets a quality value of 0, except ISO-8859-1, which gets a quality value of 1 unless it's explicitly mentioned ๐Ÿงš

if there's no Accept-Charset header, any character set is acceptable ๐ŸŒˆ if there IS one, and the server can't send a response that's acceptable according to it, then the server SHOULD send an error response with the 406 (not acceptable) status code ๐Ÿ˜ญ though sending an unacceptable response is still allowed ๐Ÿ™ƒ


14.3 Accept-Encoding ๐Ÿ“

the Accept-Encoding request-header field is basically a cousin of Accept ๐Ÿ’… but it restricts the content-codings (section 3.5) that are acceptable in the response โœจ

Accept-Encoding  = "Accept-Encoding" ":"
                   1#( codings [ ";" "q" "=" qvalue ] )
codings          = ( content-coding | "*" )

examples of how it's used ๐Ÿงš

Accept-Encoding: compress, gzip
Accept-Encoding:
Accept-Encoding: *
Accept-Encoding: compress;q=0.5, gzip;q=1.0
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0

a server checks whether a content-coding is acceptable, according to an Accept-Encoding field, using these rules ๐Ÿ‘‘

  1. if the content-coding is one of the ones listed in the Accept-Encoding field, it's acceptable, unless it comes with a qvalue of 0. (as defined in section 3.9, a qvalue of 0 means "not acceptable.") ๐Ÿ™…โ€โ™€๏ธ
  2. the special "*" symbol in an Accept-Encoding field matches any available content-coding that isn't explicitly listed in the header field ๐ŸŒธ
  3. if multiple content-codings are acceptable, the one with the highest non-zero qvalue is preferred ๐Ÿ”ฅ
  4. the "identity" content-coding is always acceptable, unless it's specifically refused, either because the Accept-Encoding field includes "identity;q=0", or because the field includes "*;q=0" and doesn't explicitly include "identity" ๐Ÿซถ if the Accept-Encoding field-value is empty, then only "identity" is acceptable ๐Ÿ’€

if an Accept-Encoding field is in a request, and the server can't send a response that's acceptable according to it, then the server SHOULD send an error response with the 406 (Not Acceptable) status code ๐Ÿ˜ญ

if there's no Accept-Encoding field in a request, the server MAY assume the client will accept any content coding ๐ŸŒˆ in that case, if "identity" is one of the available content-codings, the server SHOULD use "identity", unless it has additional info that a different content-coding is meaningful to the client โœจ

Note: if the request doesn't have an Accept-Encoding field and "identity" isn't available either, then content-codings that HTTP/1.0 clients commonly understand ("gzip" and "compress") are preferred ๐Ÿ•ฐ๏ธ some older clients improperly display messages sent with other content-codings ๐Ÿ™ˆ the server might also make this decision based on info about the particular user-agent or client ๐Ÿงš
Note: most HTTP/1.0 applications don't recognize or obey qvalues associated with content-codings ๐Ÿ’… so qvalues won't work for them and aren't permitted with x-gzip or x-compress ๐Ÿšซ

14.4 Accept-Language ๐ŸŽ€

the Accept-Language request-header field is also similar to Accept ๐Ÿฆ‹ but it restricts the set of natural languages that are preferred for the response ๐ŸŒธ language tags are defined in section 3.10 โœจ

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, which is basically an estimate of the user's preference for the languages in 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 where the first tag character after that prefix is "-" ๐Ÿงš the special "*" range, if it's in the Accept-Language field, matches every tag not matched by any other range in that field ๐ŸŒˆ

Note: this prefix matching rule does NOT mean language tags are assigned so that anyone who understands one tag automatically understands every tag it's a prefix of ๐Ÿ™ƒ the prefix rule just lets you use prefix tags when that's actually the case ๐Ÿ’…

the language quality factor for a language-tag is the quality value of the longest language-range in the field that matches it โœจ if no language-range in the field matches the tag, the language quality factor is 0 ๐Ÿ™ˆ if there's no Accept-Language header in the request, the server SHOULD assume that all languages are equally acceptable ๐Ÿซถ if there IS an Accept-Language header, then every language assigned a quality factor greater than 0 is acceptable ๐Ÿ”ฅ

it might be contrary to the user's privacy expectations to send an Accept-Language header with their complete linguistic preferences in every request ๐Ÿ˜ฌ for a discussion of this issue, see section 15.1.4 ๐Ÿ”’

because intelligibility depends so much on the individual user, it is recommended that client apps make the choice of linguistic preference available to the user ๐ŸŒธ if that choice isn't made available, then the Accept-Language header field MUST NOT be given in the request ๐Ÿšซ

Note: when you do make the linguistic preference choice available to the user, remember that users aren't familiar with the details of language matching ๐Ÿฅบ so give them appropriate guidance ๐Ÿ’– for example, users might assume that picking "en-gb" gets them any kind of English document if British English isn't available ๐Ÿ‡ฌ๐Ÿ‡ง a user agent might suggest adding "en" in that case to get the best matching behavior ๐Ÿ‘‘

14.5 Accept-Ranges โœจ

okay so Accept-Ranges is the server's way of saying "yes, I'm open to range requests for this resource" ๐Ÿฆ‹ Here's the grammar:

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 even if they haven't received this header for the resource involved. Range units are defined in section 3.12 ๐Ÿ’…

Servers that don't accept any kind of range request for a resource MAY send

Accept-Ranges: none

to tell the client not to bother trying a range request ๐Ÿ™ˆ

14.6 Age โณ

The Age response-header field is the sender's estimate of how long it's been since the response (or its revalidation) was generated at the origin server. A cached response is "fresh" if its age doesn't go past its freshness lifetime. Age values get calculated the way section 13.2.3 specifies โœจ

Age = "Age" ":" age-value
age-value = delta-seconds

Age values are non-negative decimal integers, measuring time in seconds.

Now the spicy part ๐ŸŒถ๏ธ If a cache gets a value bigger than the largest positive integer it can represent, or if any of its age calculations overflows, it MUST transmit an Age header with the value 2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST include an Age header field in every response generated from its own cache. Caches SHOULD use an arithmetic type with at least 31 bits of range. Overflow is not a vibe ๐Ÿ’€

14.7 Allow ๐Ÿงš

The Allow entity-header field lists the set of methods supported by the resource identified by the Request-URI. Its whole purpose is to tell the recipient which methods are valid for the resource ๐Ÿ’œ An Allow header field MUST be present in a 405 (Method Not Allowed) response.

Allow   = "Allow" ":" #Method

Example of use:

Allow: GET, HEAD, PUT

This field can't stop 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 that the new or modified resource should support. The server is not required to support these methods, and it 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 doesn't understand all the methods listed, because the user agent might have other ways of talking to the origin server. Hands off ๐Ÿ™…โ€โ™€๏ธ

14.8 Authorization ๐Ÿ”‘

A user agent that wants to authenticate itself with a server (usually, but not always, after getting a 401 response) does so by including an Authorization request-header field with the request ๐ŸŽ€ The field value is made of credentials holding the user agent's authentication info for the realm of the resource being requested.

Authorization  = "Authorization" ":" credentials

HTTP access authentication is described in "HTTP Authentication: Basic and Digest Access Authentication" [43]. If a request is authenticated and a realm is specified, the same credentials SHOULD be valid for all other requests within that realm (unless the authentication scheme itself says otherwise, like credentials that change based on a challenge value or that rely on synchronized clocks) โฐ

When a shared cache (see section 13.7) receives a request containing an Authorization field, it MUST NOT return the corresponding response as a reply to any other request, unless one of these specific exceptions holds ๐Ÿ‘‘

  1. If the response includes the "s-maxage" cache-control directive, the cache MAY use that response to reply to a subsequent request. But (if the specified maximum age has passed) a proxy cache MUST first revalidate it with the origin server, using the request-headers from the new request so the origin server can authenticate the new request. (This is the defined behavior for s-maxage.) If the response includes "s-maxage=0", the proxy MUST always revalidate it before re-using it.
  2. If the response includes the "must-revalidate" cache-control directive, the cache MAY use that response to reply to a subsequent request. But if the response is stale, all caches MUST first revalidate it with the origin server, using the request-headers from the new request so the origin server can authenticate the new request.
  3. If the response includes the "public" cache-control directive, it MAY be returned in reply to any subsequent request.

14.9 Cache-Control ๐ŸŽ€

The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain ๐Ÿ’– These directives are there to stop caches from messing with the request or response in ways they shouldn't. They usually override the default caching algorithms. Cache directives are unidirectional, so a directive in a request doesn't mean the same directive belongs in the response too ๐Ÿฆ‹

Note that HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache (see section 14.32).

Cache directives MUST be passed through by a proxy or gateway application, no matter whether they matter to that app, since the directives might apply to every recipient along the request/response chain. You can't target a cache-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"                          ; Section 14.9.1
     | "no-store"                          ; Section 14.9.2
     | "max-age" "=" delta-seconds         ; Section 14.9.3, 14.9.4
     | "max-stale" [ "=" delta-seconds ]   ; Section 14.9.3
     | "min-fresh" "=" delta-seconds       ; Section 14.9.3
     | "no-transform"                      ; Section 14.9.5
     | "only-if-cached"                    ; Section 14.9.4
     | cache-extension                     ; Section 14.9.6

 cache-response-directive =
       "public"                               ; Section 14.9.1
     | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
     | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
     | "no-store"                             ; Section 14.9.2
     | "no-transform"                         ; Section 14.9.5
     | "must-revalidate"                      ; Section 14.9.4
     | "proxy-revalidate"                     ; Section 14.9.4
     | "max-age" "=" delta-seconds            ; Section 14.9.3
     | "s-maxage" "=" delta-seconds           ; Section 14.9.3
     | cache-extension                        ; Section 14.9.6

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

When a directive shows up without any 1#field-name parameter, it applies to the entire request or response. When it shows up with a 1#field-name parameter, it only applies to the named field or fields, not the rest of the request or response ๐Ÿงฉ This keeps things extensible, because future versions of HTTP might apply these directives to header fields that HTTP/1.1 doesn't define.

The cache-control directives fall into these general categories:

  • Restrictions on what's cacheable, which only the origin server can put in place.
  • Restrictions on what a cache may store, which either the origin server or the user agent can impose.
  • Changes to the basic expiration mechanism, which either the origin server or the user agent can impose.
  • Controls over cache revalidation and reload, which only the user agent can impose.
  • Control over transformation of entities.
  • Extensions to the caching system ๐ŸŒˆ

14.9.1 What is Cacheable ๐Ÿ“

By default, a response is cacheable if the requirements of the request method, the request header fields, and the response status all say it's cacheable. Section 13.4 sums up these defaults for cacheability โœจ The following Cache-Control response directives let an origin server override the default cacheability of a response:

public : Says the response MAY be cached by any cache, even if it would normally be non-cacheable or only cacheable within a non-shared cache. (For more, see Authorization in section 14.8.) ๐Ÿซถ

private : Says all or part of the response message is meant for a single user and MUST NOT be cached by a shared cache. This lets the origin server say the specified parts are only for one user and aren't a valid response for requests from other users. A private (non-shared) cache MAY cache the response ๐Ÿฆ‹

Note: This usage of the word private only controls where the response may be cached. It cannot ensure the privacy of the message content. Don't let the name fool you ๐Ÿ˜ญ

no-cache : If the no-cache directive doesn't specify a field-name, then a cache MUST NOT use the response to satisfy a subsequent request without successful revalidation with the origin server. This lets the origin server stop caching even by caches that have been set up to return stale responses to clients ๐Ÿ’…

If the no-cache directive does specify one or more field-names, then a cache MAY use the response to satisfy a subsequent request, subject to any other caching restrictions. However, the specified field-name(s) MUST NOT be sent in the response to a subsequent request without successful revalidation with the origin server. This lets the origin server stop certain header fields from being reused, while the rest of the response can still be cached ๐ŸŒธ

Note: Most HTTP/1.0 caches won't recognize or obey this directive. Not all caches are on the same page ๐Ÿ™ˆ

14.9.2. What May be Stored by Caches โœจ

okay bestie, let's talk about no-store ๐Ÿ”’ Its whole job is stopping sensitive stuff from leaking or hanging around in places it shouldn't, like backup tapes ๐Ÿ“ผ It applies to the entire message, and it MAY be sent in a response or in a request. If it shows up in a request, a cache MUST NOT store any part of that request or any response to it. If it shows up in a response, a cache MUST NOT store any part of that response or the request that triggered it. This applies to both non-shared and shared caches. "MUST NOT store" here means the cache MUST NOT intentionally keep the info in non-volatile storage, and it MUST make a best-effort attempt to clear the info out of volatile storage as quickly as possible after forwarding it. ๐Ÿงน

Even when no-store is on a response, users might still save it outside the caching system on purpose (hello, "Save As" dialog ๐Ÿ’พ). History buffers MAY store such responses as part of their normal operation. ๐Ÿ•ฐ๏ธ

The whole point of this directive is to keep service authors and users who worry about accidental info releases through unexpected cache access happy ๐Ÿฅน It might help privacy in some cases, BUT it is not a reliable or sufficient way to protect privacy at all. ๐Ÿšจ Malicious or compromised caches might not recognize or obey it, and communication networks might be open to eavesdropping. ๐Ÿ‘€ Please don't treat it as a force field! ๐Ÿ›ก๏ธ

14.9.3. Modifications of the Basic Expiration Mechanism ๐Ÿ’ซ

The expiration time of an entity MAY be set by the origin server using the Expires header (see section 14.21). Or, it MAY be set using the max-age directive in a response. When max-age is present in a cached response, that response is stale if its current age is greater than the age value given (in seconds) at the time of a new request for that resource. A max-age directive on a response implies the response is cacheable (i.e., "public") unless some other, more restrictive cache directive is also there. ๐Ÿ“

If a response has both an Expires header and a max-age directive, max-age overrides Expires, even if Expires is more restrictive. ๐Ÿ‘‘ This rule lets an origin server give a longer expiration time to an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. That can be useful if certain HTTP/1.0 caches calculate ages or expiration times wrong, maybe because their clocks are desynchronized. โฐ

Lowkey tea: many HTTP/1.0 cache implementations treat an Expires value that is less than or equal to the response Date value as the same thing as the no-cache Cache-Control response directive. ๐Ÿซ– If an HTTP/1.1 cache gets a response like that, and the response doesn't include a Cache-Control header field, it SHOULD consider the response non-cacheable to stay compatible with HTTP/1.0 servers. ๐Ÿค

Note: An origin server might want to use a newer cache control feature, like the private directive, on a network that still has older caches that don't understand it. ๐Ÿง“ The origin server will need to pair the new feature with an Expires field whose value is less than or equal to the Date value. That stops older caches from caching the response improperly. ๐Ÿ›‘

s-maxage

If a response includes an s-maxage directive, then for a shared cache (but NOT a private cache), the maximum age set by this directive overrides the maximum age set by either the max-age directive or the Expires header. ๐Ÿ’… The s-maxage directive also brings along the meaning of the proxy-revalidate directive (see section 14.9.4). That means the shared cache must not use the entry after it goes stale to answer a later request without first revalidating it with the origin server. ๐Ÿ” The s-maxage directive is always ignored by a private cache. ๐Ÿ™…โ€โ™€๏ธ

Heads up: most older caches that don't follow this spec don't implement any cache-control directives at all. ๐Ÿฆ• An origin server that wants a cache-control directive which restricts, but doesn't prevent, caching by an HTTP/1.1-compliant cache MAY take advantage of the rule that max-age overrides Expires, plus the fact that pre-HTTP/1.1-compliant caches don't look at max-age. ๐Ÿง 

Other directives let a user agent tweak the basic expiration mechanism. These directives MAY be specified on a request: ๐Ÿ“ฑ

  • max-age: The client is happy to accept a response whose age is no greater than the specified time in seconds. Unless max-stale is also included, the client is not willing to accept a stale response. ๐Ÿ™…
  • min-fresh: The client is happy to accept a response whose freshness lifetime is no less than its current age plus the specified time in seconds. In other words, the client wants a response that will still be fresh for at least that many seconds. โณ
  • max-stale: The client is willing to accept a response that has gone past its expiration time. If max-stale gets a value, the client will accept a response that is past its expiration time by no more than that many seconds. If no value is given to max-stale, the client will accept a stale response of any age. ๐Ÿฅด

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

A cache MAY be configured to return stale responses without validation, but only if this doesn't conflict with any "MUST"-level requirements about cache validation (e.g., a "must-revalidate" cache-control directive). ๐Ÿ™ƒ

If both the new request and the cached entry include max-age directives, the lesser of the two values is used to decide the freshness of the cached entry for that request. ๐Ÿ

14.9.4 Cache Revalidation and Reload Controls โœจ

Okay bestie, sometimes a user agent wants or needs to make a cache revalidate its entry with the origin server (not just with the next cache along the path), or to fully reload its entry from the origin server ๐Ÿ”„. End-to-end revalidation might be necessary if either the cache or the origin server 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 can be requested in two ways. If the client does not have its own local cached copy, we call it "unspecified end-to-end revalidation". If the client does have a local cached copy, 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. Field names MUST NOT be included with the no-cache directive in a request. The server MUST NOT use a cached copy when responding to such a request. Iconic behavior, no cap ๐Ÿ™…โ€โ™€๏ธ

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 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 does not include a cache-validating conditional. Instead, 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 ๐Ÿงš

max-age

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 might 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. Lowkey a big deal ๐Ÿ‘‘

However, the choice of validator might 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 can 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 can 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. ๐Ÿ™ˆ

only-if-cached

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 ๐Ÿ“ถ

must-revalidate

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.) This is the main character rule for caches ๐ŸŽฌ

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. Ngl this part is so important ๐Ÿ˜ญ๐Ÿซถ

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. > Be honest with the user every single time, okay? ๐Ÿšจ

proxy-revalidate

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 ๐ŸŽจ

no-transform

Implementors of intermediate caches (proxies) have found it useful to convert the media type of certain entity bodies. A non-transparent 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. Smart, right? ๐Ÿง 

Serious operational problems occur, however, when these transformations are 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. Not okay to mess with that ๐Ÿฉบ๐Ÿ”ฌ

Therefore, if a message 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, including the value of the entity-body itself. Hands off, literally ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–

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. It's giving clever design ๐Ÿฆ‹

This extension mechanism depends on an 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) could 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. Safe and sound ๐Ÿซถ

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 cacheability) 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. Main character energy for this header ๐Ÿ’…

The Connection header has the following grammar:

Connection = "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.

Message headers listed in the Connection header MUST NOT include end-to-end headers, such as Cache-Control. Don't put Cache-Control in there, it's a whole no ๐Ÿ™…โ€โ™€๏ธ

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. Bye bye connection ๐Ÿ‘‹๐Ÿฅน

HTTP/1.1 applications that do not support persistent connections MUST include the 'close' connection option in every message. ๐ŸŽ€

A system receiving an HTTP/1.0 (or lower-version) message that includes a Connection header MUST, for each connection-token in this field, remove and ignore any header field(s) from the message with the same name as the connection-token. This protects against mistaken forwarding of such header fields by pre-HTTP/1.1 proxies. See section 19.6.2. It's literally protecting the whole chain, iykyk ๐Ÿงš๐Ÿ’œ

14.11 Content-Encoding โœจ

Okay bestie, Content-Encoding is a modifier on the media-type ๐Ÿ’… When it shows up, its value tells you which extra content codings got applied to the entity-body, so you know exactly what decoding to do to get back to the media-type in the Content-Type header field ๐ŸŽ€ It's mainly there so a document can be compressed without losing the identity of its underlying media type. Iconic, honestly ๐Ÿฆ‹

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

Content codings are defined in section 3.5. Here's an example of how it looks:

Content-Encoding: gzip

The content-coding is a characteristic of the entity identified by the Request-URI. Typically the entity-body is stored with this encoding and only gets decoded before rendering or something similar ๐Ÿงš However, a non-transparent proxy MAY modify the content-coding if the new coding is known to be acceptable to the recipient, unless the "no-transform" cache-control directive is present in the message. Not the proxy messing with your stuff ๐Ÿ’€

If the content-coding of an entity is not "identity", then the response MUST include a Content-Encoding entity-header (section 14.11) that lists the non-identity content-coding(s) used. Lowkey a must-have ๐Ÿซถ

If the content-coding of an entity in a request message is not acceptable to the origin server, the server SHOULD respond with a status code of 415 (Unsupported Media Type). That's the server being picky, and that's valid ๐Ÿ’…

If multiple encodings have been applied to an entity, the content codings MUST be listed in the order in which they were applied. Order matters, bestie ๐ŸŒˆ Additional information about the encoding parameters MAY be provided by other entity-header fields not defined by this specification โœจ


14.12 Content-Language ๐ŸŒธ

The Content-Language entity-header field describes the natural language(s) of the intended audience for the enclosed entity. Quick heads up: that might not match every language used inside the entity-body ๐Ÿ‘€

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

Language tags are defined in section 3.10. The whole point of Content-Language is letting a user identify and tell apart entities based on their own preferred language ๐Ÿ’– So if the body is only meant for a Danish-literate audience, the field is:

Content-Language: da

If no Content-Language is specified, the default is that the content is intended for all language audiences. 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 ๐Ÿคทโ€โ™€๏ธ

Multiple languages MAY be listed for content that is intended for multiple audiences. For example, a rendition of the "Treaty of Waitangi," presented at the same time in the original Maori and English versions, would call for:

Content-Language: mi, en

BUT just because an entity has multiple languages in it doesn't mean it's for multiple linguistic audiences ๐Ÿ™ˆ Think about a beginner's language primer, like "A First Lesson in Latin." That's clearly for an English-literate audience, so the Content-Language would properly only include "en" ๐Ÿ“

Content-Language MAY be applied to any media type -- it is not limited to textual documents. Images and audio can have a language too, periodt ๐ŸŽ€


14.13 Content-Length ๐Ÿงš

The Content-Length entity-header field tells you the size of the entity-body, as a decimal number of OCTETs, that gets sent to the recipient. Or, if it's a HEAD method, the size the entity-body would have been if the request had been a GET ๐Ÿ‘‘

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

Here's an example:

Content-Length: 3495

Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the rules in section 4.4. That's the main move, unless section 4.4 says no ๐Ÿ’…

Any Content-Length greater than or equal to zero is a valid value. Section 4.4 explains how to figure out the length of a message-body if there's no Content-Length given ๐Ÿฆ‹

Heads up, the meaning of this field is really different from the MIME one ๐Ÿ˜ญ In MIME it's an optional field used within the "message/external-body" content-type. In HTTP, it SHOULD be sent whenever the message's length can be figured out before it gets transferred, unless section 4.4 prohibits it. Different vibes, same name ๐Ÿ’œ


14.14 Content-Location ๐ŸŒˆ

The Content-Location entity-header field MAY be used to supply the resource location for the entity enclosed in the message, when that entity can be reached from a location separate from the requested resource's URI. A server SHOULD provide a Content-Location for the variant that matches the response entity. Especially when a resource has multiple entities attached and each one has its own location to be accessed by, the server SHOULD provide a Content-Location for the particular variant that gets returned. Main character server energy ๐ŸŽ€

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

The value of Content-Location also defines the base URI for the entity โœจ

The Content-Location value is NOT a replacement for the original requested URI ๐Ÿ™…โ€โ™€๏ธ (lol, not caps, my bad, it's just a note). It's only a statement of where the resource for this particular entity lives at the time of the request. Future requests MAY specify the Content-Location URI as the request-URI if they want to identify the source of that particular entity ๐Ÿ’–

A cache cannot assume that an entity with a Content-Location different from the URI used to retrieve it can be used to answer later requests on that Content-Location URI. BUT the 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 the Request-URI ๐Ÿงญ

The meaning of the Content-Location header in PUT or POST requests is undefined. Servers are free to ignore it in those cases ๐Ÿคทโ€โ™€๏ธ


14.15 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 provide an end-to-end message integrity check (MIC) of the entity-body ๐Ÿ” (Quick note: a MIC is good for catching accidental changes to the entity-body in transit, but it's not proof against malicious attacks ๐Ÿ’€)

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 or client to work as an integrity check of the entity-body. Only origin servers or clients MAY generate the Content-MD5 header field. Proxies and gateways MUST NOT generate it, because that would defeat its whole purpose 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 on the content of the entity-body, including any content-coding that has been applied. It does NOT include any transfer-encoding applied to the message-body. If the message comes in with a transfer-encoding, that encoding MUST be removed before you check the Content-MD5 value against the received entity ๐Ÿงน

This means the digest is 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 so the digest can be computed for MIME composite media-types (for example multipart/* and message/rfc822). But this doesn't change how the digest is computed, as described in the paragraph above ๐ŸŒธ

There are a few consequences of this. The entity-body for composite types MAY contain many body-parts, and each one can have 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's assumed that the content of the body-part already has that encoding applied. The body-part then gets included in the Content-MD5 digest as is, meaning after the encoding was applied. The Transfer-Encoding header field is not allowed within body-parts ๐Ÿšซ

Conversion of all line breaks to CRLF MUST NOT be done before computing or checking the digest. The line break convention used in the text that's actually transmitted MUST be left unaltered when computing the digest. Don't touch the line breaks, bestie ๐Ÿ™

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 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's 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. Lots of nuance here, and honestly, I'm obsessed ๐Ÿงš๐Ÿ’œ

14.16 Content-Range โœจ

okay so Content-Range is the header that shows up when the server is sending just a piece of the entity-body ๐Ÿงฉ and it needs to say where that piece goes in the full thing. (Range units are defined in section 3.12, go read that if you're curious ๐Ÿค“)

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

content-range-spec      = byte-content-range-spec
byte-content-range-spec = bytes-unit SP
                          byte-range-resp-spec "/"
                          ( instance-length | "*" )

byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
                               | "*"
instance-length           = 1*DIGIT

The header SHOULD tell you the total length of the full entity-body ๐Ÿ“, unless that length is unknown or hard to figure out. The asterisk * just means "the instance-length isn't known yet" when the response got generated ๐Ÿคทโ€โ™€๏ธ

Now this is the part I'm obsessed with ๐Ÿ˜ญ Unlike byte-ranges-specifier values (see section 14.35.1), a byte-range-resp-spec MUST only specify ONE range, and it MUST contain absolute byte positions for both the first and last byte of that range. No vibes-based ranges, bestie ๐Ÿ’…

A byte-content-range-spec is invalid if its last-byte-pos is less than its first-byte-pos, or if its instance-length is less than or equal to its last-byte-pos. Yikes ๐Ÿ’€ The recipient of an invalid one MUST ignore it AND any content that came along with it.

A server sending a 416 (Requested range not satisfiable) response SHOULD include a Content-Range field with a byte-range-resp-spec of * ๐Ÿ™ˆ The instance-length tells you the current length of the selected resource. Meanwhile a 206 (Partial Content) response MUST NOT include a Content-Range field with a byte-range-resp-spec of *. Don't mix those up, periodt ๐Ÿซถ

Here are some examples, assuming the entity has 1234 bytes total ๐Ÿ“

  • 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 a message carries the content of a single range (like a response to a request for one range, or a request for a bunch of ranges that overlap with no holes), it gets sent with a Content-Range header AND a Content-Length header saying how many bytes actually got 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 a message carries multiple ranges (like a response to a request for several non-overlapping ranges), they get sent as a multipart message ๐Ÿง The multipart media type for this is "multipart/byteranges", as defined in appendix 19.2. See appendix 19.6.3 for a compatibility issue, it's a whole thing ๐Ÿ‘€

A response to a request for a single range MUST NOT be sent using the multipart/byteranges media type ๐Ÿšซ A response to a request for multiple ranges, whose result is a single range, MAY be sent as a multipart/byteranges media type with one part, so that one's allowed ๐ŸŒธ And a client that can't decode a multipart/byteranges message MUST NOT ask for multiple byte-ranges in a single request. Know your limits, bestie ๐Ÿซถ

When a client asks for multiple byte-ranges in one request, the server SHOULD send them back in the order they showed up in the request โœจ

If the server ignores a byte-range-spec because it's syntactically invalid, the server SHOULD treat the request as if the invalid Range header field never existed. (Usually that means it returns a 200 response with the full entity ๐Ÿฐ)

If the server gets a request (other than one with an If-Range request-header field) with an unsatisfiable Range request-header field, meaning every one of its byte-range-spec values has a first-byte-pos bigger than the current length of the selected resource, it SHOULD return a 416 (Requested range not satisfiable) response (section 10.4.17) ๐Ÿ™…โ€โ™€๏ธ

Note: clients cannot depend on servers to send a 416 (Requested range not satisfiable) response instead of a 200 (OK) response for an unsatisfiable Range request-header, since not all servers implement this request-header. ๐Ÿ’€ Servers are unreliable, we have to be ready for anything.

14.17 Content-Type ๐ŸŽ€

The Content-Type entity-header field tells the recipient what media type the entity-body is ๐Ÿ’– Or, if the method is HEAD, it tells you the media type that would've been sent if the request had been a GET. Iconic behaviour ๐Ÿ‘‘

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, go to section 7.2.1 ๐Ÿงš


14.18 Date ๐Ÿ•ฐ๏ธ

The Date general-header field shows the date and time the message was originated, with the same semantics as orig-date in RFC 822 ๐Ÿ“ฎ The field value is an HTTP-date (see section 3.3.1), and it MUST be sent in RFC 1123 [8]-date format. No other format, babe ๐Ÿ’…

Date  = "Date" ":" HTTP-date

Here's an example:

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

Origin servers MUST include a Date header field in all responses ๐Ÿ“… BUT there are some exceptions, lowkey:

  1. If the response status code is 100 (Continue) or 101 (Switching Protocols), the response MAY include a Date header field, totally up to the server ๐Ÿคทโ€โ™€๏ธ
  2. If the response status code is a server error, like 500 (Internal Server Error) or 503 (Service Unavailable), and it's inconvenient or impossible to generate a valid Date, then skip it ๐Ÿ’€
  3. If the server doesn't have a clock that can give a reasonable approximation of the current time, its responses MUST NOT include a Date header field. In that case, the rules in section 14.18.1 MUST be followed ๐Ÿ•ฐ๏ธ๐Ÿšซ

A received message that doesn't have a Date header field MUST get one assigned by the recipient if the message is going to be cached by that recipient, or gatewayed over a protocol that requires a Date ๐Ÿซถ An HTTP implementation without a clock MUST NOT cache responses without revalidating them on every use, no shortcuts โฐ And an HTTP cache, especially a shared cache, SHOULD use a mechanism like NTP [28] to sync its clock with a reliable external standard ๐ŸŒˆ

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 client without a clock MUST NOT send a Date header field in a request.

The HTTP-date in a Date header SHOULD NOT be a time after the message was generated ๐Ÿ™ˆ It SHOULD be the best available approximation of when the message was generated, unless the implementation has no way to get a reasonably accurate date and time. In theory, the date should be the moment just before the entity gets generated. In practice, though, it can be generated at any point during message origination without changing its semantic value ๐Ÿง

14.18.1 Clockless Origin Server Operation โณ

Some origin server implementations might not have a clock at all ๐Ÿ˜ญ An origin server without a clock MUST NOT assign Expires or Last-Modified values to a response, UNLESS those values were associated with the resource by a system or user that does have a reliable clock. It MAY assign an Expires value that's known, at or before server configuration time, to be in the past. This lets you do "pre-expiration" of responses without storing separate Expires values for each resource, which is honestly so smart ๐Ÿง โœจ


14.19 ETag ๐Ÿท๏ธ

The ETag response-header field gives the current value of the entity tag for the requested variant ๐Ÿ’œ The headers used with entity tags are described in sections 14.24, 14.26 and 14.44. The entity tag MAY be used for comparison with other entities from the same resource (see section 13.3.3) ๐Ÿฆ‹

ETag = "ETag" ":" entity-tag

Examples:

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

14.20 Expect ๐Ÿ™‹โ€โ™€๏ธ

The Expect request-header field is how the client says "hey, these particular server behaviours are required" ๐Ÿซถ

Expect       =  "Expect" ":" 1#expectation

expectation  =  "100-continue" | expectation-extension
expectation-extension =  token [ "=" ( token | quoted-string )
                         *expect-params ]
expect-params =  ";" token [ "=" ( token | quoted-string ) ]

A server that doesn't understand any of the expectation values in the Expect field, or can't comply with them, MUST respond with an appropriate error status ๐Ÿšจ The server MUST respond with a 417 (Expectation Failed) status if any of the expectations can't be met. If there are other problems with the request, it can send some other 4xx status instead ๐Ÿ™ƒ

This header field has extensible syntax so future stuff can be added ๐Ÿ”ฎ If a server gets a request with an Expect field that includes an expectation-extension it doesn't support, it MUST respond with a 417 (Expectation Failed) status.

Comparing expectation values is case-insensitive for unquoted tokens (including the 100-continue token), but it's case-sensitive for quoted-string expectation-extensions. Be careful with those quotes, bestie ๐Ÿ’…

The Expect mechanism is hop-by-hop ๐Ÿ” That means an HTTP/1.1 proxy MUST return a 417 (Expectation Failed) status if it gets a request with an expectation it can't meet. HOWEVER, the Expect request-header itself is end-to-end, so it MUST be forwarded if the request is forwarded ๐Ÿซถ

Lots of older HTTP/1.0 and HTTP/1.1 applications don't understand the Expect header, so keep that in mind ๐Ÿง“

See section 8.2.3 for how the 100 (continue) status is used โœจ


14.21 Expires โฐ

The Expires entity-header field gives the date and time after which the response is considered stale ๐Ÿฅ€ A stale cache entry usually can't be returned by a cache (whether it's a proxy cache or a user agent cache) unless it gets validated first with the origin server, 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 does NOT mean the original resource will change or cease to exist at, before, or after that time. Not the vibe, so don't assume it ๐Ÿ™…โ€โ™€๏ธ

The format is an absolute date and time, as defined by HTTP-date in section 3.3.1, and it MUST be in RFC 1123 date format:

Expires = "Expires" ":" HTTP-date

Here's an example of how it's used:

Expires: Thu, 01 Dec 1994 16:00:00 GMT
Note: if a response includes a Cache-Control field with the max-age directive (see section 14.9.3), that directive overrides the Expires field. Max-age wins, periodt ๐Ÿ‘‘

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

To mark a response as "already expired," an origin server sends an Expires date that is equal to the Date header value. (For the rules on expiration calculations, see section 13.2.4 ๐Ÿงฎ)

To mark a response as "never expires," an origin server sends 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, so don't get carried away ๐Ÿ™ˆ

The presence of an Expires header field with a date value in the future on a response that would otherwise be non-cacheable by default indicates that the response is cacheable, unless a Cache-Control header field (section 14.9) says otherwise ๐Ÿซง

14.22 From ๐Ÿ“ฌ

okay bestie, the From header is if given ๐Ÿ’Œ and when you do send it, it SHOULD contain an Internet e-mail address for the actual human who controls the requesting user agent. That address SHOULD be machine-usable, going by "mailbox" in RFC 822 [9] as updated by RFC 1123 [8]:

From   = "From" ":" mailbox

Here's an example:

From: webmaster@w3.org

This header MAY be used for logging and for spotting where invalid or unwanted requests are coming from ๐Ÿ•ต๏ธโ€โ™€๏ธ but it SHOULD NOT be used as a sketchy form of access protection, obviously ๐Ÿ™„. The whole point is that the request is happening on behalf of the person listed, and that person takes responsibility for whatever method got performed. Robot agents especially SHOULD include this header ๐Ÿค– so the person running the robot can be reached if something goes sideways on the other end. ๐Ÿซถ

The e-mail address here MAY be different from the Internet host that actually sent the request. Like, if a request goes through a proxy, the original issuer's address SHOULD be used ๐Ÿงš.

Big rule: the client SHOULD NOT send the From header without the user's approval, because it could clash with their privacy or their site's security policy ๐Ÿ”’. It's strongly recommended that the user can turn this field on or off, and change its value, at any time before a request goes out ๐Ÿ’….

14.23 Host ๐Ÿ 

The Host request-header tells the server which Internet host and port number the resource is being requested from, taken from the original URI the user gave or from the referring resource (usually an HTTP URL, see section 3.2.2 โœจ). The Host value MUST represent the naming authority of the origin server or gateway given by the original URL. Why does this matter? Because it lets the server tell apart URLs that look the same inside, like the root "/" of a server hosting many host names on one IP address ๐Ÿ‘‘.

Host = "Host" ":" host [ ":" port ] ; Section 3.2.2

A "host" with no trailing port info means the default port for the service (so "80" for an HTTP URL) ๐ŸŒธ. For example, a request to the origin server for <http://www.w3.org/pub/WWW/> would properly look like this:

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

Real talk, these are all MUST-level:

  • A client MUST include a Host header field in all HTTP/1.1 request messages ๐Ÿ˜ค.
  • If the requested URI doesn't include an Internet host name for the service, the Host header field MUST be given with an empty value ๐Ÿซฅ.
  • An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy ๐Ÿ“ฎ.
  • All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field ๐Ÿ’€.

For other Host requirements, check out sections 5.2 and 19.6.1.1 ๐Ÿ“š.

14.24 If-Match ๐Ÿ”

The If-Match request-header makes a method conditional. A client that already has one or more entities from the resource can check that one of them is still current by listing their entity tags in the If-Match header. Entity tags are defined in section 3.11 ๐Ÿท๏ธ. The whole vibe is efficient cache updates with as little transaction overhead as possible โœจ, and it also stops you from accidentally changing the wrong version of a resource on updating requests ๐Ÿ™…โ€โ™€๏ธ. As a special case, "*" 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 come back in the response to a similar GET request (one 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 didn't exist ๐Ÿฆ‹.

A server MUST use the strong comparison function (see section 13.3.3) 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 super useful when the client wants to stop an updating method, like PUT, from changing a resource that's been modified since the client last grabbed it ๐Ÿ™ˆ.

If the request would, without the If-Match header, end in anything other than a 2xx or 412 status, then the If-Match header MUST be ignored ๐Ÿซ .

Soooo, "If-Match: *" means the method SHOULD be performed if the representation picked by the origin server (or by a cache, maybe using the Vary mechanism, see section 14.44) exists, and it MUST NOT be performed if that representation doesn't exist ๐ŸŒˆ.

A request that's trying to update a resource (like a PUT) MAY include an If-Match header to signal that the method MUST NOT be applied if the entity matching the If-Match value (a single entity tag) is no longer a representation of that resource ๐Ÿ›‘. The user is basically saying "don't go through if this changed without me knowing" ๐Ÿฅน. Examples:

If-Match: "xyzzy"
If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-Match: *

Also, a request with both an If-Match header and either an If-None-Match or an If-Modified-Since header is undefined by this spec ๐Ÿคทโ€โ™€๏ธ.

14.25 If-Modified-Since โฐ

The If-Modified-Since request-header makes a method conditional: if the requested variant hasn't been modified since the time in this field, the server won't send an entity back. Instead it'll send a 304 (not modified) response with no message-body ๐Ÿ˜Œ.

If-Modified-Since = "If-Modified-Since" ":" HTTP-date

Here's 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 entity only if it's been modified since the date in that header. The algorithm for that includes these cases ๐Ÿงฎ:

  • a) If the request would normally end in anything other than a 200 (OK) status, or if the If-Modified-Since date is invalid, the response is exactly the same as a normal GET. A date 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 hasn't been modified since a valid If-Modified-Since date, the server SHOULD return a 304 (Not Modified) response ๐Ÿ’ค.

Same energy as before: the purpose is efficient cache updates with minimal transaction overhead ๐ŸŒท.

Note: The Range request-header changes what If-Modified-Since means. See section 14.35 for the full tea โ˜•.
Note: The server interprets If-Modified-Since times, and its clock might not be synced with the client's ๐Ÿ•ฐ๏ธ.
Note: When handling an If-Modified-Since header, some servers use an exact date comparison instead of a less-than check to decide whether to send a 304 (Not Modified) response. For the best results when sending If-Modified-Since for cache validation, clients are advised to use the exact date string from a previous Last-Modified header whenever possible ๐ŸŽฏ.
Note: If a client uses an arbitrary date in If-Modified-Since instead of one taken from the Last-Modified header for the same request, it should be aware that the server reads this date in its own understanding of time. The client should think about unsynchronized clocks and rounding problems from the different time encodings on each side ๐Ÿง . That includes race conditions if the document changed between the first request and the If-Modified-Since date of a later request, plus clock-skew problems if the date comes from the client's clock without being corrected to the server's clock. Corrections for different time bases between client and server are at best approximate, because of network latency ๐ŸŒ€.

Last thing: a request with both an If-Modified-Since header and either an If-Match or an If-Unmodified-Since header is undefined by this specification ๐Ÿซฃ.

14.26 If-None-Match โœจ

okay so the If-None-Match request-header field is what makes a request conditional ๐ŸŽ€ a client that already has one or more entities from a resource can check that none of them are current by listing their entity tags in this header. the whole point is letting caches update with barely any transaction overhead ๐Ÿ’… it also stops a method like PUT from accidentally overwriting a resource the client thinks doesn't exist ๐Ÿ™ˆ

as a special case, the value * matches any current entity of the resource ๐Ÿฆ‹

If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

so if any of the entity tags match the entity tag of the entity that would've come back in the response to a similar GET request (the one 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 ๐Ÿ˜ญ the only exception is when it's required to, because the resource's modification date doesn't match the one given in an If-Modified-Since header field in the request. instead, if the request method was GET or HEAD, the server SHOULD respond with a 304 (Not Modified) response, and include the cache-related header fields (especially ETag) from one of the entities that matched ๐Ÿงš for every other request method, the server MUST respond with a status of 412 (Precondition Failed) ๐Ÿ’€

see section 13.3.3 for the rules on figuring out whether two entity tags match ๐Ÿ” the weak comparison function can only be used with GET or HEAD requests ๐ŸŒธ

if none of the entity tags match, the server MAY perform the requested method as if the If-None-Match header field didn't exist ๐ŸŒˆ but it MUST also ignore any If-Modified-Since header field(s) in the request. so basically, if no entity tags match, the server MUST NOT return a 304 (Not Modified) response โœจ

if the request would otherwise result in anything other than a 2xx or 304 status without the If-None-Match header field, then the If-None-Match header MUST be ignored ๐Ÿ™…โ€โ™€๏ธ (check section 13.3.4 for how the server handles it when both If-Modified-Since and If-None-Match show up in the same request.)

the meaning of If-None-Match: * is that the method MUST NOT be performed if the representation selected by the origin server exists (or by a cache, possibly using the Vary mechanism, see section 14.44). and it SHOULD be performed if the representation doesn't exist ๐Ÿซถ this is super useful for stopping 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: *

the result of a request that has both an If-None-Match header field and either an If-Match or an If-Unmodified-Since header field is undefined by this spec ๐Ÿคทโ€โ™€๏ธ


14.27 If-Range ๐ŸŽ€

okay picture this: a client has a partial copy of an entity in its cache and wants the full up-to-date copy ๐Ÿ’– 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 changed, the client would have to make a second request just to grab the whole current entity-body ๐Ÿ˜ฉ

the If-Range header lets the client "short-circuit" that second request ๐Ÿฆ‹ informally, it means 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 tell a valid HTTP-date apart from any form of entity-tag by looking at no more than two characters, which is so clever ๐Ÿง ) the If-Range header SHOULD only be used together with a Range header, and MUST be ignored if the request doesn't include a Range header, or if the server doesn't support the sub-range operation ๐Ÿ™ˆ

if the entity tag 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 doesn't match, the server SHOULD return the entire entity using a 200 (OK) response ๐Ÿซถ


14.28 If-Unmodified-Since ๐Ÿ’…

the If-Unmodified-Since request-header field makes a method conditional ๐ŸŒธ if the requested resource hasn't been modified since the time given in this field, the server SHOULD perform the requested operation as if the If-Unmodified-Since header weren't there at all ๐Ÿฆ‹

if the requested variant HAS been modified since that 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 (meaning without the If-Unmodified-Since header) result in anything other than a 2xx or 412 status, the If-Unmodified-Since header SHOULD be ignored ๐Ÿ™…โ€โ™€๏ธ

if the specified date is invalid, the header is ignored ๐Ÿ—‘๏ธ

the result of a request that has both an If-Unmodified-Since header field and either an If-None-Match or an If-Modified-Since header field is undefined by this specification ๐Ÿคทโ€โ™€๏ธ


14.29 Last-Modified ๐ŸŒˆ

the Last-Modified entity-header field tells you the date and time the origin server believes the variant was last modified โฐ

Last-Modified  = "Last-Modified" ":" HTTP-date

an example of how it's used:

Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT

what this header means depends on the origin server's implementation and what the original resource actually is ๐Ÿงš for files, it might just be the file system's 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 ๐Ÿ—ƒ๏ธ and for virtual objects, it might be the last time the internal state changed ๐Ÿ‘ป

an origin server MUST NOT send a Last-Modified date that's later than the server's time of message origination ๐Ÿšซ if 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 for its response โฑ๏ธ this lets a recipient accurately judge the entity's modification time, especially if the entity changes right around when the response gets generated ๐ŸŽฏ

HTTP/1.1 servers SHOULD send Last-Modified whenever that's feasible ๐Ÿ’œ


14.30 Location ๐Ÿฆ‹

the Location response-header field redirects the recipient to a location other than the Request-URI, either to finish the request or to identify a new resource ๐Ÿ—บ๏ธ for 201 (Created) responses, the Location is the new resource that the request created ๐ŸŽ‰ for 3xx responses, the location SHOULD point to the server's preferred URI for automatic redirection to the resource ๐Ÿ”— the field value is a single absolute URI.

Location       = "Location" ":" absoluteURI

an example:

Location: http://www.w3.org/pub/WWW/People.html
Note: the Content-Location header field (section 14.14) is different from Location because 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 check section 13.10 for the cache requirements of some methods ๐Ÿ‘€

14.31 Max-Forwards ๐Ÿ”ฅ

the Max-Forwards request-header field gives you a way, together with the TRACE (section 9.8) and OPTIONS (section 9.2) methods, to limit how many proxies or gateways can forward the request to the next inbound server ๐Ÿ›‘ this is super handy when a client is trying to trace a request chain that seems to be failing or looping in the middle ๐Ÿ”„

Max-Forwards   = "Max-Forwards" ":" 1*DIGIT

the Max-Forwards value is a decimal integer that tells you how many more times this request message can be forwarded ๐Ÿ”ข

each proxy or gateway that receives a TRACE or OPTIONS request with a Max-Forwards header field MUST check and update its value before forwarding the request ๐Ÿงพ if the received value is zero (0), the recipient MUST NOT forward the request, and instead MUST respond as the final recipient ๐Ÿ›ฌ if the received Max-Forwards value is greater than zero, then the forwarded message MUST contain an updated Max-Forwards field with a value decremented by one (1) โž–

the Max-Forwards header field MAY be ignored for all other methods defined by this specification, and for any extension methods that don't explicitly refer to it as part of their method definition ๐Ÿ™ƒ


14.32 Pragma ๐ŸŒธ

the Pragma general-header field carries implementation-specific directives that might apply to any recipient along the request/response chain ๐Ÿงƒ all pragma directives specify optional behavior from the protocol's point of view, although some systems MAY require that behavior to 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 already 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 backward compatibility with HTTP/1.0 ๐Ÿ•ฐ๏ธ clients SHOULD include both header fields when they send a no-cache request 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, no matter how significant they are to that application ๐ŸŽ€ that's because the directives might apply to all recipients along the request/response chain ๐Ÿ”— you can't specify a pragma for one specific recipient, but any pragma directive that isn't relevant to a recipient SHOULD be ignored by that recipient ๐Ÿ™ˆ

HTTP/1.1 caches SHOULD treat Pragma: no-cache as if the client had sent Cache-Control: no-cache ๐Ÿ’œ and no new Pragma directives will be defined in HTTP ๐Ÿ›‘

Note: because the meaning of Pragma: no-cache as a response header field isn't actually specified, it doesn't give you a reliable replacement for Cache-Control: no-cache in a response

14.33 Proxy-Authenticate โœจ

okay bestie, so the Proxy-Authenticate response header MUST be included in a 407 (Proxy Authentication Required) response ๐Ÿซถ. Its value is a challenge that spells out the auth scheme and params the proxy wants for this Request-URI ๐Ÿ’…

Proxy-Authenticate  = "Proxy-Authenticate" ":" 1#challenge

The whole HTTP access auth process is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43] ๐Ÿ“š. Unlike WWW-Authenticate, this one only applies to the current connection and SHOULD NOT be passed on to downstream clients ๐Ÿ™…โ€โ™€๏ธ. BUT an intermediate proxy might need its own creds, so it asks the downstream client for them, and in some situations that looks exactly like the proxy is forwarding Proxy-Authenticate ๐Ÿ‘€๐Ÿ”ฅ

14.34 Proxy-Authorization ๐Ÿ”

the Proxy-Authorization request header lets the client identify itself (or its user) to a proxy that requires authentication ๐ŸŽ€. Its value is credentials with the auth info of the user agent for the proxy and/or the realm of the resource being requested โœจ

Proxy-Authorization     = "Proxy-Authorization" ":" credentials

The HTTP access auth process is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43]. Unlike Authorization, this header only applies to the next outbound proxy that demanded auth through the Proxy-Authenticate field ๐Ÿฆ‹. When proxies are chained, the first outbound proxy that was expecting credentials is the one that consumes the Proxy-Authorization header ๐Ÿ’œ. A proxy MAY relay the credentials from the client request to the next proxy, but only if that's how the proxies cooperatively authenticate a given request ๐Ÿงš

14.35 Range ๐ŸŒˆ

14.35.1 Byte Ranges

okay so since every HTTP entity shows up in messages as a sequence of bytes, byte ranges make sense for any HTTP entity ๐Ÿ’–. (Not every client and server has to support byte-range ops tho ๐Ÿ™ˆ)

Byte range specs apply to the sequence of bytes in the entity-body, which isn't necessarily the same as the message-body ๐ŸŒธ

A byte range operation MAY specify a single range of bytes, or a set of ranges within one 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, so the positions are inclusive. Byte offsets start at zero ๐Ÿงฎ

If last-byte-pos is present, it MUST be greater than or equal to the first-byte-pos in that byte-range-spec, or that spec is syntactically invalid ๐Ÿšซ. If a recipient gets a byte-range-set with one or more syntactically invalid byte-range-spec values, it MUST ignore the header field that includes that byte-range-set ๐Ÿ’€

If last-byte-pos is absent, or if it's greater than or equal to the current length of the entity-body, last-byte-pos is taken to be one less than the current length of the entity-body in bytes ๐ŸŒท

by picking its last-byte-pos, a client can limit how many bytes it gets back without knowing the size of the entity ๐Ÿ‘‘
suffix-byte-range-spec = "-" suffix-length
suffix-length = 1*DIGIT

a suffix-byte-range-spec gives you the suffix of the entity-body, with a length from the suffix-length value. (So this form asks for the last N bytes of an entity-body ๐Ÿซถ) If the entity is shorter than the suffix-length, the whole entity-body gets used โœจ

If a syntactically valid byte-range-set has at least one byte-range-spec whose first-byte-pos is less than the current length of the entity-body, or at least one suffix-byte-range-spec with a non-zero suffix-length, then the byte-range-set is satisfiable ๐Ÿฅณ. Otherwise it's unsatisfiable. If it's unsatisfiable, the server SHOULD return a response with a status of 416 (Requested range not satisfiable) ๐Ÿ˜ญ. Otherwise, the server SHOULD return a response with a status of 206 (Partial Content) containing the satisfiable ranges of the entity-body ๐ŸŽ‰

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.35.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, using 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 ought to support byte ranges when possible, since Range helps with efficient recovery from partially failed transfers, and with efficient partial retrieval of large entities ๐Ÿ’œ

If the server supports the Range header and the specified range or ranges are appropriate for the entity:

  • 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) ๐ŸŒˆ
  • 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 does NOT affect the 304 (Not Modified) response returned when the conditional is false ๐Ÿ™ˆ

Sometimes it's more fitting to use the If-Range header (see section 14.27) alongside the Range header ๐Ÿงš

If a proxy that supports ranges gets a Range request, forwards it 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 fits its cache allocation policies ๐Ÿ—‚๏ธ

14.36 Referer ๐Ÿ”—

The Referer[sic] request header lets the client tell the server, for the server's benefit, the address (URI) of the resource the Request-URI was obtained from (the "referrer", even though the header field is misspelled ๐Ÿ™ƒ). It lets a server build lists of back-links to resources for interest, logging, optimized caching, etc. It also helps trace obsolete or mistyped links for maintenance ๐Ÿ› ๏ธ. The Referer field MUST NOT be sent if the Request-URI came from a source that doesn't have its own URI, like input from the user's keyboard โŒจ๏ธ

Referer        = "Referer" ":" ( absoluteURI | relativeURI )

Example:

Referer: http://www.w3.org/hypertext/DataSources/Overview.html

If the field value is a relative URI, it SHOULD be interpreted relative to the Request-URI. The URI MUST NOT include a fragment ๐Ÿšซ. See section 15.1.3 for security considerations ๐Ÿ”

14.37 Retry-After โฐ

The Retry-After response header can go with a 503 (Service Unavailable) response to show how long the service is expected to be unavailable to the requesting client ๐Ÿ˜ฉ. It MAY also be used with any 3xx (Redirection) response to show the minimum time the user-agent is asked to wait before issuing the redirected request ๐Ÿง. Its value can be an HTTP-date or an integer number of seconds (in decimal) after the time of the response ๐ŸŒธ

Retry-After  = "Retry-After" ":" ( HTTP-date | delta-seconds )

Two examples of how it's used:

Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120

In the latter example, the delay is 2 minutes โณโœจ

14.38 Server ๐Ÿ–ฅ๏ธ

The Server response header has 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 ๐Ÿ‘‘

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.45) ๐Ÿฆ‹

Note: revealing the specific software version of the server might make the server machine more vulnerable to attacks against software known to contain security holes ๐Ÿ˜ญ๐Ÿšจ Server implementors are encouraged to make this field a configurable option ๐Ÿซถ

14.39 TE โœจ

okay bestie, the TE request-header field is how a client tells the server which extension transfer-codings it's willing to accept in the response, and whether it's cool with trailer fields in a chunked transfer-coding ๐ŸŽ€ Its value can be the keyword "trailers", a comma-separated list of extension transfer-coding names, or both, and each name can come with optional accept parameters (see section 3.6) ๐Ÿ’…

TE        = "TE" ":" #( t-codings )
t-codings = "trailers" | ( transfer-extension [ accept-params ] )

So "trailers" means the client will take trailer fields in a chunked transfer-coding (section 3.6.1) ๐Ÿฆ‹ It's reserved for transfer-coding use even though it isn't a transfer-coding itself, which is very "it's complicated" of it ๐Ÿ™ˆ

Some examples, because we love a good example ๐Ÿ“

TE: deflate
TE:
TE: trailers, deflate;q=0.5

The TE header field only applies to the immediate connection, so the keyword MUST be supplied within a Connection header field (section 14.10) whenever TE is present in an HTTP/1.1 message. Not optional, bestie ๐Ÿ‘‘

A server checks whether a transfer-coding is acceptable under a TE field using these rules:

  1. The "chunked" transfer-coding is always acceptable ๐ŸŒธ If the keyword "trailers" is listed, the client is saying it's willing to accept trailer fields in the chunked response for itself AND any downstream clients too. So, if it's there, the client is basically claiming that either every downstream client is fine with trailer fields in the forwarded response, or that it'll buffer the response for the downstream recipients itself ๐Ÿ˜ญ

Note: HTTP/1.1 does not define any means to limit the size of a chunked response such that a client can be assured of buffering the entire response.

  1. If the transfer-coding being tested is one of the transfer-codings listed in the TE field, it's acceptable UNLESS it comes with a qvalue of 0 ๐Ÿ’€ (As defined in section 3.9, a qvalue of 0 means "not acceptable." Iconic behavior, honestly โœจ)
  2. If multiple transfer-codings are acceptable, the one with the highest non-zero qvalue wins ๐Ÿ† The "chunked" transfer-coding always has a qvalue of 1, so it's always on top ๐Ÿ‘‘

If the TE field-value is empty, or there's no TE field at all, the only transfer-coding is "chunked" ๐Ÿงš And a message with no transfer-coding is always acceptable, no drama ๐Ÿ’–


14.40 Trailer ๐ŸŒˆ

The Trailer general field value says that the given set of header fields is present in the trailer of a message encoded with chunked transfer-coding ๐ŸŽ€

Trailer  = "Trailer" ":" 1#field-name

An HTTP/1.1 message SHOULD include a Trailer header field when it uses chunked transfer-coding with a non-empty trailer. This is lowkey essential, because it lets the recipient know which header fields to expect in the trailer ๐Ÿซถ

If there's no Trailer header field, the trailer SHOULD NOT include any header fields ๐Ÿ™…โ€โ™€๏ธ Check section 3.6.1 for the restrictions on trailer fields in a "chunked" transfer-coding, periodt ๐Ÿ’…

Message header fields listed in the Trailer header field MUST NOT include the following header fields:

  • Transfer-Encoding
  • Content-Length
  • Trailer

Not allowed, not ever ๐Ÿ’€


14.41 Transfer-Encoding ๐Ÿฆ‹

The Transfer-Encoding general-header field indicates what (if any) type of transformation has been applied to the message body so it can be transferred safely between sender and recipient โœจ Here's the tea: this is different from content-coding, 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. Here's an example:

Transfer-Encoding: chunked

If multiple encodings have been applied to an entity, the transfer-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 ๐ŸŒธ

Heads up though, many older HTTP/1.0 applications don't understand the Transfer-Encoding header at all ๐Ÿ™ˆ


14.42 Upgrade ๐Ÿš€

The Upgrade general-header lets the client specify what additional communication protocols it supports and would like to use IF the server finds it appropriate to switch ๐Ÿฆ‹ The server MUST use the Upgrade header field within a 101 (Switching Protocols) response to indicate which protocol(s) are being switched. Non-negotiable, bestie ๐Ÿ‘‘

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'd like to use another protocol, like a later HTTP version with a higher major version number, even though the current request is being made over HTTP/1.1 ๐Ÿ’– This makes the transition between incompatible protocols way smoother, since the client can start the request in the more commonly supported protocol while still telling the server it'd prefer a "better" protocol if one's available. ("Better" is decided by the server, possibly based on the method and/or the resource being requested, so the server's the one with the final say ๐Ÿ‘‘)

Upgrade only applies to switching application-layer protocols on the existing transport-layer connection โœจ It CANNOT be used to insist on a protocol change. The server's acceptance and use of it is optional ๐Ÿ™ˆ The capabilities and nature of the application-layer communication after the switch depend entirely on the new protocol chosen. BUT, the first action after changing protocols MUST be a response to the initial HTTP request that contained 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 ๐ŸŒˆ

Upgrade also cannot be used to switch to a protocol on a different connection. For that, a 301, 302, 303, or 305 redirection response is the better move ๐Ÿฆ‹

This specification only defines the protocol name "HTTP" for the family of Hypertext Transfer Protocols, following the HTTP version rules of section 3.1 and future updates to this spec ๐Ÿ’œ Any token can be used as a protocol name, but it'll only be useful if both the client and server associate that name with the same protocol. Communication, bestie ๐ŸŽ€


14.43 User-Agent ๐ŸŒธ

The User-Agent request-header field has info about the user agent that sent 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 that identify the agent and any subproducts that make up a significant part of it. By convention, the product tokens are listed in order of how significant they are for identifying the application ๐Ÿ“

User-Agent     = "User-Agent" ":" 1*( product | comment )

Example:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

14.44 Vary ๐Ÿ’œ

The Vary field value lists the set of request-header fields that fully determines, while the response is fresh, whether a cache is allowed to use the response to answer a later request without revalidation ๐Ÿฆ‹ For uncacheable or stale responses, the Vary field value tells the user agent which criteria were used to select the representation ๐ŸŒˆ A Vary value of "*" means a cache can't work out from a later request's headers whether this response is the right representation, so it's a whole mood ๐Ÿ™ˆ See section 13.6 for how caches use the Vary header field.

Vary  = "Vary" ":" ( "*" | 1#field-name )

An HTTP/1.1 server SHOULD include a Vary header field with any cacheable response that's subject to server-driven negotiation โœจ This lets a cache properly interpret future requests on that resource, and tells the user agent that negotiation is happening on it ๐Ÿ’– A server MAY include a Vary header field with a non-cacheable response that's subject to server-driven negotiation too, since it can give the user agent useful info about the dimensions the response varies over at that moment ๐Ÿซถ

A Vary field value that's a list of field-names means the representation was picked by 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 field names, for as long as the response is fresh ๐Ÿ‘‘

The field-names don't have to be standard request-header fields defined by this spec, and field names are case-insensitive ๐ŸŒธ

A Vary value of "" means that unspecified parameters, not limited to request-headers (like the client's network address), play a role in choosing the representation ๐Ÿงš The "" value MUST NOT be generated by a proxy server. Only an origin server can generate it ๐Ÿ’…

14.45. Via ๐Ÿฆ‹

okay bestie, the Via header is literally a trail of breadcrumbs ๐Ÿžโœจ. Gateways and proxies MUST use it to show which intermediate protocols and recipients sat between the user agent and the server on requests, and between the origin server and the client on responses. It's the HTTP cousin of the "Received" field from RFC 822 [9], and it's for three things: tracking where messages got forwarded, avoiding request loops, and figuring out the protocol capabilities of every sender along the chain ๐Ÿ’….

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 is the protocol version the message arrived on at each segment of the chain. It gets tacked onto the Via value when the message is forwarded, so the upstream apps' protocol 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 (and optional port) of the recipient that forwarded the message ๐ŸŽ€. But if the real host is sensitive info, it MAY be swapped out for a pseudonym ๐Ÿ™ˆ. 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 end result is ordered by the sequence of forwarding apps ๐Ÿ‘‘.

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 the 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 then forwards it to the origin server at www.ics.uci.edu. The request that www.ics.uci.edu receives would have this Via header ๐Ÿฆ‹:

Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)

Proxies and gateways acting 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 be propagated if it's explicitly enabled. If it isn't 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 requirements about hiding internal structures, a proxy MAY combine an ordered subsequence of Via entries that have identical received-protocol values into one single entry. For example:

Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

could be collapsed to

Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

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 ๐Ÿšซ.


14.46. Warning โš ๏ธ

The Warning header carries extra info about the status or transformation of a message that might not otherwise show up in the message itself. It's usually there to flag a possible loss of semantic transparency from caching or from transformations applied to the entity body ๐Ÿ‘€.

Warning headers get sent with responses, using this grammar:

Warning    = "Warning" ":" 1#warning-value

warning-value = warn-code SP warn-agent SP warn-text
                                             [SP warn-date]

warn-code  = 3DIGIT
warn-agent = ( host [ ":" port ] ) | pseudonym
                ; the name or pseudonym of the server adding
                ; the Warning header, for use in debugging
warn-text  = quoted-string
warn-date  = <"> HTTP-date <">

A response MAY carry more than one Warning header ๐Ÿ’œ.

The warn-text SHOULD be in a natural language and character set that's most likely to be understood by the human user receiving the response ๐ŸŒธ. That choice MAY be based on any available knowledge, like where the cache or user is, the Accept-Language field in a request, the Content-Language field in a response, and so on. 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 2047 [14] ๐Ÿงพ.

Warning headers can generally go on any message, but some warn-codes are specific to caches and can only go on response messages. New Warning headers SHOULD be added after any existing ones. A cache MUST NOT delete any Warning header it received with a message. However, 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 ought to tell the user as many of them as it can, in the order they appear in the response. If it's not possible to inform the user of all of them, 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 ๐Ÿ’….

Requirements for how caches behave with respect to Warnings are stated in section 13.1.2 ๐Ÿง .

Here's the list of the warn-codes defined right now. Each one has a recommended English warn-text and a description of what it means โœจ.

  • 110 Response is stale: MUST be included whenever the returned response is stale.
  • 111 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.
  • 112 Disconnected operation: SHOULD be included if the cache is intentionally disconnected from the rest of the network for a period of time.
  • 113 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.
  • 199 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, besides presenting the warning to the user.
  • 214 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, or the entity-body of the response, unless this Warning code already appears in the response.
  • 299 Miscellaneous persistent 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.

If an implementation sends a message with one or more Warning headers whose version is HTTP/1.0 or lower, then the sender MUST include in each warning-value a warn-date that matches the date in the response ๐Ÿ“….

If an implementation receives a message with a warning-value that includes a warn-date, and that warn-date is different from the Date value in the response, then that warning-value MUST be deleted from the message before storing, forwarding, or using it. (This prevents bad consequences of naive caching of Warning header fields ๐Ÿ™….) If all of the warning-values get deleted for this reason, the Warning header MUST be deleted as well.


14.47. WWW-Authenticate ๐Ÿ”

The WWW-Authenticate response-header MUST be included in 401 (Unauthorized) response messages. Its value is at least one challenge that indicates the authentication scheme(s) and parameters that apply to the Request-URI ๐Ÿ—๏ธ.

WWW-Authenticate  = "WWW-Authenticate" ":" 1#challenge

The HTTP access authentication process is described in "HTTP Authentication: Basic and Digest Access Authentication" [43]. User agents are advised to be extra careful when parsing the WWW-Authenticate value ๐Ÿง. It might contain more than one challenge, or more than one WWW-Authenticate header might be provided, and the contents of a challenge can themselves contain a comma-separated list of authentication parameters.


15. Security Considerations ๐Ÿ”ฅ

This section is here to inform app developers, info providers, and users about the security limitations of HTTP/1.1 as described by this document. It doesn't include definitive solutions to the problems revealed, though it does make some suggestions for reducing security risks ๐Ÿ›ก๏ธ.

15.1. Personal Information ๐Ÿซฃ

HTTP clients are often privy to huge amounts of personal information (e.g. the user's name, location, mail address, passwords, encryption keys, etc.), and they SHOULD be very careful to prevent unintentional leakage of this information via the HTTP protocol to other sources ๐Ÿšจ. We very strongly recommend that a convenient interface be provided so the user can control dissemination of such information, and that designers and implementors be particularly careful in this area. History shows that errors here often create serious security and/or privacy problems and generate highly adverse publicity for the implementor's company ๐Ÿ’€.

15.1.1. Abuse of Server Log Information ๐Ÿ•ต๏ธ

A server is in the position to save personal data about a user's requests, which might identify their reading patterns or subjects of interest. This info is clearly confidential in nature, and its handling can be constrained by law in certain countries ๐ŸŒ. People using the HTTP protocol to provide data are responsible for making sure such material isn't distributed without the permission of any individuals who are identifiable by the published results ๐Ÿซถ.

15.1.2. Transfer of Sensitive Information โœจ

Okay so bestie, HTTP is a generic data transfer protocol, which means it literally cannot regulate what's inside the data it moves ๐Ÿ’€. There's also no way to know ahead of time how sensitive a piece of info is inside any given request. So applications SHOULD give the info provider as much control over it as possible ๐Ÿซถ. Four header fields deserve special mention here: Server, Via, Referer and From ๐Ÿฆ‹.

Revealing the exact software version of the server could make the server machine more vulnerable to attacks on software that's known to have security holes ๐Ÿ˜ญ. Implementors 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 header lets people study reading patterns and draw reverse links ๐Ÿ‘€. It can be super useful, but its power can be abused if user details aren't separated from the info in the Referer. Even when the personal info has been removed, the Referer header might still reveal a private document's URI, and publishing that would be inappropriate ๐Ÿ™ˆ.

The info sent in the From field might clash with the user's privacy interests or their site's security policy ๐Ÿ”. So it SHOULD NOT be transmitted unless the user can disable, enable, and modify the contents of the field. The user MUST be able to set the contents of this field within a user preference or application defaults configuration.

We suggest, though do not require, that a convenient toggle interface be provided so the user can enable or disable sending From and Referer info ๐ŸŽ€.

The User-Agent (section 14.43) or Server (section 14.38) header fields can sometimes be used to figure out that a specific client or server has a particular security hole that might get exploited ๐Ÿ’€. Unfortunately, that same info is often used for other valuable purposes, and HTTP doesn't currently have a better mechanism for them ๐Ÿ˜ญ.

15.1.3. Encoding Sensitive Information in URI's ๐ŸŒธ

Because the source of a link might be private info, or might reveal an otherwise private info 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 or anonymously, which would enable or disable sending Referer and From info respectively ๐ŸŒˆ.

Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol ๐Ÿ”’.

Authors of services that use the HTTP protocol SHOULD NOT use GET based forms for submitting sensitive data ๐Ÿšซ, because that causes the data to be encoded in the Request-URI. Many existing servers, proxies, and user agents log the request URI somewhere it might be visible to third parties ๐Ÿ‘€. Servers can use POST-based form submission instead

15.1.4. 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 in particular can reveal info the user would consider private, because understanding particular languages is often strongly correlated with membership of a particular ethnic group ๐Ÿ˜ญ. User agents that offer an option to configure the contents of an Accept-Language header to be sent in every request are strongly encouraged to have that configuration process include a message that makes the user aware of the privacy loss involved ๐Ÿ’œ.

One way to limit the privacy loss is for a user agent to leave out Accept-Language headers by default. It can then detect, by looking for any Vary response-header fields generated by the server, that sending them could improve the quality of service, and ask the user whether to start sending them to that server ๐Ÿ“.

Elaborate, user-customized accept header fields sent in every request can be used by servers as pretty reliable, long-lived user identifiers, especially if they include quality values ๐Ÿ•ต๏ธ. Those identifiers would let content providers do click-trail tracking, and let collaborating content providers match cross-server click-trails or form submissions of individual users ๐Ÿ˜ณ. For lots of users not behind a proxy, the network address of the host running the user agent will also work as a long-lived user identifier ๐ŸŒ. In environments where proxies are used to enhance privacy, user agents ought to be conservative about offering accept header configuration options to end users ๐Ÿซฃ. As an extreme privacy measure, proxies could filter the accept headers in relayed requests โœจ. General purpose user agents that offer a high degree of header configurability SHOULD warn users about the loss of privacy that can be involved ๐Ÿ”ฅ.


15.2. Attacks Based On File and Path Names ๐Ÿ—‚๏ธ

Implementations of HTTP origin servers SHOULD be careful to restrict the documents returned by HTTP requests to only the ones the server administrators intended ๐Ÿ’…. If an HTTP server translates HTTP URIs directly into file system calls, the server MUST take special care not to serve files that weren't meant to be delivered to HTTP clients ๐Ÿšจ. For example, UNIX, Microsoft Windows, and other operating systems use ".." as a path component to mean a directory level above the current one ๐Ÿ™ˆ. On a system like that, an HTTP server MUST disallow any such construct in the Request-URI if it would otherwise allow access to a resource outside those intended to be accessible via the HTTP server. Similarly, files meant only for internal reference by the server (such as access control files, configuration files, and script code) MUST be protected from inappropriate retrieval, since they might contain sensitive information ๐Ÿ˜ญ. Experience has shown that minor bugs in such HTTP server implementations have turned into security risks ๐Ÿ’€.


15.3. DNS Spoofing ๐ŸŽญ

Clients using HTTP rely heavily on the Domain Name Service, so they're generally prone to security attacks based on deliberate mis-association of IP addresses and DNS names ๐Ÿ˜ฌ. Clients need to be cautious about assuming that an IP number/DNS name association is still valid ๐Ÿง.

In particular, HTTP clients SHOULD rely on their name resolver to confirm an IP number/DNS name association, instead of caching the results of previous host name lookups ๐Ÿ”. Many platforms can already cache host name lookups locally when appropriate, and they SHOULD be configured to do so โญ. It's only proper for these lookups to be cached, however, when the TTL (Time To Live) info reported by 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 HTTP clients don't follow this rule, they could get spoofed when a previously accessed server's IP address changes ๐Ÿ˜ฑ. Since network renumbering is expected to become more and more common [24], the chance of this attack will grow. Following this requirement cuts down on this potential security vulnerability ๐Ÿ›ก๏ธ.

This requirement also improves load-balancing behavior for clients using replicated servers with the same DNS name, and it lowers the odds of a user failing to access sites that use that strategy ๐ŸŽ€.


15.4. Location Headers and Spoofing ๐Ÿ“

If a single server supports multiple organizations that don't trust each other, then it MUST check the values of Location and Content-Location headers in responses generated under control of those organizations ๐Ÿ•ต๏ธ. It needs to make sure they don't try to invalidate resources they have no authority over ๐Ÿšซ.


15.5. Content-Disposition Issues ๐Ÿ“„

RFC 1806 [35], which the often implemented Content-Disposition header in HTTP (see section 19.5.1) is derived from, has a bunch of very serious security considerations ๐Ÿ˜ฌ. Content-Disposition isn't part of the HTTP standard, but since it's widely implemented, we're documenting its use and risks for implementors ๐Ÿ“š. See RFC 2183 [49] (which updates RFC 1806) for details ๐Ÿ”Ž.


15.6. Authentication Credentials and Idle Clients ๐Ÿ”‘

Existing HTTP clients and user agents typically keep authentication info indefinitely ๐Ÿ˜ณ. HTTP/1.1. doesn't give a server a method to tell clients to discard these cached credentials. This is a significant defect that needs further extensions to HTTP ๐Ÿ’€. Here are some situations where credential caching can mess with the application's security model, though the list isn't limited to these ๐Ÿ‘‡:

  • Clients that have been idle for a long time, after which the server might want the client to reprompt the user for credentials โฐ.
  • Applications that include a session termination indication (such as a logout' or commit' button on a page) after which the server side of the application "knows" there's no further reason for the client to keep the credentials ๐Ÿ™…โ€โ™€๏ธ.

This is currently under separate study ๐Ÿงช. There are a number of work-arounds for parts of this problem, and we encourage using password protection in screen savers, idle time-outs, and other methods that reduce the security problems inherent in this issue ๐Ÿซถ. In particular, user agents that cache credentials are encouraged to provide an easy-to-reach mechanism for discarding cached credentials under user control ๐Ÿ’….

15.7 Proxies and Caching โœจ

Okay bestie, proxies are literally men-in-the-middle by design ๐Ÿ˜ญ, which makes them a juicy target for man-in-the-middle attacks ๐Ÿ™ˆ. If the machine a proxy runs on gets compromised, it's a whole disaster. Proxies can see security-related info, personal info about users and organizations, and proprietary info belonging to users and content providers ๐Ÿ’€. A compromised proxy, or one set up without thinking about security and privacy, could be used for a wide range of potential attacks ๐Ÿ”ฅ.

Proxy operators should protect the systems their proxies run on, the same way they'd protect any system that holds or carries sensitive info ๐Ÿซถ. Log info collected at proxies often has highly sensitive personal info and/or info about organizations, so it needs to be carefully guarded, with guidelines for its use developed and followed (Section 15.1.1). Main character energy means treating those logs like gold ๐Ÿ‘‘.

Caching proxies add extra vulnerabilities ๐Ÿงบ, since the cache is an attractive target for malicious exploitation. Cache contents stick around after an HTTP request is done, so an attack on the cache can reveal info long after a user thinks it's been removed from the network ๐Ÿ‘€. So cache contents should be protected as sensitive information.

Proxy implementors should consider the privacy and security implications of their design and coding decisions, and of the configuration options they give proxy operators (especially the default configuration) ๐Ÿ’….

Users of a proxy need to be aware that they're no more trustworthy than the people who run the proxy ๐Ÿ˜ค. HTTP itself can't solve this one.

The judicious use of cryptography, when appropriate, may suffice to protect against a broad range of security and privacy attacks ๐Ÿ”. That cryptography is beyond the scope of the HTTP/1.1 specification.

15.7.1 Denial of Service Attacks on Proxies

They exist. They are hard to defend against. Research continues. Beware. ๐Ÿ’€๐ŸŒˆ


16 Acknowledgments โœจ

This specification makes heavy use of the augmented BNF and generic constructs defined by David H. Crocker for RFC 822 [9]. Similarly, it reuses many of the definitions provided by Nathaniel Borenstein and Ned Freed for MIME [7]. We hope that including them here helps reduce past confusion over the relationship between HTTP and Internet mail message formats ๐Ÿ’Œ.

The HTTP protocol has evolved considerably over the years ๐ŸŒธ. It has benefited from a large and active developer community (the many people who have participated on the www-talk mailing list), and that community has been most responsible for the success of HTTP and of the World-Wide Web in general ๐Ÿซถ. 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 special recognition for their efforts in defining early aspects of the protocol ๐Ÿ‘‘.

This document has benefited greatly from the comments of everyone participating in the HTTP-WG. In addition to those already mentioned, the following individuals have contributed to this specification ๐Ÿงš:

    Gary Adams                  Ross Patterson
    Harald Tveit Alvestrand     Albert Lunde
    Keith Ball                  John C. Mallery
    Brian Behlendorf            Jean-Philippe Martin-Flatin
    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               Josh Cohen

Much of the content and presentation of the caching design is thanks to suggestions and comments from individuals including Shel Kaphan, Paul Leach, Koen Holtman, David Morris, and Larry Masinter ๐Ÿ“.

Most of the specification of ranges is based on work originally done by Ari Luotonen and John Franks, with additional input from Steve Zilles ๐ŸŽ€.

Thanks to the "cave men" of Palo Alto. You know who you are ๐Ÿฆ‹.

Jim Gettys (the current editor of this document) wishes particularly to thank Roy Fielding, the previous editor of this document, along with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, and Larry Masinter for their help โœจ. And thanks go particularly to Jeff Mogul and Scott Lawrence for performing the "MUST/MAY/SHOULD" audit ๐Ÿ™Œ.

The Apache Group, Anselm Baird-Smith, author of Jigsaw, and Henrik Frystyk implemented RFC 2068 early, and we wish to thank them for discovering many of the problems that this document attempts to rectify ๐Ÿ’œ.

17 References โœจ

okay bestie, the bibliography is literally where all the receipts live ๐Ÿงพ๐Ÿ’… every single source is listed below, with all the details, so you can go find them yourself if you want to go down a rabbit hole ๐Ÿ‡

  • [1] Alvestrand, H., "Tags for the Identification of Languages", RFC 1766, 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, March 1993.
  • [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC 1630, June 1994.
  • [4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource Locators (URL)", RFC 1738, December 1994.
  • [5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language - 2.0", RFC 1866, November 1995.
  • [6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
  • [7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
  • [8] Braden, R., "Requirements for Internet Hosts -- Communication Layers", STD 3, RFC 1123, October 1989.
  • [9] Crocker, D., "Standard for The Format of ARPA Internet Text Messages", STD 11, RFC 822, 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, June 1995.
  • [12] Horton, M. and R. Adams, "Standard for Interchange of USENET Messages", RFC 1036, December 1987.
  • [13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC 977, February 1986.
  • [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, November 1996.
  • [15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC 1867, November 1995.
  • [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, August 1982.
  • [17] Postel, J., "Media Type Registration Procedure", RFC 1590, November 1996.
  • [18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC 959, October 1985.
  • [19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC 1700, October 1994.
  • [20] Sollins, K. and L. Masinter, "Functional Requirements for Uniform Resource Names", RFC 1737, 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, October 1995.
  • [24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC 1900, February 1996.
  • [25] Deutsch, P., "GZIP file format specification version 4.3", RFC 1952, 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 Conference '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/touch/pubs/http-perf96/>, ISI Research Report ISI/RR-98-463, (original report dated Aug. 1996), USC/Information Sciences Institute, August 1998.
  • [28] Mills, D., "Network Time Protocol (Version 3) Specification, Implementation and Analysis", RFC 1305, March 1992.
  • [29] Deutsch, P., "DEFLATE Compressed Data Format Specification version 1.3", RFC 1951, May 1996.
  • [30] S. Spero, "Analysis of HTTP Performance Problems," http://sunsite.unc.edu/mdma-release/http-prob.html.
  • [31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format Specification version 3.3", RFC 1950, 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.
  • [33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2068, January 1997.
  • [34] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [35] Troost, R. and Dorner, S., "Communicating Presentation Information in Internet Messages: The Content-Disposition Header", RFC 1806, June 1995.
  • [36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and Interpretation of HTTP Version Numbers", RFC 2145, May 1997. [jg639]
  • [37] Palme, J., "Common Internet Message Headers", RFC 2076, February 1997. [jg640]
  • [38] Yergeau, F., "UTF-8, a transformation format of Unicode and ISO-10646", RFC 2279, January 1998. [jg641]
  • [39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E., Lie, H., and C. Lilley. "Network Performance Effects of HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes France, September 1997.[jg642]
  • [40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, November 1996. [jg643]
  • [41] Alvestrand, H., "IETF Policy on Character Sets and Languages", BCP 18, RFC 2277, January 1998. [jg644]
  • [42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax and Semantics", RFC 2396, August 1998. [jg645]
  • [43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, June 1999. [jg646]
  • [44] Luotonen, A., "Tunneling TCP based protocols through Web proxy servers," Work in Progress. [jg647]
  • [45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of Aggregate Documents, such as HTML (MHTML)", RFC 2110, March 1997.
  • [46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP 9, RFC 2026, October 1996.
  • [47] Masinter, L., "Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)", RFC 2324, 1 April 1998.
  • [48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples", RFC 2049, November 1996.
  • [49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field", RFC 2183, August 1997.

18 Authors' Addresses ๐Ÿ’Œ

these are the lovely people who wrote the whole thing, and where you can reach them ๐Ÿซถ the contact details are copied exactly as they appear in the document:

Roy T. Fielding
Information and Computer Science
University of California, Irvine
Irvine, CA 92697-3425, USA

Fax: +1 (949) 824-1715
EMail: fielding@ics.uci.edu


James Gettys
World Wide Web Consortium
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
Compaq Computer Corporation
250 University Avenue
Palo Alto, California, 94305, USA

EMail: mogul@wrl.dec.com


Henrik Frystyk Nielsen
World Wide Web Consortium
MIT Laboratory for Computer Science
545 Technology Square
Cambridge, MA 02139, USA

Fax: +1 (617) 258 8682
EMail: frystyk@w3.org


Larry Masinter
Xerox Corporation
3333 Coyote Hill Road
Palo Alto, CA 94034, USA

EMail: masinter@parc.xerox.com
Paul J. Leach
Microsoft Corporation
1 Microsoft Way
Redmond, WA 98052, USA

EMail: paulle@microsoft.com


Tim Berners-Lee
Director, World Wide Web 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 and application/http ๐Ÿ“จ

okay so this appendix is the official paperwork for two media types ๐Ÿงพโœจ besides defining HTTP/1.1, this document also acts as the spec for "message/http" and "application/http". ๐Ÿ’… the message/http one can wrap a single HTTP request or response, as long as it follows the MIME rules for "message" types about line length and encodings ๐Ÿ“ the application/http one can wrap a pipeline of one or more HTTP requests or responses, which are not intermixed ๐Ÿฆ‹ the registration details go to IANA [17], and they look like this:

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

Media Type name:         application
Media subtype name:      http
Required parameters:     none
Optional parameters:     version, msgtype
 version: The HTTP-Version number of the enclosed messages
          (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: HTTP messages enclosed by this type
          are in "binary" format; use of an appropriate
          Content-Transfer-Encoding is required when
          transmitted via E-mail.
Security considerations: none

that's the whole media type paperwork, bestie! ๐ŸŒˆ๐Ÿ”ฅ

19.2. Internet Media Type multipart/byteranges

Okay bestie, so when an HTTP 206 (Partial Content) response includes the content of multiple ranges (a response to a request for multiple non-overlapping ranges) ๐Ÿงฉ, it gets sent as a multipart message-body โœจ. The media type for this is called multipart/byteranges ๐ŸŽ€.

The multipart/byteranges media type includes two or more parts, and each part has its own Content-Type and Content-Range fields ๐Ÿ’–. The required boundary parameter is the boundary string that separates each body-part ๐Ÿฆ‹.

       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

Here's an example, because examples are everything ๐ŸŒธ:

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--

Some notes for you, bestie ๐Ÿ“:

  1. Additional CRLFs may precede the first boundary string in the entity.
  2. Although RFC 2046 [40] permits the boundary string to be quoted, some existing implementations handle a quoted boundary string incorrectly. ๐Ÿ’€
  3. A number of browsers and servers were coded to an early draft of the byteranges specification to use a media type of multipart/x-byteranges, which is almost, but not quite, compatible with the version documented in HTTP/1.1 ๐Ÿ™ˆ

19.3. Tolerant Applications

Okay so, this document lays out the requirements for generating HTTP/1.1 messages, but not every app is going to get it perfectly right ๐Ÿ˜ญ. We therefore recommend that operational applications be tolerant of deviations whenever those deviations can be interpreted unambiguously ๐Ÿซถ.

Clients SHOULD be tolerant in parsing the Status-Line, and servers tolerant when parsing the Request-Line ๐ŸŽ€. In particular, they SHOULD accept any amount of SP or HT characters between fields, even though only a single SP is required โœจ.

The line terminator for message-header fields is the sequence CRLF. However, we recommend that applications, when parsing such headers, recognize a single LF as a line terminator and ignore the leading CR ๐ŸŒˆ.

The character set of an entity-body SHOULD be labeled as the lowest common denominator of the character codes used within that body, with the exception that not labeling the entity is preferred over labeling the entity with the labels US-ASCII or ISO-8859-1 ๐Ÿ’…. See section 3.7.1 and 3.4.1.

Here are the extra rules for parsing and encoding dates, plus other date drama to watch out for ๐Ÿ“…:

  • HTTP/1.1 clients and caches SHOULD assume that an RFC-850 date which appears to be more than 50 years in the future is in fact in the past (this helps solve the "year 2000" problem) ๐Ÿ‘‘.
  • An HTTP/1.1 implementation MAY internally represent a parsed Expires date as earlier than the proper value, but MUST NOT internally represent 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 incorrectly carries a date value 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 RFC 2045 Entities

HTTP/1.1 borrows a lot of constructs from Internet Mail (RFC 822 [9]) and the Multipurpose Internet Mail Extensions (MIME [7]) so entities can be sent in an open variety of representations with extensible mechanisms ๐ŸŒธ. But RFC 2045 is all about mail, and HTTP has a few features that are different from what RFC 2045 describes ๐Ÿ‘€. These differences were carefully chosen to optimize performance over binary connections, to allow greater freedom in the use of new media types, to make date comparisons easier, and to acknowledge the practice of some early HTTP servers and clients ๐Ÿ’–.

This appendix describes the specific areas where HTTP differs from RFC 2045. Proxies and gateways to strict MIME environments SHOULD be aware of these differences and provide the appropriate conversions where necessary ๐ŸŽ€. Proxies and gateways from MIME environments to HTTP also need to be aware of the differences, because some conversions might be required โœจ.

19.4.1. MIME-Version

HTTP is not a MIME-compliant protocol ๐Ÿ™ƒ. However, HTTP/1.1 messages MAY include a single MIME-Version general-header field to indicate what version of the MIME protocol was used to construct the message. Use of the MIME-Version header field indicates that the message is in full compliance with the MIME protocol (as defined in RFC 2045[7]). Proxies/gateways are responsible for ensuring full compliance (where possible) when exporting 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. However, HTTP/1.1 message parsing and semantics are defined by this document and not the MIME specification ๐Ÿ’œ.

19.4.2. Conversion to Canonical Form

RFC 2045 [7] requires that an Internet mail entity be converted to canonical form prior to being transferred, as described in section 4 of RFC 2049 [48] ๐Ÿ“ฌ. Section 3.7.1 of this document describes the forms allowed for subtypes of the "text" media type when transmitted over HTTP. RFC 2046 requires that content with a type of "text" represent line breaks as CRLF and forbids the use of CR or LF outside of line break sequences. HTTP allows CRLF, bare CR, and bare LF to indicate a line break within text content when a message is transmitted over HTTP ๐Ÿซง.

Where it is possible, a proxy or gateway from HTTP to a strict MIME environment SHOULD translate all line breaks within the text media types described in section 3.7.1 of this document to the RFC 2049 canonical form of CRLF. Note, however, that this might be complicated by the presence of a Content-Encoding, and by the fact that HTTP allows the use of some character sets which do not use octets 13 and 10 to represent CR and LF, as is the case for some multi-byte character sets ๐ŸŒ€.

Implementors should note that conversion will break any cryptographic checksums applied to the original content unless the original content is already in canonical form. Therefore, the canonical form is recommended for any content that uses such checksums in HTTP ๐Ÿ”.

19.4.3. Conversion of Date Formats

HTTP/1.1 uses a restricted set of date formats (section 3.3.1) to simplify the process of date comparison ๐Ÿ—“๏ธ. Proxies and gateways from other protocols SHOULD ensure that any Date header field present in a message conforms to one of the HTTP/1.1 formats, and rewrite the date if necessary ๐Ÿ’….

19.4.4. Introduction of Content-Encoding

RFC 2045 does not include any concept equivalent to HTTP/1.1's Content-Encoding header field. Since this acts as a modifier on the media type, proxies and gateways 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 applications of Content-Type for Internet mail have used a media-type parameter of ;conversions=<content-coding> to perform a function equivalent to Content-Encoding. However, this parameter is not part of RFC 2045.) ๐Ÿง

19.4.5. No Content-Transfer-Encoding

HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC 2045 ๐Ÿ™…โ€โ™€๏ธ. Proxies and gateways from MIME-compliant protocols to HTTP MUST remove any non-identity CTE ("quoted-printable" or "base64") encoding prior to delivering the response message to an HTTP client ๐Ÿงน.

Proxies and gateways from HTTP to MIME-compliant protocols are responsible for ensuring that the message is in the correct format and encoding for safe transport on that protocol, where "safe transport" is defined by the limitations of the protocol being used. Such a proxy or gateway SHOULD label the data with an appropriate Content-Transfer-Encoding if doing so will improve the likelihood of safe transport over the destination protocol โœจ.

19.4.6. Introduction of Transfer-Encoding

HTTP/1.1 introduces the Transfer-Encoding header field (section 14.41) ๐Ÿšš. Proxies/gateways MUST remove any transfer-coding prior to forwarding a message via a MIME-compliant protocol ๐Ÿซถ.

A process for decoding the "chunked" transfer-coding (section 3.6) can be represented in pseudo-code as:

       length := 0
       read chunk-size, chunk-extension (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. MHTML and Line Length Limitations

HTTP implementations which share code with MHTML [45] implementations need to be aware of MIME line length limitations ๐Ÿ“. Since HTTP does not have this limitation, HTTP does not fold long lines ๐Ÿฆ‹. MHTML messages being transported by HTTP follow all conventions of MHTML, including line length limitations and folding, canonicalization, etc., since HTTP transports all message-bodies as payload (see section 3.7.2) and does not interpret the content or any MIME header lines that might be contained therein ๐Ÿงš.

19.5. Additional Features

RFC 1945 and RFC 2068 document protocol elements used by some existing HTTP implementations, but not consistently and correctly across most HTTP/1.1 applications ๐Ÿ“. Implementors are advised to be aware of these features, but cannot rely upon their presence in, or interoperability with, other HTTP/1.1 applications. Some of these describe proposed experimental features, and some describe features that experimental deployment found lacking that are now addressed in the base HTTP/1.1 specification ๐ŸŒˆ.

A number of other headers, such as Content-Disposition and Title, from SMTP and MIME are also often implemented (see RFC 2076 [37]) ๐Ÿ’–.

19.5.1. Content-Disposition ๐Ÿ’–

okay so Content-Disposition is a response header field that lets the origin server suggest a default filename when the user wants to save the content to a file ๐Ÿ“โœจ. It's derived from how RFC 1806 [35] defined Content-Disposition, so it has history, bestie ๐Ÿงš

content-disposition = "Content-Disposition" ":"
                      disposition-type *( ";" disposition-parm )
disposition-type = "attachment" | disp-extension-token
disposition-parm = filename-parm | disp-extension-parm
filename-parm = "filename" "=" quoted-string
disp-extension-token = token
disp-extension-parm = token "=" ( token | quoted-string )

An example is:

Content-Disposition: attachment; filename="fname.ext"

The receiving user agent SHOULD NOT respect any directory path information present in the filename-parm parameter, which is the only parameter believed to apply to HTTP implementations at this time. The filename SHOULD be treated as a terminal component only. ๐Ÿ™…โ€โ™€๏ธ๐Ÿ—‚๏ธ so the filename is just a name, not a whole path. no directory vibes allowed ๐Ÿ’…

If this header is used in a response with the application/octet-stream content-type, the implied suggestion is that the user agent should not display the response, but directly enter a `save response as...' dialog. ๐Ÿ“ฅ basically "don't open this, just save it" energy.

See section 15.5 for Content-Disposition security issues. ๐Ÿšจ Please go read that one, it's giving serious danger zone vibes.


19.6. Compatibility with Previous Versions ๐Ÿฆ‹

okay so it's beyond the scope of a protocol spec to force anyone to stay compatible with older versions ๐Ÿ™„ but HTTP/1.1 was deliberately built to make supporting previous versions easy, which is so thoughtful ๐Ÿฅน Worth noting: when this spec was written (1996), they expected 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 they expected 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. Some implementations use the Keep-Alive version of persistent connections described in section 19.7.1 of RFC 2068 [33]. ๐Ÿงธ

19.6.1. Changes from HTTP/1.0 ๐ŸŒธ

This section gives the big picture on the major differences between HTTP/1.0 and HTTP/1.1 โœจ

19.6.1.1. Changes to Simplify Multi-homed Web Servers and Conserve IP Addresses ๐ŸŒˆ

the requirements that clients and servers support the Host request-header, report an error if the Host request-header (section 14.23) is missing from an HTTP/1.1 request, and accept absolute URIs (section 5.1.2) are some of the most important changes in this spec ๐Ÿ‘‘ no cap.

Old HTTP/1.0 clients assumed one IP address per server, because there was no other established way to tell which server a request was meant for besides the IP address it was sent to ๐Ÿ™ˆ The changes above will let the Internet, once older HTTP clients aren't common anymore, host multiple websites on a single IP address. That makes big operational Web servers way simpler, where giving one host tons of IP addresses caused serious problems ๐Ÿ’€ The Internet could also get back IP addresses that were only handed out so special-purpose domain names could be used in root-level HTTP URLs. Given how fast the Web grew and how many servers are already out there, it's extremely important that all HTTP implementations (including updates to existing HTTP/1.0 apps) correctly implement these requirements:

  • Both clients and servers MUST support the Host request-header.
  • A client that sends an HTTP/1.1 request MUST send a Host header.
  • 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.2. Compatibility with HTTP/1.0 Persistent Connections ๐Ÿงต

Some clients and servers might want to stay compatible with older implementations of persistent connections in HTTP/1.0 clients and servers. In HTTP/1.0, persistent connections are explicitly negotiated because they aren't the default behavior. The HTTP/1.0 experimental implementations were faulty, and HTTP/1.1's new facilities were designed to fix those problems ๐Ÿ”ง The problem was that some existing 1.0 clients may 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 HTTP/1.0 proxy would end up hung, waiting for the close on the response ๐Ÿ˜ญ The result is that 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 ๐Ÿ™…โ€โ™€๏ธ So we need some other mechanism for indicating a persistent connection is desired, one that's safe to use 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. See section 14.10. ๐Ÿซถ

The original HTTP/1.0 form of persistent connections (the Connection: Keep-Alive and Keep-Alive header) is documented in RFC 2068. [33]

19.6.3. Changes from RFC 2068 ๐Ÿ“

This specification has been carefully audited to correct and disambiguate key word usage. RFC 2068 had many problems with the conventions laid out in RFC 2119 [34] ๐Ÿค“

Clarified which error code should be used for inbound server failures (e.g. DNS failures). (Section 10.5.5).

CREATE had a race that required an Etag be sent when a resource is first created. (Section 10.2.2).

Content-Base was deleted from the specification: it wasn't implemented widely, and there's no simple, safe way to introduce it without a robust extension mechanism. It's also used in a similar, but not identical, fashion in MHTML [45]. ๐Ÿ—‘๏ธ

Transfer-coding and message lengths all interact in ways that needed fixing, especially exactly when chunked encoding is used (to allow for transfer encoding that may not be self delimiting). It was important to straighten out exactly how message lengths are computed. (Sections 3.6, 4.4, 7.2.2, 13.5.2, 14.13, 14.16)

A content-coding of "identity" was introduced to solve problems discovered in caching. (section 3.5)

Quality Values of zero should indicate that "I don't want something," so clients can refuse a representation. (Section 3.9) ๐Ÿ™…โ€โ™€๏ธ

The use and interpretation of HTTP version numbers was clarified by RFC 2145. Require proxies to upgrade requests to the highest protocol version they support, to deal with problems discovered in HTTP/1.0 implementations (Section 3.1) โฌ†๏ธ

Charset wildcarding was introduced to avoid an explosion of character set names in accept headers. (Section 14.2)

A case was missed in the Cache-Control model of HTTP/1.1, so s-maxage was introduced to add that missing case. (Sections 13.4, 14.8, 14.9, 14.9.3)

The Cache-Control: max-age directive wasn't properly defined for responses. (Section 14.9.3)

There are situations where a server (especially a proxy) doesn't know the full length of a response but can still serve a byterange request. We therefore need a mechanism that allows byteranges with a content-range that doesn't indicate the full length of the message. (Section 14.16) ๐Ÿงฉ

Range request responses would get super verbose if all metadata were always returned. By letting the server send only the needed headers in a 206 response, this problem goes away. (Section 10.2.7, 13.5.3, and 14.27) ๐ŸŽ€

Fixed the problem with unsatisfiable range requests. There are two cases: syntactic problems, and a range that doesn't exist in the document. The 416 status code was needed to resolve this ambiguity and to indicate an error for a byte range request that falls outside of the actual contents of a document. (Section 10.4.17, 14.16) ๐Ÿ’…

Rewrite of the message transmission requirements to make it much harder for implementors to get it wrong, since errors here can have a big impact on the Internet, and to deal with the following problems:

  1. Changing "HTTP/1.1 or later" to "HTTP/1.1", in contexts where this was incorrectly placing a requirement on the behavior of an implementation of a future version of HTTP/1.x
  2. Made it clear that user-agents should retry requests, not "clients" in general.
  3. Converted requirements for clients to ignore unexpected 100 (Continue) responses, and for proxies to forward 100 responses, into a general requirement for 1xx responses.
  4. Modified some TCP-specific language, to make it clearer that non-TCP transports are possible for HTTP.
  5. Require that the origin server MUST NOT wait for the request body before it sends a required 100 (Continue) response.
  6. Allow, rather than require, a server to omit 100 (Continue) if it has already seen some of the request body.
  7. Allow servers to defend against denial-of-service attacks and broken clients.

This change adds the Expect header and 417 status code. The message transmission requirement fixes are in sections 8.2, 10.4.18, 8.1.2.2, 13.11, and 14.20. ๐Ÿšฆ

Proxies should be able to add Content-Length when appropriate. (Section 13.5.2)

Cleaned up the confusion between 403 and 404 responses. (Section 10.4.4, 10.4.5, and 10.4.11)

Warnings could be cached incorrectly, or not updated appropriately. (Section 13.1.2, 13.2.4, 13.5.2, 13.5.3, 14.9.3, and 14.46) Warning also needed to be a general header, since PUT or other methods may need it in requests. โš ๏ธ

Transfer-coding had significant problems, particularly with its interactions with chunked encoding. The solution is that transfer-codings become as full-fledged as content-codings. This involves adding an IANA registry for transfer-codings (separate from content codings), a new header field (TE), and enabling trailer headers in the future. Transfer encoding is a major performance benefit, so it was worth fixing [39]. TE also solves another, obscure, downward interoperability problem that could have occurred due to interactions between authentication trailers, chunked encoding, and HTTP/1.0 clients. (Section 3.6, 3.6.1, and 14.39) ๐Ÿง 

The PATCH, LINK, UNLINK methods were defined but not commonly implemented in previous versions of this specification. See RFC 2068 [33]. ๐Ÿฉน

The Alternates, Content-Version, Derived-From, Link, URI, Public and Content-Base header fields were defined in previous versions of this specification, but not commonly implemented. See RFC 2068 [33]. ๐Ÿชฆ


20. Index ๐Ÿ“š

Please see the PostScript version of this RFC for the INDEX. ๐Ÿงšโ€โ™€๏ธ

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐ŸŽ€

okay so this is the legal part, but it's still lowkey iconic โœจ The Internet Society owns the copyright, and everyone can copy and share this document and translations of it. People are also allowed to write derivative works that comment on or explain it, or that help people implement it. Those can be prepared, copied, published, and distributed, in whole or in part, with no real restrictions, as long as the copyright notice and this paragraph stay on every copy and derivative work ๐Ÿซถ

The one thing you can't do is modify this document itself. That means you can't remove the copyright notice or the references to the Internet Society or other Internet organizations. The exceptions are when you need it to develop Internet standards, in which case you have to follow the copyright procedures in the Internet Standards process, or when you translate it into languages other than English ๐ŸŒˆ

The permissions above are perpetual. The Internet Society, its successors, and its assigns won't take them back, so they're forever, bestie ๐Ÿ’œ

This document and the information in it are provided "AS IS," and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐Ÿ˜ญ no cap, that's the legal energy we're dealing with.


Acknowledgement ๐ŸŒธ

Funding for the RFC Editor function is currently provided by the Internet Society. ๐Ÿงš Someone has to keep the lights on, and the Internet Society is the one doing it right now. ๐Ÿ“

๐Ÿ“ฆ where this page comes from