RFC 9110

HTTP Semantics

๐Ÿ“… published June 2022, from ietf

HTTP Semantics โœจ

Okay bestie, welcome to RFC 9110, aka the HTTP Semantics spec ๐Ÿฆ‹ It's STD 97, which means it's an official Internet Standard, and it's giving main character energy. This is part 1 of 48, so we're just getting the setup first ๐ŸŒธ

  • Number: RFC 9110, from the Internet Engineering Task Force (IETF) ๐Ÿ’–
  • Written by: R. Fielding, Ed. (Adobe), M. Nottingham, Ed. (Fastly), and J. Reschke, Ed. (greenbytes) ๐Ÿ‘‘
  • Category: Standards Track, so it's an official standard ๐ŸŽ€
  • Date: June 2022 ๐ŸŒˆ
  • ISSN: 2070-1721
  • Obsoletes: RFCs 2818, 7230, 7231, 7232, 7233, 7235, 7538, 7615, and 7694 ๐Ÿ’… (the abstract says it only obsoletes portions of 7230, so that's the detail to remember ๐Ÿ™ˆ)
  • Updates: RFC 3864 โœจ

Abstract

Okay so HTTP, the Hypertext Transfer Protocol, is a stateless application-level protocol ๐Ÿงš It's built for distributed, collaborative hypertext information systems, which is the fancy way of saying the web ๐ŸŒ This doc lays out the overall architecture of HTTP, sets the common terminology everyone uses, and defines the parts of the protocol that are shared by all versions ๐Ÿ’œ It covers the core protocol elements, the extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes ๐Ÿ”ฅ

The abstract also says this document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230 ๐Ÿฆ‹ Major glow-up energy, periodt ๐Ÿ’€

Status of This Memo

This is an Internet Standards Track document โญ

It's a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community ๐Ÿซถ It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG) ๐Ÿ’… For more on Internet Standards, check out Section 2 of RFC 7841 ๐Ÿ“š

Info about the current status of this document, any errata, and how to send feedback can be found at https://www.rfc-editor.org/info/rfc9110 ๐Ÿ“

Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved ๐Ÿ’–

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read these, bestie, because they spell out your rights and restrictions for this document ๐Ÿ™ˆ Any Code Components pulled out of this document have to include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in that license ๐Ÿ”ฅ

This document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The people who control the copyright in some of that older material may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process. So unless you've got an adequate license from whoever controls that copyright, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process ๐Ÿ’€ The only exceptions are formatting it for publication as an RFC or translating it into languages other than English ๐ŸŒˆ

Okay bestie, the table of contents comes first so we can see the whole map of the doc ๐Ÿ—บ๏ธโœจ

Table of Contents ๐ŸŽ€

Table of Contents

   1.  Introduction
     1.1.  Purpose
     1.2.  History and Evolution
     1.3.  Core Semantics
     1.4.  Specifications Obsoleted by This Document
   2.  Conformance
     2.1.  Syntax Notation
     2.2.  Requirements Notation
     2.3.  Length Requirements
     2.4.  Error Handling
     2.5.  Protocol Version
   3.  Terminology and Core Concepts
     3.1.  Resources
     3.2.  Representations
     3.3.  Connections, Clients, and Servers
     3.4.  Messages
     3.5.  User Agents
     3.6.  Origin Server
     3.7.  Intermediaries
     3.8.  Caches
     3.9.  Example Message Exchange
   4.  Identifiers in HTTP
     4.1.  URI References
     4.2.  HTTP-Related URI Schemes
       4.2.1.  http URI Scheme
       4.2.2.  https URI Scheme
       4.2.3.  http(s) Normalization and Comparison
       4.2.4.  Deprecation of userinfo in http(s) URIs
       4.2.5.  http(s) References with Fragment Identifiers
     4.3.  Authoritative Access
       4.3.1.  URI Origin
       4.3.2.  http Origins
       4.3.3.  https Origins
       4.3.4.  https Certificate Verification
       4.3.5.  IP-ID Reference Identity
   5.  Fields
     5.1.  Field Names
     5.2.  Field Lines and Combined Field Value
     5.3.  Field Order
     5.4.  Field Limits
     5.5.  Field Values
     5.6.  Common Rules for Defining Field Values
       5.6.1.  Lists (#rule ABNF Extension)
         5.6.1.1.  Sender Requirements
         5.6.1.2.  Recipient Requirements
       5.6.2.  Tokens
       5.6.3.  Whitespace
       5.6.4.  Quoted Strings
       5.6.5.  Comments
       5.6.6.  Parameters
       5.6.7.  Date/Time Formats
   6.  Message Abstraction
     6.1.  Framing and Completeness
     6.2.  Control Data
     6.3.  Header Fields
     6.4.  Content
       6.4.1.  Content Semantics
       6.4.2.  Identifying Content
     6.5.  Trailer Fields
       6.5.1.  Limitations on Use of Trailers
       6.5.2.  Processing Trailer Fields
     6.6.  Message Metadata
       6.6.1.  Date
       6.6.2.  Trailer
   7.  Routing HTTP Messages
     7.1.  Determining the Target Resource
     7.2.  Host and :authority
     7.3.  Routing Inbound Requests
       7.3.1.  To a Cache
       7.3.2.  To a Proxy
       7.3.3.  To the Origin
     7.4.  Rejecting Misdirected Requests
     7.5.  Response Correlation
     7.6.  Message Forwarding
       7.6.1.  Connection
       7.6.2.  Max-Forwards
       7.6.3.  Via
     7.7.  Message Transformations
     7.8.  Upgrade
   8.  Representation Data and Metadata
     8.1.  Representation Data
     8.2.  Representation Metadata
     8.3.  Content-Type
       8.3.1.  Media Type
       8.3.2.  Charset
       8.3.3.  Multipart Types
     8.4.  Content-Encoding
       8.4.1.  Content Codings
         8.4.1.1.  Compress Coding
         8.4.1.2.  Deflate Coding
         8.4.1.3.  Gzip Coding
     8.5.  Content-Language
       8.5.1.  Language Tags
     8.6.  Content-Length
     8.7.  Content-Location
     8.8.  Validator Fields
       8.8.1.  Weak versus Strong
       8.8.2.  Last-Modified
         8.8.2.1.  Generation
         8.8.2.2.  Comparison
       8.8.3.  ETag
         8.8.3.1.  Generation
         8.8.3.2.  Comparison
         8.8.3.3.  Example: Entity Tags Varying on Content-Negotiated
                 Resources
   9.  Methods
     9.1.  Overview
     9.2.  Common Method Properties
       9.2.1.  Safe Methods
       9.2.2.  Idempotent Methods
       9.2.3.  Methods and Caching
     9.3.  Method Definitions
       9.3.1.  GET
       9.3.2.  HEAD
       9.3.3.  POST
       9.3.4.  PUT
       9.3.5.  DELETE
       9.3.6.  CONNECT
       9.3.7.  OPTIONS
       9.3.8.  TRACE
   10. Message Context
     10.1.  Request Context Fields
       10.1.1.  Expect
       10.1.2.  From
       10.1.3.  Referer
       10.1.4.  TE
       10.1.5.  User-Agent
     10.2.  Response Context Fields
       10.2.1.  Allow
       10.2.2.  Location
       10.2.3.  Retry-After
       10.2.4.  Server
   11. HTTP Authentication
     11.1.  Authentication Scheme
     11.2.  Authentication Parameters
     11.3.  Challenge and Response
     11.4.  Credentials
     11.5.  Establishing a Protection Space (Realm)
     11.6.  Authenticating Users to Origin Servers
       11.6.1.  WWW-Authenticate
       11.6.2.  Authorization
       11.6.3.  Authentication-Info
     11.7.  Authenticating Clients to Proxies
       11.7.1.  Proxy-Authenticate
       11.7.2.  Proxy-Authorization
       11.7.3.  Proxy-Authentication-Info
   12. Content Negotiation
     12.1.  Proactive Negotiation
     12.2.  Reactive Negotiation
     12.3.  Request Content Negotiation
     12.4.  Content Negotiation Field Features
       12.4.1.  Absence
       12.4.2.  Quality Values
       12.4.3.  Wildcard Values
     12.5.  Content Negotiation Fields
       12.5.1.  Accept
       12.5.2.  Accept-Charset
       12.5.3.  Accept-Encoding
       12.5.4.  Accept-Language
       12.5.5.  Vary
   13. Conditional Requests
     13.1.  Preconditions
       13.1.1.  If-Match
       13.1.2.  If-None-Match
       13.1.3.  If-Modified-Since
       13.1.4.  If-Unmodified-Since
       13.1.5.  If-Range
     13.2.  Evaluation of Preconditions
       13.2.1.  When to Evaluate
       13.2.2.  Precedence of Preconditions
   14. Range Requests
     14.1.  Range Units
       14.1.1.  Range Specifiers
       14.1.2.  Byte Ranges
     14.2.  Range
     14.3.  Accept-Ranges
     14.4.  Content-Range
     14.5.  Partial PUT
     14.6.  Media Type multipart/byteranges
   15. Status Codes
     15.1.  Overview of Status Codes
     15.2.  Informational 1xx
       15.2.1.  100 Continue
       15.2.2.  101 Switching Protocols
     15.3.  Successful 2xx
       15.3.1.  200 OK
       15.3.2.  201 Created
       15.3.3.  202 Accepted
       15.3.4.  203 Non-Authoritative Information
       15.3.5.  204 No Content
       15.3.6.  205 Reset Content
       15.3.7.  206 Partial Content
         15.3.7.1.  Single Part
         15.3.7.2.  Multiple Parts
         15.3.7.3.  Combining Parts
     15.4.  Redirection 3xx
       15.4.1.  300 Multiple Choices
       15.4.2.  301 Moved Permanently
       15.4.3.  302 Found
       15.4.4.  303 See Other
       15.4.5.  304 Not Modified
       15.4.6.  305 Use Proxy
       15.4.7.  306 (Unused)
       15.4.8.  307 Temporary Redirect
       15.4.9.  308 Permanent Redirect
     15.5.  Client Error 4xx
       15.5.1.  400 Bad Request
       15.5.2.  401 Unauthorized
       15.5.3.  402 Payment Required
       15.5.4.  403 Forbidden
       15.5.5.  404 Not Found
       15.5.6.  405 Method Not Allowed
       15.5.7.  406 Not Acceptable
       15.5.8.  407 Proxy Authentication Required
       15.5.9.  408 Request Timeout
       15.5.10. 409 Conflict
       15.5.11. 410 Gone
       15.5.12. 411 Length Required
       15.5.13. 412 Precondition Failed
       15.5.14. 413 Content Too Large
       15.5.15. 414 URI Too Long
       15.5.16. 415 Unsupported Media Type
       15.5.17. 416 Range Not Satisfiable
       15.5.18. 417 Expectation Failed
       15.5.19. 418 (Unused)
       15.5.20. 421 Misdirected Request
       15.5.21. 422 Unprocessable Content
       15.5.22. 426 Upgrade Required
     15.6.  Server Error 5xx
       15.6.1.  500 Internal Server Error
       15.6.2.  501 Not Implemented
       15.6.3.  502 Bad Gateway
       15.6.4.  503 Service Unavailable
       15.6.5.  504 Gateway Timeout
       15.6.6.  505 HTTP Version Not Supported
   16. Extending HTTP
     16.1.  Method Extensibility
       16.1.1.  Method Registry
       16.1.2.  Considerations for New Methods
     16.2.  Status Code Extensibility
       16.2.1.  Status Code Registry
       16.2.2.  Considerations for New Status Codes
     16.3.  Field Extensibility
       16.3.1.  Field Name Registry
       16.3.2.  Considerations for New Fields
         16.3.2.1.  Considerations for New Field Names
         16.3.2.2.  Considerations for New Field Values
     16.4.  Authentication Scheme Extensibility
       16.4.1.  Authentication Scheme Registry
       16.4.2.  Considerations for New Authentication Schemes
     16.5.  Range Unit Extensibility
       16.5.1.  Range Unit Registry
       16.5.2.  Considerations for New Range Units
     16.6.  Content Coding Extensibility
       16.6.1.  Content Coding Registry
       16.6.2.  Considerations for New Content Codings
     16.7.  Upgrade Token Registry
   17. Security Considerations
     17.1.  Establishing Authority
     17.2.  Risks of Intermediaries
     17.3.  Attacks Based on File and Path Names
     17.4.  Attacks Based on Command, Code, or Query Injection
     17.5.  Attacks via Protocol Element Length
     17.6.  Attacks Using Shared-Dictionary Compression
     17.7.  Disclosure of Personal Information
     17.8.  Privacy of Server Log Information
     17.9.  Disclosure of Sensitive Information in URIs
     17.10. Application Handling of Field Names
     17.11. Disclosure of Fragment after Redirects
     17.12. Disclosure of Product Information
     17.13. Browser Fingerprinting
     17.14. Validator Retention
     17.15. Denial-of-Service Attacks Using Range
     17.16. Authentication Considerations
       17.16.1.  Confidentiality of Credentials
       17.16.2.  Credentials and Idle Clients
       17.16.3.  Protection Spaces
       17.16.4.  Additional Response Fields
   18. IANA Considerations
     18.1.  URI Scheme Registration
     18.2.  Method Registration
     18.3.  Status Code Registration
     18.4.  Field Name Registration
     18.5.  Authentication Scheme Registration
     18.6.  Content Coding Registration
     18.7.  Range Unit Registration
     18.8.  Media Type Registration
     18.9.  Port Registration
     18.10. Upgrade Token Registration
   19. References
     19.1.  Normative References
     19.2.  Informative References
   Appendix A.  Collected ABNF
   Appendix B.  Changes from Previous RFCs
     B.1.  Changes from RFC 2818
     B.2.  Changes from RFC 7230
     B.3.  Changes from RFC 7231
     B.4.  Changes from RFC 7232
     B.5.  Changes from RFC 7233
     B.6.  Changes from RFC 7235
     B.7.  Changes from RFC 7538
     B.8.  Changes from RFC 7615
     B.9.  Changes from RFC 7694
   Acknowledgements
   Index
   Authors' Addresses

1. Introduction โœจ

1.1. Purpose

Okay so HTTP (the Hypertext Transfer Protocol) is a whole family of stateless, application-level, request/response protocols ๐Ÿ’– They all share a generic interface, extensible semantics, and self-descriptive messages, which is what lets them do flexible interaction with network-based hypertext information systems. It's giving modular and it's giving iconic ๐Ÿฆ‹

HTTP hides the messy details of how a service is actually built behind a uniform interface that clients can use no matter what kind of resource they're talking to ๐Ÿซถ The servers don't need to know each client's purpose either. A request can be looked at all on its own, rather than being tied to one specific type of client or some predetermined sequence of app steps. That's how general-purpose implementations get to be useful in loads of different contexts, reduces interaction complexity, and lets things evolve independently over time ๐ŸŒˆ The way that this is designed is just chef's kiss ๐Ÿ‘‘

HTTP is also built to work as an intermediation protocol ๐Ÿงš Proxies and gateways can take non-HTTP information systems and translate them into a more generic interface, so everybody gets to hang out in the same place ๐Ÿ’…

Now here's the tea ๐Ÿต Because of all this flexibility, the protocol can't be defined by what goes on behind the interface. Instead, we're limited to defining the syntax of communication, the intent of received communication, and the expected behavior of recipients. ๐Ÿ˜ญ If you look at a communication all by itself, successful actions ought to show up as matching changes in the observable interface that servers provide. BUT since multiple clients might act in parallel (and maybe at cross-purposes ๐Ÿ’€), we can't require those changes to be observable beyond the scope of a single response ๐Ÿ™ˆ

1.2. History and Evolution ๐Ÿ•ฐ๏ธโœจ

okay so HTTP has been the main information transfer protocol for the World Wide Web since it showed up in 1990 ๐Ÿ’ป bestie it started out super simple, just low-latency requests with one method, GET, to grab a presumed hypertext document at a given pathname ๐ŸŽ€ then the Web grew and HTTP got upgraded to wrap requests and responses in messages, send arbitrary data formats using MIME-like media types, and route requests through intermediaries ๐Ÿฆ‹ those versions ended up being named HTTP/0.9 and HTTP/1.0 (see [HTTP/1.0]) ๐ŸŒธ

HTTP/1.1 was the glow-up ๐Ÿ’… it refined the features while keeping compatibility with the existing text-based messaging syntax, so interoperability, scalability, and robustness across the Internet all got better ๐ŸŒˆ it added length-based data delimiters for both fixed and dynamic (chunked) content, a consistent framework for content negotiation, opaque validators for conditional requests, cache controls for better cache consistency, range requests for partial updates, and default persistent connections ๐Ÿซถ HTTP/1.1 was introduced in 1995 and published on the Standards Track in 1997 [RFC2068], revised in 1999 [RFC2616], and revised again in 2014 ([RFC7230] through [RFC7235]) ๐Ÿ“

HTTP/2 ([HTTP/2]) brought a multiplexed session layer on top of the existing TLS and TCP protocols so you can exchange concurrent HTTP messages with efficient field compression and server push ๐Ÿ”ฅ HTTP/3 ([HTTP/3]) gives concurrent messages even more independence by using QUIC as a secure multiplexed transport over UDP instead of TCP ๐Ÿงš

all three major versions of HTTP rely on the semantics defined by this document โœจ they haven't obsoleted each other, because each one has specific benefits and limitations depending on the context of use ๐Ÿ’œ implementations are expected to pick the most appropriate transport and messaging syntax for their particular context, no cap ๐Ÿ’–

this revision separates the definition of semantics (this document) and caching ([CACHING]) from the current HTTP/1.1 messaging syntax ([HTTP/1.1]) ๐ŸŽ€ the point is to let each major protocol version progress independently while still referring to the same core semantics ๐Ÿฆ‹


1.3. Core Semantics ๐Ÿง 

HTTP gives you a uniform interface for interacting with a resource (Section 3.1) ๐Ÿ’… regardless of its type, nature, or implementation ๐ŸŒธ you do it by sending messages that manipulate or transfer representations (Section 3.2) โœจ

every message is either a request or a response ๐Ÿ’– a client builds request messages that communicate its intentions and routes them toward an identified origin server ๐Ÿš€ a server listens for requests, parses each message it receives, interprets the message semantics in relation to the identified target resource, and responds to that request with one or more response messages ๐Ÿซถ the client checks received responses to see if its intentions were carried out, then decides what to do next based on the status codes and content it got ๐Ÿ‘‘

HTTP semantics include the intentions defined by each request method (Section 9) ๐Ÿฆ‹ extensions to those semantics that might be described in request header fields ๐ŸŒˆ status codes that describe the response (Section 15) ๐Ÿ’œ and other control data and resource metadata that might be given in response fields ๐Ÿ“

semantics also cover representation metadata that describes how content is meant to be interpreted by a recipient ๐ŸŽ€ request header fields that might influence content selection โœจ and the various selection algorithms that are collectively called "content negotiation" (Section 12) ๐Ÿ’… iykyk, it's a whole thing ๐Ÿ˜ญ


1.4. Specifications Obsoleted by This Document ๐Ÿ—‘๏ธ

this document obsoletes the following specs, so here's the tea, bestie โ˜•

   +============================================+===========+=====+
   | Title                                      | Reference | See |
   +============================================+===========+=====+
   | HTTP Over TLS                              | [RFC2818] | B.1 |
   +--------------------------------------------+-----------+-----+
   | HTTP/1.1 Message Syntax and Routing [*]    | [RFC7230] | B.2 |
   +--------------------------------------------+-----------+-----+
   | HTTP/1.1 Semantics and Content             | [RFC7231] | B.3 |
   +--------------------------------------------+-----------+-----+
   | HTTP/1.1 Conditional Requests              | [RFC7232] | B.4 |
   +--------------------------------------------+-----------+-----+
   | HTTP/1.1 Range Requests                    | [RFC7233] | B.5 |
   +--------------------------------------------+-----------+-----+
   | HTTP/1.1 Authentication                    | [RFC7235] | B.6 |
   +--------------------------------------------+-----------+-----+
   | HTTP Status Code 308 (Permanent Redirect)  | [RFC7538] | B.7 |
   +--------------------------------------------+-----------+-----+
   | HTTP Authentication-Info and Proxy-        | [RFC7615] | B.8 |
   | Authentication-Info Response Header Fields |           |     |
   +--------------------------------------------+-----------+-----+
   | HTTP Client-Initiated Content-Encoding     | [RFC7694] | B.9 |
   +--------------------------------------------+-----------+-----+

                               Table 1
[*] This document only obsoletes the portions of RFC 7230 that are independent of the HTTP/1.1 messaging syntax and connection management ๐Ÿงฉ the remaining bits of RFC 7230 are obsoleted by "HTTP/1.1" [HTTP/1.1] ๐Ÿ’€

2. Conformance โœ…

2.1. Syntax Notation โœ๏ธ

this spec uses the Augmented Backus-Naur Form (ABNF) notation of [RFC5234], extended with the notation for case-sensitivity in strings defined in [RFC7405] ๐ŸŽ€

it also uses a list extension, defined in Section 5.6.1, that lets you define comma-separated lists compactly with a "#" operator ๐Ÿฆ‹ (it's kinda like how the "*" operator shows repetition) Appendix A shows the collected grammar with all list operators expanded to standard ABNF notation ๐Ÿ’œ

as a convention, ABNF rule names prefixed with "obs-" denote obsolete grammar rules that only show up for historical reasons ๐Ÿ•ฐ๏ธ

the following core rules are included by reference, as defined in Appendix B.1 of [RFC5234] ๐Ÿ’…:

  • ALPHA (letters)
  • CR (carriage return)
  • CRLF (CR LF)
  • CTL (controls)
  • DIGIT (decimal 0-9)
  • DQUOTE (double quote)
  • HEXDIG (hexadecimal 0-9/A-F/a-f)
  • HTAB (horizontal tab)
  • LF (line feed)
  • OCTET (any 8-bit sequence of data)
  • SP (space)
  • VCHAR (any visible US-ASCII character)

Section 5.6 defines some generic syntactic components for field values ๐ŸŒธ

this spec uses the terms "character", "character encoding scheme", "charset", and "protocol element" as they are defined in [RFC6365] ๐ŸŒˆ

2.2. Requirements Notation ๐Ÿ“œ

okay, this part is the big one ๐Ÿ˜ญ the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] ๐Ÿ”ฅ but only when they show up in all capitals, exactly like this ๐Ÿ’– lowercase versions are just regular words, bestie ๐Ÿซถ

this spec sets conformance criteria based on the role a participant plays in HTTP communication โœจ so requirements land on senders, recipients, clients, servers, user agents, intermediaries, origin servers, proxies, gateways, or caches, depending on which behaviour the requirement is limiting ๐Ÿฆ‹ extra requirements can go on implementations, resource owners, and protocol element registrations when they apply beyond the scope of a single communication ๐Ÿงš

the verb "generate" gets used instead of "send" where a requirement only applies to implementations that create the protocol element ๐ŸŽ€ as opposed to an implementation that forwards a received element downstream ๐Ÿš€

an implementation counts as conformant if it complies with all of the requirements tied to the roles it plays in HTTP ๐Ÿ‘‘

A sender MUST NOT generate protocol elements that do not match the grammar defined by the corresponding ABNF rules ๐Ÿ™…โ€โ™€๏ธ within a given message, a sender MUST NOT generate protocol elements or syntax alternatives that are only allowed to be generated by participants in other roles (i.e., a role that the sender does not have for that message) ๐Ÿ’… so like, stay in your lane ๐Ÿ˜ค

conformance to HTTP covers both the particular messaging syntax of the protocol version in use AND conformance to the semantics of the protocol elements sent ๐ŸŒˆ for example, a client that claims conformance to HTTP/1.1 but fails to recognize the features required of HTTP/1.1 recipients will fail to interoperate with servers that adjust their responses to match those claims ๐Ÿ’€ features that reflect user choices, like content negotiation and user-selected extensions, can affect application behaviour beyond the protocol stream ๐Ÿซถ so sending protocol elements that inaccurately reflect a user's choices will confuse the user and get in the way of their choice ๐Ÿ˜ญ

when an implementation fails semantic conformance, recipients of its messages will eventually come up with workarounds to adjust their behaviour accordingly ๐Ÿ™ˆ a recipient MAY use such workarounds and still be conformant to this protocol, as long as the workarounds are limited to the implementations at fault ๐Ÿ“ for example, servers often scan parts of the User-Agent field value, and user agents often scan the Server field value, to adjust their own behaviour around known bugs or poorly chosen defaults ๐Ÿง 

2.3. Length Requirements ๐Ÿ“

a recipient SHOULD parse a received protocol element defensively ๐Ÿ›ก๏ธ with only marginal expectations that the element will conform to its ABNF grammar and fit within a reasonable buffer size ๐ŸŒธ

HTTP doesn't have specific length limits for many of its protocol elements, because what counts as appropriate varies wildly depending on the deployment context and purpose of the implementation ๐ŸŒˆ so interoperability between senders and recipients depends on shared expectations about what's a reasonable length for each protocol element ๐Ÿฆ‹ also, what's commonly considered reasonable for some protocol elements has changed over the past three decades of HTTP use, and it's expected to keep changing in the future ๐Ÿ•ฐ๏ธโœจ

at a minimum, a recipient MUST be able to parse and process protocol element lengths that are at least as long as the values it generates for those same protocol elements in other messages ๐Ÿ’– for example, an origin server that publishes very long URI references to its own resources needs to be able to parse and process those same references when they're received as a target URI ๐ŸŽ€

a lot of received protocol elements only get parsed as far as needed to identify and forward that element downstream ๐Ÿš€ for example, an intermediary might parse a received field into its field name and field value components, then forward the field without any further parsing inside the field value ๐Ÿ’…

2.4. Error Handling โœจ

okay bestie, this one is a big rule ๐Ÿซถ A recipient MUST interpret a received protocol element according to the semantics this spec defines for it, extensions included. The only exception is when the recipient has figured out (through experience or configuration) that the sender is getting what those semantics imply wrong. For example, an origin server might ignore an Accept-Encoding header if the User-Agent header shows a specific implementation version that's known to break on certain content codings ๐Ÿ’€

Unless noted otherwise, a recipient MAY attempt to recover a usable protocol element from an invalid construct. HTTP doesn't define specific error handling mechanisms unless they directly affect security ๐Ÿ” because different apps need totally different strategies. A web browser might want to quietly recover when a Location header doesn't parse according to the ABNF, while a systems control client might think any kind of error recovery is dangerous ๐Ÿ˜ญ

Some requests can be automatically retried by a client if the underlying connection fails, as described in Section 9.2.2 ๐Ÿ”

2.5. Protocol Version ๐ŸŽ€

HTTP's version number is two decimal digits separated by a "." (period or decimal point). The first digit is the major version and tells you the messaging syntax. The second digit is the minor version and tells you the highest minor version within that major version the sender is conformant to (able to understand for future communication) ๐Ÿ’–

HTTP's core semantics don't change between protocol versions, but how they show up "on the wire" can. So the HTTP version number changes when incompatible changes are made to the wire format. HTTP also allows incremental, backwards-compatible changes without a version bump, through the defined extension points in Section 16 ๐Ÿงš

The protocol version as a whole shows the sender's conformance with the requirements in that version's specification(s). For example, "HTTP/1.1" is defined by the combined specifications of this document, "HTTP Caching" [CACHING], and "HTTP/1.1" [HTTP/1.1] ๐Ÿ“š

The major version number goes up when an incompatible message syntax is introduced. The minor number goes up when changes to the protocol add to the message semantics or imply additional capabilities of the sender ๐ŸŒˆ

The minor version advertises the sender's communication capabilities even when the sender is only using a backwards-compatible subset of the protocol. This lets the recipient know that more advanced features can be used in response (by servers) or in future requests (by clients) ๐Ÿ‘‘

When a major version of HTTP doesn't define any minor versions, the minor version "0" is implied. The "0" is used when referring to that protocol within elements that require a minor version identifier ๐Ÿ“

3. Terminology and Core Concepts ๐Ÿฆ‹

HTTP was created for the World Wide Web (WWW) architecture and has evolved over time to support the scalability needs of a worldwide hypertext system. A lot of that architecture shows up in the terminology used to define HTTP, so it's all connected ๐ŸŒธ

3.1. Resources ๐Ÿ’œ

The target of an HTTP request is called a "resource". HTTP doesn't limit what a resource can be. It just defines an interface that might be used to interact with resources โœจ Most resources are identified by a Uniform Resource Identifier (URI), as described in Section 4.

One design goal of HTTP is to separate resource identification from request semantics. This is possible because the request semantics live in the request method (Section 9) and a few request-modifying header fields. A resource cannot treat a request in a way that's inconsistent with the semantics of the request's method. For example, even if a resource's URI implies semantics that aren't safe, a client can expect the resource to avoid unsafe actions when processing a request with a safe method (see Section 9.2.1) ๐Ÿ™ˆ

HTTP relies on the Uniform Resource Identifier (URI) standard [URI] to indicate the target resource (Section 7.1) and the relationships between resources ๐Ÿ”—

3.2. Representations ๐Ÿฆ‹

A "representation" is information meant to reflect a past, current, or desired state of a given resource, in a format that can be easily communicated via the protocol. A representation is made up of a set of representation metadata and a potentially unbounded stream of representation data (Section 8) ๐Ÿ“ฆ

HTTP allows "information hiding" behind its uniform interface. It does this by describing communication in terms of a transferable representation of the resource state, instead of transferring the resource itself ๐Ÿซฃ That means the resource identified by a URI can be pretty much anything, even temporal stuff like "the current weather in Laguna Beach", while still giving info that represents the resource at the time a message is generated [REST]. iconic ๐Ÿ˜ญ

The uniform interface is kind of like a window. You can observe and act on a thing only by sending messages to an independent actor on the other side. So we need a shared abstraction that "takes the place of" the current or desired state of that thing in our communications. When a representation is hypertext, it can provide both a representation of the resource state and processing instructions that help guide the recipient's future interactions ๐ŸชŸ

A target resource might be provided with, or be capable of generating, multiple representations that each try to reflect the resource's current state. An algorithm, usually based on content negotiation (Section 12), is used to pick the one representation that's most applicable to a given request. This "selected representation" provides the data and metadata for evaluating conditional requests (Section 13) and for building the content of 200 (OK), 206 (Partial Content), and 304 (Not Modified) responses to GET (Section 9.3.1) ๐Ÿ’…

3.3. Connections, Clients, and Servers ๐Ÿ”Œ

HTTP is a client/server protocol that operates over a reliable transport- or session-layer "connection" ๐Ÿงต

An HTTP "client" is a program that establishes a connection to a server so it can send one or more HTTP requests. An HTTP "server" is a program that accepts connections in order to service HTTP requests by sending HTTP responses ๐Ÿค

The terms client and server only refer to the roles these programs play for a particular connection. The same program might be a client on some connections and a server on others ๐Ÿ”„

HTTP is defined as a stateless protocol. That means each request message's semantics can be understood in isolation, and the relationship between connections and the messages on them has no impact on how those messages are interpreted. For example, a CONNECT request (Section 9.3.6) or a request with the Upgrade header field (Section 7.8) can happen at any time, not just in the first message on a connection. Lots of implementations depend on HTTP's stateless design to reuse proxied connections or to dynamically load balance requests across multiple servers โš–๏ธ

So, a server MUST NOT assume that two requests on the same connection come from the same user agent, unless the connection is secured and specific to that agent. Some non-standard HTTP extensions (e.g., [RFC4559]) have been known to break this requirement, which caused security and interoperability problems ๐Ÿ˜ฌ this is a serious one, bestie ๐Ÿšจ

3.4. Messages ๐Ÿ’Œ

HTTP is a stateless request/response protocol for exchanging "messages" across a connection. The terms "sender" and "recipient" refer to any implementation that sends or receives a given message, respectively ๐Ÿ“จ

A client sends requests to a server in the form of a "request" message with a method (Section 9) and a request target (Section 7.1). The request might also contain header fields (Section 6.3) for request modifiers, client information, and representation metadata. It can carry content (Section 6.4) meant to be processed according to the method, plus trailer fields (Section 6.5) that communicate information collected while sending the content ๐ŸŽ

A server responds to a client's request by sending one or more "response" messages, each including a status code (Section 15) โœจ The response might also contain header fields for server information, resource metadata, and representation metadata. It can carry content that gets interpreted according to the status code, plus trailer fields that communicate information collected while sending the content ๐ŸŒŸ

3.5. User Agents ๐Ÿงš

The term "user agent" refers to any of the various client programs that initiate a request ๐Ÿ™‹

The most familiar user agent is the general-purpose Web browser, but that's only a small percentage of implementations. Other common user agents include spiders (web-traversing robots), command-line tools, billboard screens, household appliances, scales, light bulbs, firmware update scripts, mobile apps, and communication devices in a multitude of shapes and sizes ๐Ÿค–๐Ÿ’ก it's giving everything

Being a user agent doesn't mean a human is directly interacting with the software at the time of a request. In lots of cases, a user agent is installed or configured to run in the background and save its results for later inspection (or to save only the subset of results that might be interesting or erroneous). Spiders, for example, are usually given a start URI and configured to follow certain behavior while crawling the Web as a hypertext graph ๐Ÿ•ท๏ธ

Many user agents can't, or choose not to, make interactive suggestions to their user or give adequate warnings about security or privacy concerns. In the few cases where this specification requires reporting errors to the user, it's acceptable for that reporting to only be visible in an error console or log file ๐Ÿ“ Likewise, if a requirement says an automated action has to be confirmed by the user before proceeding, it might be met through advance configuration choices, run-time options, or simply avoiding the unsafe action altogether. Confirmation doesn't imply any specific user interface or interruption of normal processing if the user has already made that choice ๐Ÿ’–

3.6. Origin Server ๐Ÿ‘‘

The term "origin server" refers to a program that can originate authoritative responses for a given target resource ๐Ÿ›๏ธ

The most familiar origin servers are large public websites. But just like user agents being equated with browsers, it's easy to think all origin servers are the same. Common origin servers also include home automation units, configurable networking components, office machines, autonomous robots, news feeds, traffic cameras, real-time ad selectors, and video-on-demand platforms ๐ŸŽฌ

Most HTTP communication is a retrieval request (GET) for a representation of some resource identified by a URI. In the simplest case, this happens over a single bidirectional connection (===) between the user agent (UA) and the origin server (O) ๐Ÿช„

            request   >
       UA ======================================= O
                                   <   response

                                  Figure 1

3.7. Intermediaries ๐Ÿฆ‹

okay so HTTP lets intermediaries step in and help satisfy requests along a whole chain of connections ๐Ÿ”—โœจ There are three common flavours: proxy, gateway, and tunnel. Sometimes one single intermediary can be an origin server, a proxy, a gateway, or a tunnel, switching roles depending on each request ๐Ÿ’…

            >             >             >             >
       UA =========== A =========== B =========== C =========== O
                  <             <             <             <

                                  Figure 2

Figure 2 shows three intermediaries (A, B, and C) sitting between the user agent and the origin server ๐ŸŽ€ A request or response that travels the whole chain goes through four separate connections, so it's a lot of hops bestie ๐Ÿ˜ญ Some HTTP options might only apply to the connection with the nearest, non-tunnel neighbour, some only to the endpoints of the chain, and some to every connection along the way ๐Ÿงš The diagram looks linear, but everyone can be juggling multiple conversations at once. For example, B might be getting requests from clients other than A and/or forwarding requests to servers other than C, all while it's handling A's request ๐Ÿ™ˆ And later requests can take a totally different path through the connections, often based on dynamic configuration for load balancing. main character routing energy ๐Ÿ‘‘

The terms "upstream" and "downstream" describe directional requirements relative to the message flow. All messages flow from upstream to downstream ๐ŸŒŠ The terms "inbound" and "outbound" describe directional requirements relative to the request route. Inbound means "toward the origin server", and outbound means "toward the user agent" ๐Ÿฆ‹

A "proxy" is a message-forwarding agent that the client chooses, usually through local configuration rules ๐Ÿ”ง It receives requests for some type(s) of absolute URI and tries to satisfy them by translating through the HTTP interface. Some translations are minimal, like proxy requests for "http" URIs. Others might need translation to and from completely different application-level protocols ๐ŸŒˆ Proxies are often used to group an organisation's HTTP requests through one common intermediary, for security services, annotation services, or shared caching ๐Ÿ” Some proxies apply transformations to selected messages or content while they're being forwarded, as described in Section 7.7 โœจ

A "gateway" (a.k.a. "reverse proxy") is an intermediary that acts as an origin server for the outbound connection, but translates received requests and forwards them inbound to another server or servers ๐Ÿชž Gateways are often used to encapsulate legacy or untrusted information services, to improve server performance through "accelerator" caching, and to enable partitioning or load balancing of HTTP services across multiple machines ๐Ÿ’–

All HTTP requirements that apply to an origin server also apply to the outbound communication of a gateway ๐Ÿ’… A gateway talks to inbound servers using any protocol it likes, including private extensions to HTTP that are outside the scope of this specification ๐Ÿซถ However, an HTTP-to-HTTP gateway that wants to interoperate with third-party HTTP servers needs to conform to user agent requirements on the gateway's inbound connection. it has to be a good guest ๐ŸŽ€

A "tunnel" acts as a blind relay between two connections and doesn't change the messages ๐Ÿš‡ Once it's active, a tunnel isn't considered a party to the HTTP communication, even though it might have been started by an HTTP request ๐Ÿ™ˆ A tunnel stops existing when both ends of the relayed connection are closed. Tunnels are used to extend a virtual connection through an intermediary, such as when Transport Layer Security (TLS, [TLS13]) is used to set up confidential communication through a shared firewall proxy ๐Ÿ”’

The categories above only cover intermediaries that take part in the HTTP communication. There are also intermediaries that act on lower layers of the network protocol stack, filtering or redirecting HTTP traffic without the knowledge or permission of the message senders ๐Ÿ‘€ > Network intermediaries are indistinguishable (at a protocol level) from an on-path attacker, and they often introduce security flaws or interoperability problems by mistakenly violating HTTP semantics. this is the part where you should be scared ๐Ÿ˜ญ

For example, an "interception proxy" [RFC3040] (also commonly known as a "transparent proxy" [RFC1919]) differs from an HTTP proxy because it is not chosen by the client ๐Ÿ•ต๏ธ Instead, an interception proxy filters or redirects outgoing TCP port 80 packets (and occasionally other common port traffic). They're commonly found on public network access points, as a way of enforcing account subscription before you can use non-local Internet services, and inside corporate firewalls to enforce network usage policies ๐Ÿ’ผ


3.8. Caches ๐ŸŒธ

A "cache" is a local store of previous response messages, plus the subsystem that controls its message storage, retrieval, and deletion ๐Ÿ—„๏ธ A cache stores cacheable responses so that the response time and network bandwidth consumption get reduced for future, equivalent requests ๐Ÿš€ Any client or server MAY employ a cache, though a cache cannot be used while acting as a tunnel. tunnels are cache-free zones, sorry not sorry ๐Ÿ™…โ€โ™€๏ธ

The effect of a cache is that the request/response chain gets shortened if one of the participants along the chain has a cached response applicable to that request โœ‚๏ธ The figure below shows the resulting chain if B has a cached copy of an earlier response from O (via C) for a request that hasn't been cached by UA or A.

            >             >
       UA =========== A =========== B - - - - - - C - - - - - - O
                  <             <

                                  Figure 3

A response is "cacheable" if a cache is allowed to store a copy of the response message for use in answering subsequent requests ๐Ÿ’พ Even when a response is cacheable, the client or the origin server might place additional constraints on when that cached response can be used for a particular request ๐Ÿง HTTP requirements for cache behaviour and cacheable responses are defined in [CACHING] ๐Ÿ“š

There is a wide variety of cache architectures and configurations across the World Wide Web and inside large organisations ๐ŸŒ These include national hierarchies of proxy caches to save bandwidth and reduce latency, content delivery networks that use gateway caching to optimise regional and global distribution of popular sites, collaborative systems that broadcast or multicast cache entries, archives of pre-fetched cache entries for use in off-line or high-latency environments, and so on ๐Ÿงš


3.9. Example Message Exchange ๐Ÿ’œ

okay let's see it in action ๐ŸŽฌ The following example shows a typical HTTP/1.1 message exchange for a GET request (Section 9.3.1) on the URI http://www.example.com/hello.txt:

Client request:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.64.1
Host: www.example.com
Accept-Language: en, mi

Server response:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

Hello World! My content includes a trailing CRLF.

4. Identifiers in HTTP โœจ

okay the identifier era ๐Ÿชช Uniform Resource Identifiers (URIs) [URI] are used all throughout HTTP as the way to identify resources (Section 3.1) ๐ŸŒˆ

4.1. URI References ๐ŸŽ€

URI references are used to target requests, indicate redirects, and define relationships. they're basically the glue of the web ๐Ÿซถ

The definitions of "URI-reference", "absolute-URI", "relative-part", "authority", "port", "host", "path-abempty", "segment", and "query" are adopted from the URI generic syntax ๐Ÿค An "absolute-path" rule is defined for protocol elements that can contain a non-empty path component. (This rule differs slightly from the path-abempty rule of RFC 3986, which allows for an empty path, and from the path-absolute rule, which does not allow paths that begin with "//".) A "partial-URI" rule is defined for protocol elements that can contain a relative URI but not a fragment component ๐Ÿงฉ

  URI-reference = <URI-reference, see [URI], Section 4.1>
  absolute-URI  = <absolute-URI, see [URI], Section 4.3>
  relative-part = <relative-part, see [URI], Section 4.2>
  authority     = <authority, see [URI], Section 3.2>
  uri-host      = <host, see [URI], Section 3.2.2>
  port          = <port, see [URI], Section 3.2.3>
  path-abempty  = <path-abempty, see [URI], Section 3.3>
  segment       = <segment, see [URI], Section 3.3>
  query         = <query, see [URI], Section 3.4>

  absolute-path = 1*( "/" segment )
  partial-URI   = relative-part [ "?" query ]

Each protocol element in HTTP that allows a URI reference will say in its ABNF production whether it allows any form of reference (URI-reference), only a URI in absolute form (absolute-URI), only the path and optional query components (partial-URI), or some combination of the above ๐Ÿ—บ๏ธ Unless otherwise indicated, URI references are parsed relative to the target URI (Section 7.1) ๐Ÿ“

It is RECOMMENDED that all senders and recipients support, at a minimum, URIs with lengths of 8000 octets in protocol elements. Note that this implies some structures and on-wire representations (for example, the request line in HTTP/1.1) will necessarily be larger in some cases ๐Ÿ“

IANA maintains the registry of URI Schemes [BCP35] at <https://www.iana.org/assignments/uri-schemes/>. Although requests might target any URI scheme, the following schemes are inherent to HTTP servers ๐Ÿ“‹

+============+====================================+=========+
| URI Scheme | Description                        | Section |
+============+====================================+=========+
| http       | Hypertext Transfer Protocol        | 4.2.1   |
+------------+------------------------------------+---------+
| https      | Hypertext Transfer Protocol Secure | 4.2.2   |
+------------+------------------------------------+---------+

                              Table 2

Note that the presence of an "http" or "https" URI does not imply that there is always an HTTP server at the identified origin listening for connections ๐Ÿ™ƒ Anyone can mint a URI, whether or not a server exists and whether or not that server currently maps that identifier to a resource ๐Ÿช„ The delegated nature of registered names and IP addresses creates a federated namespace whether or not an HTTP server is present ๐ŸŒ

4.2.1. http URI Scheme ๐ŸŒธ

okay so the "http" URI scheme is defined right here ๐Ÿ’– It's for minting identifiers inside the hierarchical namespace run by a potential HTTP origin server, one that's listening for TCP ([TCP]) connections on a given port. Maybe there's a server there, maybe there isn't, but the name lives in that namespace ๐Ÿฆ‹

  http-URI = "http" "://" authority path-abempty [ "?" query ]

The origin server for an "http" URI is identified by the authority component. That includes a host identifier ([URI], Section 3.2.2) and an optional port number ([URI], Section 3.2.3). If the port subcomponent is empty or just not given, TCP port 80 (the reserved port for WWW services) is the default ๐ŸŽ€. The origin decides who has the right to respond authoritatively to requests aimed at the identified resource, as defined in Section 4.3.2 ๐Ÿ’….

ok but bestie, a sender MUST NOT generate an "http" URI with an empty host identifier ๐Ÿ™…โ€โ™€๏ธ And if a recipient gets one anyway, it MUST reject it as invalid. no exceptions, no vibes-based parsing ๐Ÿ’€

The hierarchical path component and the optional query component identify the target resource within that origin server's namespace โœจ

4.2.2. https URI Scheme ๐Ÿ”

the "https" URI scheme is also defined here ๐ŸŽ‰ It's basically the same energy, minting identifiers in the hierarchical namespace governed by a potential origin server listening for TCP connections on a given port. The difference is the glow-up: that server also has to be capable of setting up a TLS ([TLS13]) connection that's been secured for HTTP communication ๐ŸŒˆ

In this context, "secured" has a very specific meaning. The server has been authenticated as acting on behalf of the identified authority, AND all HTTP communication with that server has confidentiality and integrity protection that's acceptable to both client and server ๐Ÿซถ

  https-URI = "https" "://" authority path-abempty [ "?" query ]

The origin server for an "https" URI is also identified by the authority component, with a host identifier ([URI], Section 3.2.2) and an optional port number ([URI], Section 3.2.3). If the port subcomponent is empty or not given, TCP port 443 (the reserved port for HTTP over TLS) is the default ๐Ÿ”’ The origin determines who has the right to respond authoritatively to requests for the identified resource, as defined in Section 4.3.3.

A sender MUST NOT generate an "https" URI with an empty host identifier ๐Ÿ™…โ€โ™€๏ธ A recipient that processes such a URI reference MUST reject it as invalid, same as with "http" ๐Ÿ’…

The hierarchical path component and optional query component identify the target resource within that origin server's namespace ๐Ÿฆ‹

A client MUST ensure that its HTTP requests for an "https" resource are secured before they're communicated, and that it only accepts secured responses to those requests. Also, the cryptographic mechanisms that are acceptable to client and server are usually negotiated, and they can change over time ๐Ÿ”„

Resources on the "https" scheme have no shared identity with the "http" scheme. They're distinct origins with separate namespaces, so no mixing them up ๐Ÿ™ˆ Still, extensions to HTTP that apply to all origins with the same host, like the Cookie protocol [COOKIE], let information set by one service impact communication with other services in a matching group of host domains. Those extensions ought to be designed with great care to stop information from a secured connection getting inadvertently exchanged within an unsecured context ๐Ÿšจ

4.2.3. http(s) Normalization and Comparison ๐Ÿ’œ

URIs with an "http" or "https" scheme are normalized and compared according to the methods defined in Section 6 of [URI], using the defaults described above for each scheme. It's giving tidy-up energy ๐Ÿงน

HTTP does not require a specific method for determining equivalence. For example, a cache key might be compared as a simple string, after syntax-based normalization, or after scheme-based normalization ๐Ÿ“

Scheme-based normalization (Section 6.2.3 of [URI]) of "http" and "https" URIs involves these extra rules:

  • If the port is equal to the default port for a scheme, the normal form is to omit the port subcomponent.
  • When not being used as the target of an OPTIONS request, an empty path component is equivalent to an absolute path of "/", so the normal form is to provide a path of "/" instead.
  • The scheme and host are case-insensitive and normally provided in lowercase; all other components are compared in a case-sensitive manner.
  • Characters other than those in the "reserved" set are equivalent to their percent-encoded octets: the normal form is to not encode them (see Sections 2.1 and 2.2 of [URI]).

For example, these three URIs are equivalent โœจ

      http://example.com:80/~smith/home.html
      http://EXAMPLE.com/%7Esmith/home.html
      http://EXAMPLE.com:/%7esmith/home.html

Two HTTP URIs that are equivalent after normalization (using any method) can be assumed to identify the same resource, and any HTTP component MAY perform normalization ๐Ÿ‘‘ As a result, distinct resources SHOULD NOT be identified by HTTP URIs that are equivalent after normalization (using any method defined in Section 6.2 of [URI]). so don't give two different things the same-looking address, bestie ๐Ÿ™

4.2.4. Deprecation of userinfo in http(s) URIs ๐Ÿ™…โ€โ™€๏ธ

The URI generic syntax for authority also includes a userinfo subcomponent ([URI], Section 3.2.1) for putting user authentication information in the URI. The "user:password" format inside that subcomponent is deprecated, so we're moving on from it ๐Ÿ‘‹

Some implementations use the userinfo component for internal configuration of authentication information, like in command invocation options, configuration files, or bookmark lists. Even so, that usage might expose a user identifier or password ๐Ÿ˜ญ

A sender MUST NOT generate the userinfo subcomponent (and its "@" delimiter) when an "http" or "https" URI reference is generated within a message as a target URI or field value. no "@" sneaking in, period ๐Ÿšซ

Before making use of an "http" or "https" URI reference received from an untrusted source, a recipient SHOULD parse for userinfo and treat its presence as an error. Its presence is a red flag because it's likely being used to hide the real authority for phishing attacks ๐ŸŽฃ

4.2.5. http(s) References with Fragment Identifiers ๐Ÿงš

Fragment identifiers let you indirectly identify a secondary resource, no matter the URI scheme, as defined in Section 3.5 of [URI]. Some protocol elements that refer to a URI allow a fragment to be included, while others don't. You can tell them apart by the ABNF rule: elements where a fragment is allowed use one rule, and the others use a specific rule that excludes fragments ๐Ÿฆ‹

Note: The fragment identifier component isn't part of the scheme definition for a URI scheme (see Section 4.3 of [URI]). That's why it doesn't show up in the ABNF definitions for the "http" and "https" URI schemes above ๐Ÿค“

4.3. Authoritative Access ๐Ÿ”‘

Authoritative access means dereferencing a given identifier to access the identified resource, in a way the client believes is authoritative, which means controlled by the resource owner ๐Ÿ‘‘ The URI scheme defines how access is granted, and that process often uses data inside the URI components, like the authority component when the generic syntax is used. Still, authoritative access isn't limited to that one mechanism โœจ

Section 4.3.1 defines the concept of an origin as a helper for these uses, and the subsections after it explain how to establish that a peer has the authority to represent an origin ๐Ÿ’–

See Section 17.1 for security considerations related to establishing authority ๐Ÿšจ

4.3.1. URI Origin ๐ŸŒ

The "origin" for a given URI is the triple of scheme, host, and port, after normalizing the scheme and host to lowercase and normalizing the port to remove any leading zeros. If the port is elided from the URI, the default port for that scheme is used. For example, this URI:

      https://Example.Com/happy.js

would have the origin:

      { "https", "example.com", "443" }

which can also be written as the normalized URI prefix with the port always present:

      https://example.com:443

Each origin defines its own namespace and controls how identifiers within that namespace are mapped to resources ๐Ÿ—บ๏ธ How the origin responds to valid requests, consistently over time, determines the semantics users associate with a URI. The usefulness of those semantics is what ultimately turns these mechanisms into a resource people can reference and access later ๐ŸŒŸ

Two origins are distinct if they differ in scheme, host, or port. Even when it can be verified that the same entity controls two distinct origins, the two namespaces under those origins are distinct unless a server authoritative for that origin explicitly aliases them ๐Ÿ™ƒ

Origin is also used within HTML and related Web protocols, which are beyond the scope of this document, as described in [RFC6454] ๐Ÿ’…

4.3.2. http Origins ๐Ÿฆ‹

Although HTTP is independent of the transport protocol, the "http" scheme (Section 4.2.1) is specific to associating authority with whoever controls the origin server listening for TCP connections on the indicated port of whatever host is identified in the authority component. This is a very weak sense of authority ๐Ÿ˜ฌ It depends on client-specific name resolution mechanisms, and on communication that might not be secured from an on-path attacker. Still, it's a sufficient minimum for binding "http" identifiers to an origin server for consistent resolution within a trusted environment ๐Ÿซถ

If the host identifier is an IP address, the origin server is the listener (if any) on the indicated TCP port at that IP address. If the host is a registered name, that name is an indirect identifier for use with a name resolution service, such as DNS, to find an address for an appropriate origin server ๐Ÿงญ

When an "http" URI is used in a context that calls for access to the indicated resource, a client MAY attempt access. It does this by resolving the host identifier to an IP address, establishing a TCP connection to that address on the indicated port, and sending over that connection an HTTP request message. That request has a request target matching the client's target URI (Section 7.1) ๐Ÿ“จ

If the server responds to such a request with a non-interim HTTP response message, as described in Section 15, then that response is considered an authoritative answer to the client's request ๐Ÿ’ฏ

Note, however, that the above is not the only way to get an authoritative response, and it doesn't mean an authoritative response is always necessary (see [CACHING]) ๐Ÿค” For example, the Alt-Svc header field [ALTSVC] lets an origin server identify other services that are also authoritative for that origin. Access to "http" identified resources might also be provided by protocols outside the scope of this document ๐ŸŒˆ

4.3.3. https Origins โœจ

okay so the "https" scheme (Section 4.2.2) is all about trust. a server gets authority because it can use the private key that goes with a certificate the client finds trustworthy for that origin server ๐Ÿ” the client usually leans on a chain of trust that starts from some prearranged or configured trust anchor, and that's how it decides a certificate is trustworthy (Section 4.3.4) ๐Ÿงš

in HTTP/1.1 and earlier, a client only gives a server authority when they're talking over a connection that got successfully established and secured, and that connection goes specifically to the host in that URI origin. the connection setup and the certificate check together count as the proof ๐Ÿ’…

in HTTP/2 and HTTP/3 it's a little more relaxed ๐Ÿฆ‹ a client gives a server authority when it's on a successfully established and secured connection and the URI origin's host matches any of the hosts listed in the server's certificate, AND the client believes it could open a connection to that host for that URI. in practice the client does a DNS query to check that the origin's host resolves to the same server IP address as the connection it already has. this restriction can be lifted if the origin server sends an equivalent ORIGIN frame [RFC8336] โœจ

the request target's host and port value get sent inside every HTTP request. that's how the origin is identified and kept separate from other namespaces the same server might control (Section 7.2) ๐Ÿ“ it's on the origin to make sure any services that get control over its certificate's private key are just as responsible for managing the matching "https" namespaces, or at least ready to reject requests that look misdirected (Section 7.4) ๐Ÿซถ

an origin server might not want to process requests for certain target URIs even when it has the authority to do so ๐Ÿ™ˆ for example, when one host runs different services on different ports (like 443 and 8000), the origin server has to check the target URI (even after the connection is secured) because a network attacker might get connections meant for one port delivered to some other port. if nobody checks, that attacker could swap a response for one target URI (like "https://example.com/foo") with a seemingly authoritative response from the other port (like "https://example.com:8000/foo") ๐Ÿ˜ญ

the "https" scheme doesn't rely on TCP or the connected port number to link up authority, because both sit outside the secured communication and so can't be trusted as definitive ๐Ÿ’€ that means the HTTP communication can happen over any channel that's been secured (as defined in Section 4.2.2), including protocols that don't use TCP at all ๐ŸŒˆ

when an "https" URI gets used somewhere that calls for access to the resource it points at, a client MAY try access by resolving the host identifier to an IP address, opening a TCP connection to that address on the indicated port, securing that connection end-to-end by successfully starting TLS over TCP with confidentiality and integrity protection, and then sending over that connection an HTTP request message whose request target matches the client's target URI (Section 7.1) ๐ŸŽ€

if the server answers that request with a non-interim HTTP response message (see Section 15), then that response counts as an authoritative answer to the client's request ๐Ÿ‘‘

BUT the above isn't the only way to get an authoritative response, and it doesn't mean an authoritative response is always needed either (see [CACHING]) ๐Ÿง 


4.3.4. https Certificate Verification

to set up a secured connection so it can dereference a URI, a client MUST verify that the service's identity is an acceptable match for the URI's origin server ๐Ÿ” certificate verification is what stops server impersonation, whether it comes from an on-path attacker or from an attacker who controls name resolution. this process needs the client to be configured with a set of trust anchors ๐Ÿงš

generally speaking, a client MUST verify the service identity using the verification process defined in Section 6 of [RFC6125] ๐Ÿ’… the client MUST also build a reference identity from the service's host. if the host is a literal IP address (Section 4.3.5), the reference identity is an IP-ID. otherwise the host is a name, and the reference identity is a DNS-ID ๐ŸŒธ

a reference identity of type CN-ID MUST NOT be used by clients ๐Ÿšซ as noted in Section 6.2.1 of [RFC6125], a CN-ID reference identity might still get used by older clients ๐Ÿฆ–

a client might be specially configured to accept a different form of server identity verification โœจ for example, a client might be connecting to a server whose address and hostname are dynamic, with the expectation that the service will present a specific certificate (or a certificate matching some externally defined reference identity) instead of one matching the target URI's origin ๐ŸŒˆ

in special cases it might make sense for a client to just ignore the server's identity, but it has to be understood that this leaves the connection open to active attack ๐Ÿ˜ฌโš ๏ธ

if the certificate isn't valid for the target URI's origin, a user agent MUST either get confirmation from the user before going ahead (see Section 3.5) or end the connection with a bad certificate error ๐Ÿ™…โ€โ™€๏ธ automated clients MUST log the error to an appropriate audit log (if there is one available) and SHOULD end the connection (with a bad certificate error) ๐Ÿ“ automated clients MAY offer a configuration setting that turns this check off, but they MUST offer a setting that turns it on ๐Ÿ’œ


4.3.5. IP-ID Reference Identity

a server that's identified with an IP address literal in the "host" field of an "https" URI has a reference identity of type IP-ID ๐Ÿงš an IP version 4 address uses the "IPv4address" ABNF rule, and an IP version 6 address uses the "IP-literal" production with the "IPv6address" option (see Section 3.2.2 of [URI]). a reference identity of IP-ID holds the decoded bytes of the IP address ๐Ÿ”ข

an IP version 4 address is 4 octets, and an IP version 6 address is 16 octets ๐ŸŒˆ IP-ID isn't defined for any other IP version ๐Ÿ™…โ€โ™€๏ธ the iPAddress choice in the certificate subjectAltName extension doesn't explicitly say which IP version it is, so it relies on the length of the address to tell the versions apart (see Section 4.2.1.6 of [RFC5280]) ๐Ÿค“

a reference identity of type IP-ID matches if the address is identical to an iPAddress value in the certificate's subjectAltName extension โœจ๐Ÿ’–


5. Fields ๐ŸŽ€

HTTP uses "fields" to carry data as extensible name/value pairs with a registered key namespace ๐Ÿ’… fields get sent and received inside the header and trailer sections of messages (Section 6) ๐Ÿ’Œ


5.1. Field Names ๐Ÿท๏ธ

a field name labels its field value so you know what semantics it has ๐Ÿง  for example, the Date header field is defined in Section 6.6.1 as holding the origination timestamp for the message it shows up in ๐Ÿ•ฐ๏ธ

field-name     = token

field names are case-insensitive, and they ought to get registered in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" (see Section 16.3.1) ๐Ÿ“š

the meaning of a field doesn't change between minor versions of the same major HTTP version, though the default behavior of a recipient when that field is missing can change ๐Ÿ”„ unless it says otherwise, fields are defined for all versions of HTTP ๐ŸŒธ in particular, the Host and Connection fields ought to be recognized by every HTTP implementation, whether or not it claims to conform with HTTP/1.1 ๐Ÿซถ

new fields can be introduced without changing the protocol version, as long as their defined semantics let recipients that don't recognize them safely ignore them (see Section 16.3) ๐Ÿฆ‹

a proxy MUST forward unrecognized header fields unless the field name is listed in the Connection header field (Section 7.6.1), or the proxy is specifically configured to block or otherwise transform those fields ๐Ÿšช other recipients SHOULD ignore unrecognized header and trailer fields ๐Ÿ™ˆ following these requirements is what lets HTTP keep getting extended without anyone having to update or remove the intermediaries already out there ๐Ÿ“โœจ


5.2. Field Lines and Combined Field Value ๐Ÿงฉ

field sections are made up of any number of "field lines" ๐Ÿ’… each one has a "field name" (see Section 5.1) that identifies the field, and a "field line value" that carries the data for that particular instance of the field ๐ŸŒท

when a field name only shows up once in a section, the combined "field value" for that field is just that field line's value ๐Ÿซง when a field name repeats within a section, its combined field value is the list of its field line values in that section, joined together in order with a comma between each one ๐Ÿ”—

here's an example of that ๐Ÿ‘‡

Example-Field: Foo, Bar
Example-Field: Baz

this section has two field lines, and they both use the field name "Example-Field" ๐ŸŽ€ the first field line value is "Foo, Bar", and the second is "Baz" ๐ŸŒˆ so the field value for "Example-Field" comes out as the list "Foo, Bar, Baz" ๐Ÿ’œ


5.3. Field Order ๐Ÿ“‹

a recipient MAY combine multiple field lines in a field section that share the same field name into one field line, and that doesn't change the message's semantics ๐Ÿงƒ you do it by appending each following field line value to the first one, in order, separated by a comma (",") and optional whitespace (OWS, defined in Section 5.6.3) โœจ for consistency, use comma SP ๐Ÿ’–

the order that field lines with the same name arrive in really matters for what the field value means ๐Ÿง  so a proxy MUST NOT change the order of those field line values when it forwards a message ๐Ÿšซ

that means (apart from the well-known exception below) a sender MUST NOT generate multiple field lines with the same name in a message (whether in the headers or trailers), and it MUST NOT append a field line when a field line with the same name is already in the message ๐Ÿ™…โ€โ™€๏ธ the only exception is when the field's definition lets multiple field line values be recombined as a comma-separated list. that means at least one option in the field's definition has to allow a comma-separated list, like an ABNF rule of #(values) defined in Section 5.6.1 ๐Ÿงฉ

Note: In practice, the "Set-Cookie" header field ([COOKIE]) often shows up across multiple field lines in a response message, and it doesn't use list syntax. that breaks the rules above about multiple field lines with the same field name ๐Ÿ˜ญ since it can't be combined into a single field value, recipients ought to handle "Set-Cookie" as a special case while processing fields ๐Ÿช (See Appendix A.2.3 of [Kri2001] for details.)

the order that field lines with different field names come in within a section doesn't matter ๐Ÿคทโ€โ™€๏ธ still, it's good practice to send header fields that carry extra control data first, like Host on requests and Date on responses, so implementations can decide as early as possible when not to handle a message ๐Ÿšฆ

a server MUST NOT apply a request to the target resource until it has received the entire request header section ๐Ÿ›‘ that's because later header field lines might include conditionals, authentication credentials, or sneaky misleading duplicate header fields that could change how the request gets processed ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ’…

5.4. Field Limits โœจ

okay so HTTP doesn't put a set limit on how long each field line is, or on each field value, or on a whole header or trailer section ๐Ÿ™ˆ (that's what Section 2 is about). People do add their own little limits in the real world, often depending on what the field is for ๐Ÿ’…

if a server gets a request header field line, field value, or group of fields that's bigger than it wants to deal with, it MUST respond with an appropriate 4xx (Client Error) status code ๐Ÿšซ ignoring those headers would make the server way more vulnerable to request smuggling attacks (Section 11.2 of [HTTP/1.1]), so don't be that server ๐Ÿ’€

clients get a little more freedom ๐Ÿฆ‹ a client MAY discard or truncate received field lines that are bigger than it wants to process, but only if the field's meaning is such that the dropped value(s) can be safely ignored without messing up the message framing or response semantics ๐ŸŒธ

5.5. Field Values ๐ŸŽ€

HTTP field values are a sequence of characters in a format that the field's grammar defines. Each field's grammar is usually written in ABNF ([RFC5234]) ๐Ÿงš

field-value    = *field-content
field-content  = field-vchar
                 [ 1*( SP / HTAB / field-vchar ) field-vchar ]
field-vchar    = VCHAR / obs-text
obs-text       = %x80-FF

a field value doesn't include leading or trailing whitespace โœจ and when a specific HTTP version lets that whitespace show up in a message, a field parsing implementation MUST exclude it before it evaluates the field value ๐Ÿงน

field values are usually kept to the US-ASCII range ([USASCII]) ๐Ÿ“ fields that need more characters can use an encoding like the one in [RFC8187] ๐Ÿ’– historically, HTTP let field content carry text in the ISO-8859-1 charset ([ISO-8859-1]), and other charsets only worked through [RFC2047] encoding ๐Ÿ™ƒ for newly defined fields, the spec SHOULD limit values to visible US-ASCII octets (VCHAR), SP, and HTAB ๐Ÿซถ and a recipient SHOULD treat any other allowed octets in field content (that's obs-text) as opaque data, meaning it doesn't try to read into them ๐Ÿ‘€

okay now this part is serious bestie ๐Ÿ˜ญ field values with CR, LF, or NUL characters are invalid and dangerous, because implementations can parse and interpret those characters in all kinds of different ways ๐Ÿ’€ so a recipient that finds CR, LF, or NUL inside a field value MUST either reject the message or replace each of those characters with SP before it does any further processing or forwards the message ๐Ÿšจ field values with other CTL characters are invalid too, but recipients MAY keep those characters for robustness when they show up in a safe context (like an application-specific quoted string that no downstream HTTP parser will touch) ๐Ÿ”ฅ

fields that only expect one member as the value are called "singleton fields" ๐ŸŒˆ fields that take several members are called "list-based fields" ๐Ÿ‘‘ the list operator extension in Section 5.6.1 is the shared notation for defining field values that can hold multiple members โœจ

commas (",") are the delimiter between members, so they need extra care if they're allowed as data inside a member ๐Ÿซฃ this applies to both list-based and singleton fields, since a singleton might get sent with multiple members by mistake, and catching that kind of error makes things more interoperable ๐Ÿค fields that need a comma inside a member, like an HTTP-date or URI-reference element, ought to be defined with delimiters around that element so the comma in the data doesn't get mistaken for a list separator ๐ŸŽ€

here's an example. a textual date and a URI can both have commas in them, and they can still be safely carried in list-based field values like these ๐Ÿฆ‹

Example-URIs: "http://example.com/a.html,foo",
              "http://without-a-comma.example.com/"
Example-Dates: "Sat, 04 May 1996", "Wed, 14 Sep 2005"

quick reminder that double quotes are almost always paired with the quoted-string production (Section 5.6.4), so using a different syntax inside the double quotes will probably cause a lot of confusion ๐Ÿ˜ตโ€๐Ÿ’ซ

lots of fields (like Content-Type, from Section 8.3) use a shared parameter syntax, which lets a parameter value be unquoted (token) or quoted (quoted-string) (Section 5.6.6) ๐Ÿ’… using that common syntax means recipients can reuse the parser parts they already have ๐Ÿงฉ and if both forms are allowed, the meaning of a parameter value ought to be the same whether it came in as a token or as a quoted string โœจ

Note: for defining field value syntax, this spec uses an ABNF rule named after the field name to describe the allowed grammar for that field's value. that happens after the value has been pulled out of the underlying messaging syntax and multiple instances have been combined into a list ๐Ÿง 

5.6. Common Rules for Defining Field Values ๐Ÿ’œ

5.6.1. Lists (#rule ABNF Extension)

an extension called #rule gets added to the ABNF rules from [RFC5234] to make the list-based field value definitions way easier to read ๐Ÿ™Œ

there's a "#" construct, kind of like "*", for defining comma-delimited lists of elements. the full form is "<n>#<m>element", which means at least <n> and at most <m> elements, each separated by a single comma (",") and optional whitespace (OWS, defined in Section 5.6.3) ๐ŸŽ€

5.6.1.1. Sender Requirements

in any production that uses the list construct, a sender MUST NOT generate empty list elements ๐Ÿ™…โ€โ™€๏ธ in other words, a sender has to generate lists that follow this syntax:

1#element => element *( OWS "," OWS element )

and:

#element => [ 1#element ]

and for n >= 1 and m > 1:

<n>#<m>element => element <n-1>*<m-1>( OWS "," OWS element )

Appendix A has the collected ABNF for senders once the list constructs have been expanded ๐Ÿ“š

5.6.1.2. Recipient Requirements

empty elements don't count toward the number of elements present ๐Ÿซ  a recipient MUST parse and ignore a reasonable number of empty list elements. that's enough to handle common sender mistakes that merge values, but not so many that they could be abused as a denial-of-service mechanism ๐Ÿšซ so a recipient MUST accept lists that follow this syntax:

#element => [ element ] *( OWS "," OWS [ element ] )

because empty list elements can show up, the RFC 5234 ABNF can't enforce how many list elements there are. so every case gets mapped as if no cardinality was specified ๐Ÿคทโ€โ™€๏ธ

for example, with these ABNF productions:

example-list      = 1#example-list-elmt
example-list-elmt = token ; see Section 5.6.2

these are valid values for example-list (the double quotes aren't part of the value, they're just there to show where it starts and ends) ๐Ÿ’–

"foo,bar"
"foo ,bar,"
"foo , ,bar,charlie"

and these are invalid, since example-list needs at least one non-empty element ๐Ÿ’€

""
","
",   ,"

5.6.2. Tokens ๐Ÿงšโ€โ™€๏ธ

tokens are short textual identifiers with no whitespace or delimiters in them โœจ

token          = 1*tchar

tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
               / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
               / DIGIT / ALPHA
               ; any VCHAR, except delimiters

lots of HTTP field values are built from common syntax parts that are separated by whitespace or specific delimiting characters ๐ŸŒธ the delimiters come from the US-ASCII visual characters that aren't allowed in a token, which are DQUOTE and "(),/:;<=>?@[\]{}" ๐ŸŽ€

5.6.3. Whitespace ๐Ÿซง

this spec uses three rules for linear whitespace: OWS (optional whitespace), RWS (required whitespace), and BWS ("bad" whitespace) ๐Ÿฉท

the OWS rule covers places where zero or more linear whitespace octets might show up. when a protocol element prefers optional whitespace for readability, a sender SHOULD generate that optional whitespace as a single SP. otherwise, a sender SHOULD NOT generate optional whitespace, except when it's needed to overwrite invalid or unwanted protocol elements during in-place message filtering ๐Ÿงฝ

the RWS rule is for when at least one linear whitespace octet is required to separate field tokens. a sender SHOULD generate RWS as a single SP ๐Ÿ’…

OWS and RWS mean exactly the same thing as a single SP ๐Ÿค any content known to be OWS or RWS MAY be replaced with a single SP before it gets interpreted or forwarded downstream โœจ

the BWS rule is for places where the grammar only allows optional whitespace for historical reasons ๐Ÿ•ฐ๏ธ a sender MUST NOT generate BWS in messages, and a recipient MUST parse for that bad whitespace and remove it before interpreting the protocol element ๐Ÿ™…โ€โ™€๏ธ BWS has no semantics, so any content known to be BWS MAY be removed before it gets interpreted or forwarded ๐Ÿงน

OWS            = *( SP / HTAB )
               ; optional whitespace
RWS            = 1*( SP / HTAB )
               ; required whitespace
BWS            = OWS
               ; "bad" whitespace

5.6.4. Quoted Strings ๐Ÿ’ฌ

a string of text gets parsed as a single value if it's wrapped in double-quote marks ๐ŸŽ€

quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext         = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text

the backslash octet ("") works as a single-octet quoting mechanism inside quoted-string and comment constructs ๐Ÿฆ‹ recipients that process the value of a quoted-string MUST handle a quoted-pair as if it were replaced by the octet that follows the backslash ๐Ÿ”

quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )

a sender SHOULD NOT generate a quoted-pair in a quoted-string unless it's necessary to quote DQUOTE and backslash octets inside that string ๐Ÿ™ˆ and a sender SHOULD NOT generate a quoted-pair in a comment unless it's necessary to quote parentheses ["(" and ")"] and backslash octets inside that comment ๐Ÿซถ

5.6.5. Comments ๐ŸŒˆ

comments can go in some HTTP fields by wrapping the comment text in parentheses ๐Ÿง but they're only allowed in fields that have "comment" as part of their field value definition ๐Ÿ“

comment        = "(" *( ctext / quoted-pair / comment ) ")"
ctext          = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text

5.6.6. Parameters ๐Ÿฆ„

parameters are name/value pairs ๐ŸŽ€ they're often used in field values as a shared syntax for adding extra info to an item. each parameter is usually introduced by an immediately preceding semicolon ๐Ÿช„

parameters      = *( OWS ";" OWS [ parameter ] )
parameter       = parameter-name "=" parameter-value
parameter-name  = token
parameter-value = ( token / quoted-string )

parameter names are case-insensitive ๐Ÿ”ค parameter values might or might not be case-sensitive, depending on what the parameter name means ๐Ÿค” you can see examples of parameters, and some equivalent forms, in media types (Section 8.3.1) and in the Accept header field (Section 12.5.1) ๐Ÿ’œ

a parameter value that matches the token production can be sent either as a token or inside a quoted-string, and the quoted and unquoted versions are equivalent ๐ŸŒท

Note: parameters don't allow any whitespace (not even "bad" whitespace) around the "=" character ๐Ÿ™…โ€โ™€๏ธ

5.6.7. Date/Time Formats ๐Ÿ•ฐ๏ธโœจ

Okay so, before 1995 servers had like three different ways to write timestamps ๐Ÿ˜ญ For the sake of old implementations, all three are defined here. The preferred one is a fixed-length, single-zone slice of the date and time spec from the Internet Message Format [RFC5322] ๐Ÿ’…

    HTTP-date    = IMF-fixdate / obs-date

Here's an example of the preferred format:

    Sun, 06 Nov 1994 08:49:37 GMT    ; IMF-fixdate

And here are the two obsolete ones:

    Sunday, 06-Nov-94 08:49:37 GMT   ; obsolete RFC 850 format
    Sun Nov  6 08:49:37 1994         ; ANSI C's asctime() format

Okay, the big rule here: a recipient that parses a timestamp in an HTTP field MUST accept all three HTTP-date formats ๐Ÿซถ And when a sender generates a field with one or more timestamps defined as HTTP-date, the sender MUST generate those timestamps in the IMF-fixdate format. No vibes-based formatting, periodt ๐Ÿ™…โ€โ™€๏ธ

Now, an HTTP-date is an instance of Coordinated Universal Time (UTC) ๐ŸŒ The first two formats say so with "GMT", which is basically the older cousin of the UTC name ๐Ÿงš The asctime format doesn't say it out loud, so its values are just assumed to be UTC.

A "clock" is an implementation that can give a reasonable approximation of the current instant in UTC โฐ A clock implementation ought to use NTP ([RFC5905]), or some similar protocol, to sync up with UTC. Iconic behavior, honestly ๐Ÿ‘‘

Preferred format:

    IMF-fixdate  = day-name "," SP date1 SP time-of-day SP GMT
    ; fixed length/zone/capitalization subset of the format
    ; see Section 3.3 of [RFC5322]

    day-name     = %s"Mon" / %s"Tue" / %s"Wed"
                 / %s"Thu" / %s"Fri" / %s"Sat" / %s"Sun"

    date1        = day SP month SP year
                 ; e.g., 02 Jun 1982

    day          = 2DIGIT
    month        = %s"Jan" / %s"Feb" / %s"Mar" / %s"Apr"
                 / %s"May" / %s"Jun" / %s"Jul" / %s"Aug"
                 / %s"Sep" / %s"Oct" / %s"Nov" / %s"Dec"
    year         = 4DIGIT

    GMT          = %s"GMT"

    time-of-day  = hour ":" minute ":" second
                 ; 00:00:00 - 23:59:60 (leap second)

    hour         = 2DIGIT
    minute       = 2DIGIT
    second       = 2DIGIT

Obsolete formats (the throwback era ๐ŸŽ€):

    obs-date     = rfc850-date / asctime-date

    rfc850-date  = day-name-l "," SP date2 SP time-of-day SP GMT
    date2        = day "-" month "-" 2DIGIT
                 ; e.g., 02-Jun-82

    day-name-l   = %s"Monday" / %s"Tuesday" / %s"Wednesday"
                 / %s"Thursday" / %s"Friday" / %s"Saturday"
                 / %s"Sunday"

    asctime-date = day-name SP date3 SP time-of-day SP year
    date3        = month SP ( 2DIGIT / ( SP 1DIGIT ))
                 ; e.g., Jun  2

HTTP-date is case sensitive ๐Ÿง Note that Section 4.2 of [CACHING] relaxes this for cache recipients, which is a whole mood ๐Ÿฆ‹

A sender MUST NOT generate additional whitespace in an HTTP-date beyond what's specifically included as SP in the grammar. The meanings of day-name, day, month, year, and time-of-day are the same as the Internet Message Format constructs with the matching name ([RFC5322], Section 3.3). Same energy, different app ๐Ÿ’œ

Recipients of a timestamp in rfc850-date format, which uses a two-digit year, MUST interpret a timestamp that seems to be more than 50 years in the future as the most recent year in the past that had the same last two digits. Time-travel handling, but make it logical ๐ŸŒ€

Recipients of timestamp values are encouraged to be robust when parsing timestamps, unless the field definition restricts them otherwise. For example, messages sometimes get forwarded over HTTP from a non-HTTP source that might generate any of the date and time specifications defined by the Internet Message Format ๐Ÿ“ฌ

Note: HTTP requirements for timestamp formats apply only to their usage within the protocol stream. Implementations are not required to use these formats for user presentation, request logging, etc. ๐Ÿ’…

6. Message Abstraction ๐Ÿงฉ

Each major version of HTTP defines its own syntax for messages, which is very relatable honestly ๐Ÿ™ˆ This section defines an abstract data type for HTTP messages, built by generalizing their characteristics, common structure, and ability to convey semantics. The abstraction is used to write requirements for senders and recipients that don't depend on the HTTP version. That way, a message from one version can get relayed through other versions without changing its meaning ๐Ÿฆ‹

A "message" consists of the following:

  • control data to describe and route the message,
  • a headers lookup table of name/value pairs for extending that control data and conveying additional information about the sender, message, content, or context,
  • a potentially unbounded stream of content, and
  • a trailers lookup table of name/value pairs for communicating information obtained while sending the content.

Framing and control data get sent first, followed by a header section containing fields for the headers table. When a message includes content, that content is sent after the header section, and it might be followed by a trailer section with fields for the trailers table โœจ

Messages are meant to be processed as a stream, so the purpose of the stream reveals itself while you're reading it ๐Ÿ“– Control data tells the recipient what it needs to know right away, header fields describe what needs to be known before content arrives, the content (when present) usually has what the recipient wants or needs to fulfill the message semantics, and trailer fields are optional metadata that wasn't known until after the content was sent ๐ŸŽ€

Messages are supposed to be "self-descriptive": everything a recipient needs to know can be figured out by looking at the message itself, after decoding or rebuilding any parts that were compressed or left out in transit. You don't need to know the sender's current app state (set up by earlier messages) to get it. However, a client MUST retain knowledge of the request when parsing, interpreting, or caching a corresponding response. For example, responses to the HEAD method look just like the start of a response to GET, but they can't be parsed the same way ๐Ÿ™ƒ

Note that this message abstraction is a generalization across many versions of HTTP, including features that might not exist in some versions. For example, trailers were introduced within the HTTP/1.1 chunked transfer coding as a trailer section after the content. An equivalent feature exists in HTTP/2 and HTTP/3 within the header block that ends each stream ๐ŸŒธ

6.1. Framing and Completeness ๐Ÿชข

Message framing shows how each message begins and ends, so every message can be told apart from other messages or noise on the same connection ๐Ÿ’– Each major version of HTTP defines its own framing mechanism.

HTTP/0.9 and early deployments of HTTP/1.0 used closing the underlying connection to end a response ๐Ÿ™€ For backwards compatibility, this implicit framing is also allowed in HTTP/1.1. The catch is that implicit framing can fail to tell an incomplete response apart when the connection closes early. That's why almost all modern implementations use explicit framing, in the form of length-delimited sequences of message data ๐Ÿ’…

A message is considered "complete" when all of the octets indicated by its framing are available. Note that when no explicit framing is used, a response message that ends with the underlying connection closing is considered complete, even though it might look exactly like an incomplete response. The exception is if a transport-level error shows it isn't complete ๐Ÿ˜ฌ

6.2. Control Data ๐ŸŽ›๏ธ

Messages start with control data that describes their primary purpose. Request message control data includes a request method (Section 9), request target (Section 7.1), and protocol version (Section 2.5). Response message control data includes a status code (Section 15), an optional reason phrase, and a protocol version ๐ŸŽ€

In HTTP/1.1 ([HTTP/1.1]) and earlier, control data is sent as the first line of a message. In HTTP/2 ([HTTP/2]) and HTTP/3 ([HTTP/3]), control data is sent as pseudo-header fields with a reserved name prefix (e.g., ":authority") ๐Ÿงš

Every HTTP message has a protocol version. Depending on the version in use, it might be identified explicitly within the message or inferred from the connection it arrived on. Recipients use that version info to figure out the limitations or potential for later communication with that sender ๐Ÿ”

When an intermediary forwards a message, the protocol version gets updated to reflect the version that intermediary used ๐Ÿ” The Via header field (Section 7.6.3) is how upstream protocol info gets communicated inside a forwarded message.

A client SHOULD send a request version equal to the highest version it's conformant with, as long as that major version isn't higher than the highest version the server supports, if that's known ๐Ÿง  A client MUST NOT send a version it isn't conformant with ๐Ÿ™…โ€โ™€๏ธ

A client MAY send a lower request version if it's known that the server incorrectly implements the HTTP specification. But it can only do that after the client has tried at least one normal request and figured out from the response status code or header fields (e.g., Server) that the server handles higher request versions badly ๐Ÿ˜ญ

A server SHOULD send a response version equal to the highest version it's conformant with that has a major version less than or equal to the one received in the request ๐Ÿ‘‘ A server MUST NOT send a version it isn't conformant with. A server can send a 505 (HTTP Version Not Supported) response if it wants, for any reason, to refuse service for the client's major protocol version ๐Ÿซ 

A recipient that gets a message with a major version number it implements and a minor version number higher than what it implements SHOULD process the message as if it were in the highest minor version, within that major version, that the recipient is conformant with โœจ A recipient can assume that a message with a higher minor version, when sent to a recipient that hasn't yet indicated support for that higher version, is backwards-compatible enough to be safely processed by any implementation of the same major version ๐ŸŒˆ

6.3. Header Fields ๐Ÿ“

Fields (Section 5) that are sent or received before the content get called "header fields" (or just "headers," colloquially) ๐Ÿ’œ

The "header section" of a message is a sequence of header field lines. Each header field might modify or extend message semantics, describe the sender, define the content, or provide additional context ๐ŸŒธ

Note: We refer to named fields specifically as a "header field" when they are only allowed to be sent in the header section. ๐Ÿ’…

6.4. Content โœจ

HTTP messages often carry a complete or partial representation as the message "content": a stream of octets that shows up after the header section, as marked out by the message framing. ๐ŸŽ€

This abstract definition of content is the data after it's been pulled out of the message framing. ๐Ÿ’… For example, an HTTP/1.1 message body (Section 6 of [HTTP/1.1]) might be a stream of data sent with the chunked transfer coding (a sequence of data chunks, one zero-length chunk, and a trailer section) ๐Ÿงš, but the content of that same message only covers the data stream after the transfer coding has been decoded. It does NOT include the chunk lengths, the chunked framing syntax, or the trailer fields (Section 6.5). ๐Ÿ™ˆ

๐Ÿ’– Quick aside: some field names have a "Content-" prefix. This is an informal convention, okay? ๐Ÿซถ Some of these fields talk about the content of the message as defined above, but others are scoped to the selected representation (Section 3.2). Check each individual field's definition to figure out which one it is. ๐ŸŒธ

6.4.1. Content Semantics โœจ

The purpose of content in a request is defined by the method semantics (Section 9). ๐Ÿฆ‹

For example, a representation in the content of a PUT request (Section 9.3.4) represents the desired state of the target resource after the request is successfully applied ๐Ÿ’…, whereas a representation in the content of a POST request (Section 9.3.3) represents information to be processed by the target resource. ๐Ÿง 

In a response, the content's purpose is defined by the request method, the response status code (Section 15), and the response fields describing that content. ๐ŸŒˆ For example, the content of a 200 (OK) response to GET (Section 9.3.1) represents the current state of the target resource, as observed at the time of the message origination date (Section 6.6.1). Meanwhile, the content of that same status code in a response to POST might represent either the processing result or the new state of the target resource after the processing is applied. ๐Ÿ‘‘

The content of a 206 (Partial Content) response to GET contains either a single part of the selected representation, or a multipart message body containing multiple parts of that representation, as described in Section 15.3.7. ๐Ÿ“

Response messages with an error status code usually contain content that represents the error condition, so the content describes the error state and what steps are suggested for resolving it. ๐Ÿ˜ญ

Responses to the HEAD request method (Section 9.3.2) never include content. The associated response header fields only indicate what their values would have been if the request method had been GET (Section 9.3.1). ๐Ÿ’€

2xx (Successful) responses to a CONNECT request method (Section 9.3.6) switch the connection to tunnel mode instead of having content. ๐Ÿ”ฅ

All 1xx (Informational), 204 (No Content), and 304 (Not Modified) responses do not include content. ๐Ÿ™…โ€โ™€๏ธ

All other responses do include content, although that content might be of zero length. โœจ

6.4.2. Identifying Content โœจ

When a complete or partial representation is transferred as message content, it's often desirable for the sender to supply an identifier (or for the recipient to figure one out) for a resource corresponding to that specific representation. ๐Ÿ” For example, a client making a GET request on a resource for "the current weather report" might want an identifier specific to the content that came back (e.g., "weather report for Laguna Beach at 20210720T1711"). This is super useful for sharing or bookmarking content from resources whose representations are expected to change over time. ๐ŸŒธ

For a request message: ๐ŸŽ€

  • If the request has a Content-Location header field, then the sender asserts that the content is a representation of the resource identified by the Content-Location field value. However, such an assertion cannot be trusted unless it can be verified by other means (not defined by this specification). The information might still be useful for revision history links. ๐Ÿฆ‹
  • Otherwise, the content is unidentified by HTTP, but a more specific identifier might be supplied within the content itself. ๐Ÿงš

For a response message, the following rules are applied in order until a match is found: ๐Ÿ’…

  1. If the request method is HEAD or the response status code is 204 (No Content) or 304 (Not Modified), there is no content in the response. ๐Ÿ™ˆ
  2. If the request method is GET and the response status code is 200 (OK), the content is a representation of the target resource (Section 7.1). โœจ
  3. If the request method is GET and the response status code is 203 (Non-Authoritative Information), the content is a potentially modified or enhanced representation of the target resource as provided by an intermediary. ๐ŸŒˆ
  4. If the request method is GET and the response status code is 206 (Partial Content), the content is one or more parts of a representation of the target resource. ๐Ÿ“
  5. If the response has a Content-Location header field and its field value is a reference to the same URI as the target URI, the content is a representation of the target resource. ๐Ÿ’–
  6. If the response has a Content-Location header field and its field value is a reference to a URI different from the target URI, then the sender asserts that the content is a representation of the resource identified by the Content-Location field value. However, such an assertion cannot be trusted unless it can be verified by other means (not defined by this specification). ๐Ÿซถ
  7. Otherwise, the content is unidentified by HTTP, but a more specific identifier might be supplied within the content itself. ๐Ÿ‘‘

6.5. Trailer Fields โœจ

Fields (Section 5) that are located within a "trailer section" are called "trailer fields" (or just "trailers", colloquially). ๐ŸŽ€ Trailer fields are super handy for supplying message integrity checks, digital signatures, delivery metrics, or post-processing status information. ๐Ÿ’œ

Trailer fields ought to be processed and stored separately from the fields in the header section, so they don't contradict message semantics that were already known when the header section was complete. ๐Ÿง The presence or absence of certain header fields might affect choices made about routing or processing the message as a whole before the trailers arrive, and those choices can't be undone by discovering trailer fields later. ๐Ÿ˜ฌ

6.5.1. Limitations on Use of Trailers โœจ

A trailer section is only possible when the version of HTTP in use supports it and an explicit framing mechanism enables it. ๐Ÿฆ‹ For example, the chunked transfer coding in HTTP/1.1 lets a trailer section be sent after the content (Section 7.1.2 of [HTTP/1.1]). ๐ŸŒธ

Many fields can't be processed outside the header section, because their evaluation has to happen before the content is received. These include fields that describe message framing, routing, authentication, request modifiers, response controls, or content format. ๐Ÿ™…โ€โ™€๏ธ A sender MUST NOT generate a trailer field unless the sender knows that the corresponding header field name's definition permits the field to be sent in trailers. ๐Ÿšซ

Trailer fields can be tricky for intermediaries that forward messages from one protocol version to another. ๐Ÿ˜ต If the entire message can be buffered in transit, some intermediaries could merge trailer fields into the header section (as appropriate) before forwarding it. However, in most cases, the trailers are simply discarded. ๐Ÿ—‘๏ธ A recipient MUST NOT merge a trailer field into a header section unless the recipient understands the corresponding header field definition, and that definition explicitly permits and defines how trailer field values can be safely merged. ๐Ÿ”’

The presence of the keyword "trailers" in the TE header field (Section 10.1.4) of a request indicates that the client is willing to accept trailer fields, on behalf of itself and any downstream clients. For requests from an intermediary, this implies that all downstream clients are willing to accept trailer fields in the forwarded response. ๐ŸŽ€ Note that the presence of "trailers" does NOT mean that the client(s) will process any particular trailer field in the response. It only means that the trailer section(s) won't be dropped by any of the clients. ๐Ÿ’…

Because trailer fields might get discarded in transit, a server SHOULD NOT generate trailer fields that it believes are necessary for the user agent to receive. ๐Ÿฅบ

6.5.2. Processing Trailer Fields โœจ

The "Trailer" header field (Section 6.6.2) can be sent to indicate fields likely to be sent in the trailer section, which lets recipients get ready for them before processing the content. ๐Ÿงš For example, this could be useful if a field name indicates that a dynamic checksum should be calculated as the content is received and then immediately checked when the trailer field value shows up. ๐Ÿ”ฅ

Like header fields, trailer fields with the same name are processed in the order received. Multiple trailer field lines with the same name have the equivalent semantics of appending the multiple values as a list of members. ๐ŸŒˆ Trailer fields that might be generated more than once during a message MUST be defined as a list-based field, even if each member value is only processed once per field line received. ๐Ÿ’–

At the end of a message, a recipient MAY treat the set of received trailer fields as a data structure of name/value pairs, similar to (but separate from) the header fields. ๐Ÿ“ Any additional processing expectations can be defined within the field specification for a field intended for use in trailers. โœจ

6.6. Message Metadata โœจ

Fields that describe the message itself, like when and how the message has been generated, can show up in both requests and responses. ๐Ÿ’œ

6.6.1. Date โœจ

okay so the Date header field tells everyone when the message was originated, bestie ๐Ÿ•ฐ๏ธ๐Ÿ’– it has the same semantics as the Origination Date Field (orig-date) from Section 3.6.1 of [RFC5322], and its value is an HTTP-date, as defined in Section 5.6.7. no cap, it's giving precision ๐Ÿ’…

Date = HTTP-date

here's a cute example ๐ŸŽ€

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

so a sender that generates a Date header field SHOULD put in the best available approximation of when the message was generated ๐ŸŒธ in theory, the date ought to be the moment just before the message content gets generated, but in practice a sender can set the date at any time during message origination, which is lowkey relatable ๐Ÿ™ˆ

an origin server with a clock (as defined in Section 5.6.7) MUST generate a Date header field in all 2xx (Successful), 3xx (Redirection), and 4xx (Client Error) responses ๐Ÿซถ and it MAY generate a Date header field in 1xx (Informational) and 5xx (Server Error) responses โœจ

an origin server without a clock MUST NOT generate a Date header field ๐Ÿ™…โ€โ™€๏ธ no vibes without a clock, periodt ๐Ÿ’€

a recipient with a clock that receives a response message without a Date header field MUST record the time it was received and append a corresponding Date header field to the message's header section if it is cached or forwarded downstream ๐Ÿฆ‹

a recipient with a clock that receives a response with an invalid Date header field value MAY replace that value with the time that response was received ๐Ÿงš

a user agent MAY send a Date header field in a request, though generally it will not do so unless it is believed to convey useful information to the server ๐Ÿ’œ for example, custom applications of HTTP might convey a Date if the server is expected to adjust its interpretation of the user's request based on differences between the user agent and server clocks โฐ


6.6.2. Trailer ๐ŸŽ€

the Trailer header field is basically the sender's guest list ๐Ÿ“ it provides a list of field names that the sender anticipates sending as trailer fields within that message, so a recipient can prep for receiving that metadata before it starts processing the content ๐ŸŒˆ

Trailer = #field-name

for example, a sender might indicate that a signature will be computed as the content is being streamed and then provide the final signature as a trailer field ๐Ÿ” this lets a recipient do the same check on the fly as it receives the content, which is seriously iconic ๐Ÿ‘‘

a sender that intends to generate one or more trailer fields in a message SHOULD generate a Trailer header field in the header section of that message to indicate which fields might be present in the trailers ๐Ÿ’…

if an intermediary discards the trailer section in transit, the Trailer field could provide a hint of what metadata was lost ๐Ÿซฃ though there is no guarantee that a sender of Trailer will always follow through by sending the named fields ๐Ÿ™ƒ


7. Routing HTTP Messages ๐Ÿ—บ๏ธ

okay so HTTP request message routing is determined by each client based on the target resource, the client's proxy configuration, and establishment or reuse of an inbound connection ๐Ÿงญ the corresponding response routing then follows the same connection chain back to the client ๐Ÿ”

7.1. Determining the Target Resource ๐ŸŽฏ

although HTTP is used in a wide variety of applications, most clients rely on the same resource identification mechanism and configuration techniques as general-purpose Web browsers ๐ŸŒ even when communication options are hard-coded in a client's configuration, we can think of their combined effect as a URI reference (Section 4.1) โœจ

a URI reference is resolved to its absolute form in order to obtain the "target URI" ๐Ÿ’– the target URI excludes the reference's fragment component, if any, since fragment identifiers are reserved for client-side processing ([URI], Section 3.5) ๐Ÿช„

to perform an action on a "target resource", the client sends a request message containing enough components of its parsed target URI to enable recipients to identify that same resource ๐Ÿ” for historical reasons, the parsed target URI components, collectively referred to as the "request target", are sent within the message control data and the Host header field (Section 7.2) ๐Ÿซถ

there are two unusual cases where the request target components are in a method-specific form ๐Ÿ™ˆ

  • For CONNECT (Section 9.3.6), the request target is the host name and port number of the tunnel destination, separated by a colon. ๐Ÿš‡
  • For OPTIONS (Section 9.3.7), the request target can be a single asterisk ("*"). โญ

see the respective method definitions for details ๐Ÿ“– these forms MUST NOT be used with other methods ๐Ÿšซ

upon receipt of a client's request, a server reconstructs the target URI from the received components in accordance with their local configuration and incoming connection context ๐Ÿงฉ this reconstruction is specific to each major protocol version ๐Ÿ”ข for example, Section 3.3 of [HTTP/1.1] defines how a server determines the target URI of an HTTP/1.1 request ๐Ÿ“œ

Note: Previous specifications defined the recomposed target URI as a distinct concept, the "effective request URI". ๐Ÿ•ต๏ธ

7.2. Host and :authority ๐Ÿ 

the Host header field in a request provides the host and port information from the target URI ๐Ÿ“ this enables the origin server to distinguish among resources while servicing requests for multiple host names ๐Ÿ˜๏ธ

in HTTP/2 [HTTP/2] and HTTP/3 [HTTP/3], the Host header field is, in some cases, supplanted by the :authority pseudo-header field of a request's control data ๐Ÿ”„

Host = uri-host [ ":" port ] ; Section 4

the target URI's authority information is critical for handling a request ๐Ÿšจ a user agent MUST generate a Host header field in a request unless it sends that information as an :authority pseudo-header field ๐Ÿ’Œ a user agent that sends Host SHOULD send it as the first field in the header section of a request ๐Ÿฅ‡

for example, a GET request to the origin server for <http://www.example.org/pub/WWW/> would begin with:

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

since the host and port information acts as an application-level routing mechanism, it is a frequent target for malware seeking to poison a shared cache or redirect a request to an unintended server ๐Ÿ˜ฑ an interception proxy is particularly vulnerable if it relies on the host and port information for redirecting requests to internal servers, or for use as a cache key in a shared cache, without first verifying that the intercepted connection is targeting a valid IP address for that host ๐Ÿšฉ

7.3. Routing Inbound Requests ๐Ÿ“ฌ

once the target URI and its origin are determined, a client decides whether a network request is necessary to accomplish the desired semantics and, if so, where that request is to be directed ๐Ÿ—บ๏ธ

7.3.1. To a Cache ๐Ÿ—„๏ธ

if the client has a cache [CACHING] and the request can be satisfied by it, then the request is usually directed there first ๐Ÿƒโ€โ™€๏ธ

7.3.2. To a Proxy ๐Ÿšช

if the request is not satisfied by a cache, then a typical client will check its configuration to determine whether a proxy is to be used to satisfy the request โš™๏ธ proxy configuration is implementation-dependent, but is often based on URI prefix matching, selective authority matching, or both ๐Ÿ”Ž and the proxy itself is usually identified by an "http" or "https" URI ๐Ÿ”—

if an "http" or "https" proxy is applicable, the client connects inbound by establishing (or reusing) a connection to that proxy and then sending it an HTTP request message containing a request target that matches the client's target URI ๐Ÿ“จ

7.3.3. To the Origin ๐Ÿก

if no proxy is applicable, a typical client will invoke a handler routine (specific to the target URI's scheme) to obtain access to the identified resource ๐Ÿ›Ž๏ธ how that is accomplished is dependent on the target URI scheme and defined by its associated specification ๐Ÿ“š

Section 4.3.2 defines how to obtain access to an "http" resource by establishing (or reusing) an inbound connection to the identified origin server and then sending it an HTTP request message containing a request target that matches the client's target URI ๐Ÿ’ซ

Section 4.3.3 defines how to obtain access to an "https" resource by establishing (or reusing) an inbound secured connection to an origin server that is authoritative for the identified origin and then sending it an HTTP request message containing a request target that matches the client's target URI ๐Ÿ”

7.4. Rejecting Misdirected Requests ๐Ÿ™…โ€โ™€๏ธ

once a request is received by a server and parsed sufficiently to determine its target URI, the server decides whether to process the request itself, forward the request to another server, redirect the client to a different resource, respond with an error, or drop the connection ๐Ÿค” this decision can be influenced by anything about the request or connection context, but is specifically directed at whether the server has been configured to process requests for that target URI and whether the connection context is appropriate for that request ๐ŸŽฏ

for example, a request might have been misdirected, deliberately or accidentally, such that the information within a received Host header field differs from the connection's host or port ๐Ÿ˜ฌ if the connection is from a trusted gateway, such inconsistency might be expected; otherwise, it might indicate an attempt to bypass security filters, trick the server into delivering non-public content, or poison a cache ๐Ÿ•ท๏ธ see Section 17 for security considerations regarding message routing ๐Ÿ›ก๏ธ

unless the connection is from a trusted gateway, an origin server MUST reject a request if any scheme-specific requirements for the target URI are not met ๐Ÿšซ in particular, a request for an "https" resource MUST be rejected unless it has been received over a connection that has been secured via a certificate valid for that target URI's origin, as defined by Section 4.2.2 ๐Ÿ”’

The 421 (Misdirected Request) status code in a response indicates that the origin server has rejected the request because it appears to have been misdirected (Section 15.5.20). ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’€

7.5. Response Correlation ๐Ÿ”—

a connection might be used for multiple request/response exchanges ๐Ÿ” the mechanism used to correlate between request and response messages is version dependent; some versions of HTTP use implicit ordering of messages, while others use an explicit identifier ๐Ÿงฉ

all responses, regardless of the status code (including interim responses) can be sent at any time after a request is received, even if the request is not yet complete ๐ŸŽ๏ธ a response can complete before its corresponding request is complete (Section 6.1) ๐Ÿ’จ likewise, clients are not expected to wait any specific amount of time for a response ๐Ÿ•ฐ๏ธ clients (including intermediaries) might abandon a request if the response is not received within a reasonable period of time ๐Ÿซ 

a client that receives a response while it is still sending the associated request SHOULD continue sending that request unless it receives an explicit indication to the contrary (see, e.g., Section 9.5 of [HTTP/1.1] and Section 6.4 of [HTTP/2]) ๐Ÿ™Œ

7.6. Message Forwarding ๐Ÿฆ‹

okay so, like we saw in Section 3.7, intermediaries can have all kinds of jobs when it comes to processing HTTP requests and responses ๐Ÿ’… Some are there to boost performance or availability โœจ Others handle access control or filter content ๐Ÿ™ˆ An HTTP stream is kinda like a pipe-and-filter setup, so there's literally no built-in limit on how much an intermediary can enhance (or mess with) either direction of the stream ๐Ÿ”ฅ

Intermediaries are expected to forward messages even when they don't recognize some protocol elements (like new methods, status codes, or field names) ๐ŸŽ€ That's because it keeps things extensible for downstream recipients, which is so considerate of them ๐Ÿซถ

An intermediary not acting as a tunnel MUST implement the Connection header field, as specified in Section 7.6.1, and it has to exclude fields from being forwarded that are only intended for the incoming connection ๐ŸŒธ

An intermediary MUST NOT forward a message to itself unless it is protected from an infinite request loop ๐Ÿ˜ญ Generally, an intermediary ought to recognize its own server names, including any aliases, local variations, or literal IP addresses, and respond to those requests directly ๐Ÿ’œ

An HTTP message can be parsed as a stream for incremental processing or forwarding downstream โœจ BUT senders and recipients cannot rely on incremental delivery of partial messages, since some implementations will buffer or delay message forwarding for the sake of network efficiency, security checks, or content transformations ๐Ÿ‘€ So don't count on it, bestie ๐Ÿ’–


7.6.1. Connection ๐ŸŽ€

The Connection header field allows the sender to list desired control options for the current connection ๐Ÿ’…

  Connection        = #connection-option
  connection-option = token

Connection options are case-insensitive ๐ŸŒˆ

When a field aside from Connection is used to supply control information for or about the current connection, the sender MUST list the corresponding field name within the Connection header field โœจ Note that some versions of HTTP prohibit the use of fields for such information, and therefore do not allow the Connection field ๐Ÿ™ˆ

Intermediaries MUST parse a received Connection header field before a message is forwarded ๐Ÿซถ Then, for each connection-option in this field, they remove any header or trailer field(s) from the message with the same name as the connection-option, and then remove the Connection header field itself (or replace it with the intermediary's own control options for the forwarded message) ๐Ÿงน

Hence, the Connection header field gives us a declarative way of telling apart fields that are only intended for the immediate recipient ("hop-by-hop") from those intended for all recipients on the chain ("end-to-end") ๐Ÿฆ‹ This makes the message self-descriptive and lets future connection-specific extensions get deployed without fear that older intermediaries will blindly forward them ๐Ÿ‘‘

Furthermore, intermediaries SHOULD remove or replace fields that are known to require removal before forwarding, whether or not they appear as a connection-option, after applying those fields' semantics ๐Ÿ’… This includes but is not limited to:

  • Proxy-Connection (Appendix C.2.2 of [HTTP/1.1])
  • Keep-Alive (Section 19.7.1 of [RFC2068])
  • TE (Section 10.1.4)
  • Transfer-Encoding (Section 6.1 of [HTTP/1.1])
  • Upgrade (Section 7.8)

A sender MUST NOT send a connection option corresponding to a field that is intended for all recipients of the content ๐Ÿ™…โ€โ™€๏ธ For example, Cache-Control is never appropriate as a connection option (Section 5.2 of [CACHING]) ๐Ÿ’€

Connection options don't always match up with a field in the message, since a connection-specific field might not be needed if there are no parameters associated with a connection option ๐Ÿ“ On the flip side, a connection-specific field received without a corresponding connection option usually means the field got improperly forwarded by an intermediary, and the recipient ought to ignore it ๐Ÿ™ˆ

When defining a new connection option that does not correspond to a field, specification authors ought to reserve the corresponding field name anyway, so there are no later collisions ๐ŸŒธ Such reserved field names are registered in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" (Section 16.3.1) ๐Ÿงš


7.6.2. Max-Forwards ๐Ÿ“

The Max-Forwards header field gives us a mechanism, used with the TRACE (Section 9.3.8) and OPTIONS (Section 9.3.7) request methods, to limit how many times the request gets forwarded by proxies ๐Ÿ” This is super useful when the client is trying to trace a request that seems to be failing or looping mid-chain ๐Ÿ˜ฉ

  Max-Forwards = 1*DIGIT

The Max-Forwards value is a decimal integer showing the remaining number of times this request message can be forwarded ๐Ÿ”ข

Each intermediary that receives a TRACE or OPTIONS request containing a Max-Forwards header field MUST check and update its value prior to forwarding the request โœ… If the received value is zero (0), the intermediary MUST NOT forward the request; instead, the intermediary MUST respond as the final recipient ๐Ÿ›‘ If the received Max-Forwards value is greater than zero, the intermediary MUST generate an updated Max-Forwards field in the forwarded message, with a field value that is the lesser of a) the received value decremented by one (1) or b) the recipient's maximum supported value for Max-Forwards ๐Ÿงฎ

A recipient MAY ignore a Max-Forwards header field received with any other request methods ๐Ÿคทโ€โ™€๏ธ


7.6.3. Via ๐ŸŒˆ

The Via header field indicates the presence of intermediate protocols and recipients between the user agent and the server (on requests) or between the origin server and the client (on responses) ๐Ÿ›ฃ๏ธ It's kinda like the Received header field in email (Section 3.6.7 of [RFC5322]) ๐Ÿ“ฌ Via can be used for tracking message forwards, avoiding request loops, and identifying the protocol capabilities of senders along the request/response chain โœจ

  Via = #( received-protocol RWS received-by [ RWS comment ] )

  received-protocol = [ protocol-name "/" ] protocol-version
                    ; see Section 7.8
  received-by       = pseudonym [ ":" port ]
  pseudonym         = token

Each member of the Via field value represents a proxy or gateway that has forwarded the message ๐Ÿงฉ Each intermediary appends its own info about how the message was received, so the end result is ordered according to the sequence of forwarding recipients ๐Ÿ”—

A proxy MUST send an appropriate Via header field, as described below, in each message that it forwards ๐Ÿ“จ An HTTP-to-HTTP gateway MUST send an appropriate Via header field in each inbound request message, and it MAY send a Via header field in forwarded response messages ๐ŸŽ

For each intermediary, the received-protocol shows the protocol and protocol version used by the upstream sender of the message ๐Ÿ•ต๏ธโ€โ™€๏ธ So the Via field value records the advertised protocol capabilities of the request/response chain, so they stay visible to downstream recipients ๐Ÿ‘€ That's handy for figuring out which backwards-incompatible features might be safe to use in response, or within a later request, as described in Section 2.5 ๐Ÿ’ก For brevity, the protocol-name is omitted when the received protocol is HTTP ๐Ÿซฐ

The received-by portion is normally the host and optional port number of a recipient server or client that subsequently forwarded the message ๐Ÿ–ฅ๏ธ However, if the real host is considered sensitive information, a sender MAY replace it with a pseudonym ๐Ÿฅธ If a port is not provided, a recipient MAY interpret that as meaning it was received on the default port, if any, for the received-protocol ๐Ÿ”Œ

A sender MAY generate comments to identify the software of each recipient, kinda like the User-Agent and Server header fields ๐Ÿค– Comments in Via are optional, though, and a recipient MAY remove them prior to forwarding the message ๐Ÿงผ

For example, a request message could be sent from an HTTP/1.0 user agent to an internal proxy code-named "fred" ๐Ÿธ That proxy uses HTTP/1.1 to forward the request to a public proxy at p.example.net, which completes the request by forwarding it to the origin server at www.example.com ๐ŸŒ The request received by www.example.com would then have the following Via header field:

   Via: 1.0 fred, 1.1 p.example.net

An intermediary used as a portal through a network firewall SHOULD NOT forward the names and ports of hosts within the firewall region unless it is explicitly enabled to do so ๐Ÿงฑ If it isn't enabled, such an intermediary SHOULD replace each received-by host of any host behind the firewall with an appropriate pseudonym for that host ๐Ÿฅท

An intermediary MAY combine an ordered subsequence of Via header field list members into a single member if the entries have identical received-protocol values ๐Ÿงƒ For example:

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

could be collapsed to:

   Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

A sender SHOULD NOT combine multiple list members unless they are all under the same organizational control and the hosts have already been replaced by pseudonyms ๐Ÿข A sender MUST NOT combine members that have different received-protocol values ๐Ÿšซ no mixing the protocols, periodt ๐Ÿ’…

7.7. Message Transformations โœจ

okay so some intermediaries can actually transform messages and their content ๐ŸŽ€ like a proxy might convert image formats to save cache space or cut down traffic on a slow link. but ngl this can go sideways when the content is for critical stuff, like medical imaging or scientific data analysis ๐Ÿ™ˆ, especially when integrity checks or digital signatures are there to prove the content is still identical to the original. one tiny edit and the whole thing is cooked ๐Ÿ’€

An HTTP-to-HTTP proxy is called a "transforming proxy" ๐Ÿฆ‹ if it's designed or configured to modify messages in a semantically meaningful way. we mean changes that go beyond normal HTTP processing and would matter to the original sender, or could matter to downstream recipients. for example, a transforming proxy might act as a shared annotation server (adding references to a local annotation database into responses), a malware filter, a format transcoder, or a privacy filter ๐Ÿงš. these transformations are presumed to be what whichever client (or client organization) picked the proxy actually wanted ๐Ÿ’…

If a proxy gets a target URI with a host name that is not a fully qualified domain name, it MAY add its own domain to the host name it received when forwarding the request. but a proxy MUST NOT change the host name if the target URI contains a fully qualified domain name ๐ŸŒธ

A proxy MUST NOT modify the "absolute-path" and "query" parts of the received target URI when forwarding it to the next inbound server, except as required by that forwarding protocol. for instance, a proxy forwarding a request to an origin server over HTTP/1.1 will swap an empty path for "/" (Section 3.2.1 of [HTTP/1.1]) or "*" (Section 3.2.4 of [HTTP/1.1]), depending on the request method ๐Ÿ“

A proxy MUST NOT transform the content (Section 6.4) of a response message that has a no-transform cache directive (Section 5.2.2.6 of [CACHING]) ๐Ÿ”’ this doesn't cover changes that leave the content alone, like adding or removing transfer codings (Section 7 of [HTTP/1.1]), so those are fine ๐Ÿ™Œ

A proxy MAY transform the content of a message that doesn't have a no-transform cache directive. and if a proxy transforms the content of a 200 (OK) response, it can tell downstream recipients that a transformation happened by changing the status code to 203 (Non-Authoritative Information) (Section 15.3.4) ๐Ÿซถ

A proxy SHOULD NOT modify header fields that describe the endpoints of the communication chain, the resource state, or the selected representation (other than the content). the exceptions are when the field's definition specifically allows the change, or when the change is deemed necessary for privacy or security ๐Ÿ”ฅ

7.8. Upgrade

the "Upgrade" header field is meant to be a simple way to switch from HTTP/1.1 to some other protocol on the same connection ๐Ÿฆ‹

A client MAY send a list of protocol names in the Upgrade header field of a request. this invites the server to switch to one or more of the named protocols, in order of descending preference, before sending the final response ๐Ÿ’œ a server MAY ignore a received Upgrade header field if it would rather keep using the current protocol on that connection. and Upgrade can't be used to insist on a protocol change ๐Ÿ™…โ€โ™€๏ธ

Upgrade          = #protocol

protocol         = protocol-name ["/" protocol-version]
protocol-name    = token
protocol-version = token

Although protocol names are registered with a preferred case, recipients SHOULD use case-insensitive comparison when matching each protocol-name to supported protocols ๐ŸŒˆ

A server that sends a 101 (Switching Protocols) response MUST send an Upgrade header field to say which new protocol(s) the connection is switching to. if multiple protocol layers are being switched, the sender MUST list the protocols in layer-ascending order ๐Ÿงš a server MUST NOT switch to a protocol that the client didn't indicate in the corresponding request's Upgrade header field. a server MAY choose to ignore the client's order of preference and pick the new protocol(s) based on other factors, like the nature of the request or the current load on the server ๐Ÿ˜ญ

A server that sends a 426 (Upgrade Required) response MUST send an Upgrade header field listing the acceptable protocols, in order of descending preference ๐Ÿ’…

A server MAY send an Upgrade header field in any other response to advertise that it supports upgrading to the listed protocols, in order of descending preference, when that's appropriate for a future request โœจ

here's a hypothetical example sent by a client:

GET /hello HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: websocket, IRC/6.9, RTA/x11

the capabilities and nature of the application-level communication after the switch depend entirely on the new protocol(s) that get chosen ๐ŸŒธ but right after sending the 101 (Switching Protocols) response, the server is expected to keep responding to the original request as if it had received its equivalent within the new protocol. so the server still has an outstanding request to finish after the switch, and it's expected to do that without the request being sent again ๐ŸŽ€

for example, if the Upgrade header field shows up in a GET request and the server decides to switch protocols, it first responds with a 101 (Switching Protocols) message in HTTP/1.1, and then immediately follows that with the new protocol's version of a response to a GET on the target resource. this lets a connection be upgraded to protocols with the same semantics as HTTP without paying the latency cost of an extra round trip ๐Ÿš€ a server MUST NOT switch protocols unless the new protocol can honor the semantics of the received message. an OPTIONS request can be honored by any protocol ๐Ÿ“

here's an example response to that hypothetical request:

HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: websocket

[... data stream switches to websocket with an appropriate response
(as defined by new protocol) to the "GET /hello" request ...]

A sender of Upgrade MUST also send an "Upgrade" connection option in the Connection header field (Section 7.6.1) so intermediaries know not to forward this field ๐Ÿ™ˆ and a server that receives an Upgrade header field in an HTTP/1.0 request MUST ignore that Upgrade field ๐Ÿ’€

a client can't start using an upgraded protocol on the connection until it has completely sent the request message. (basically, the client can't change the protocol it's sending in the middle of a message ๐Ÿ™ƒ) if a server receives both an Upgrade and an Expect header field with the "100-continue" expectation (Section 10.1.1), the server MUST send a 100 (Continue) response before sending a 101 (Switching Protocols) response ๐Ÿซถ

the Upgrade header field only works for switching protocols on top of the existing connection. it can't switch the underlying connection (transport) protocol, and it can't move the existing communication onto a different connection. for those jobs, a 3xx (Redirection) response (Section 15.4) is the better move ๐Ÿ›‘

This specification only defines the protocol name "HTTP" for use by the family of Hypertext Transfer Protocols, as defined by the HTTP version rules of Section 2.5 and future updates to this specification. additional protocol names ought to be registered using the registration procedure defined in Section 16.7 ๐Ÿ“

8. Representation Data and Metadata

8.1. Representation Data

the representation data attached to an HTTP message is either provided as the message's content, or it's referred to by the message semantics and the target URI. the representation data comes in a format and encoding defined by the representation metadata header fields ๐ŸŽจ

the data type of the representation data is figured out from the Content-Type and Content-Encoding header fields. together they make a two-layer, ordered encoding model ๐Ÿง

representation-data := Content-Encoding( Content-Type( data ) )

8.2. Representation Metadata

representation header fields give you metadata about the representation ๐Ÿ—‚๏ธ when a message includes content, these fields tell you how to interpret that data. and in a response to a HEAD request, they describe the representation data that would have been in the content if the same request had been a GET ๐Ÿ‘€

8.3. Content-Type

the "Content-Type" header field says what media type the representation is. that's either the representation enclosed in the message content, or the selected representation, depending on the message semantics ๐Ÿ’– the media type tells you both the data format and how a recipient is supposed to process it, within the scope of the received message semantics, after any content codings from Content-Encoding have been decoded ๐ŸŒท

Content-Type = media-type

Media types are defined in Section 8.3.1. here's an example of the field:

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

A sender that generates a message containing content SHOULD generate a Content-Type header field in that message, unless the intended media type of the enclosed representation is unknown to the sender. if there's no Content-Type header field, the recipient MAY either assume a media type of "application/octet-stream" ([RFC2046], Section 4.5.1) or examine the data to figure out its type ๐Ÿ•ต๏ธโ€โ™€๏ธ

ok real talk, resource owners don't always set up their origin server to send the right Content-Type for a representation ๐Ÿ˜ค some user agents look at the content and, in certain cases, override the type they received (see [Sniffing], for example). this "MIME sniffing" can lead to wrong conclusions about the data, which might expose the user to extra security risks (e.g., "privilege escalation") ๐Ÿ’€ plus, different media types often share the same data format and only differ in how the data is meant to be processed, and you just can't tell that apart by inspecting the data alone ๐Ÿ™ƒ when sniffing is implemented, implementers are encouraged to give the user a way to turn it off ๐Ÿ”

Content-Type is defined as a singleton field, but it's sometimes generated multiple times by mistake. that makes a combined field value that looks like a list. recipients often try to handle this error by using the last syntactically valid member of the list. that can cause interoperability and security problems if different implementations handle the error in different ways ๐Ÿšจ

8.3.1. Media Type โœจ

okay so bestie, media types are how HTTP says "this is what kind of data I'm holding" ๐Ÿ’– They're used in the Content-Type (Section 8.3) and Accept (Section 12.5.1) header fields so that the data typing stays open and extensible, and type negotiation can actually happen ๐Ÿฆ‹ A media type doesn't just name a data format, it also brings along various processing models, which is how you know what to do with the data given the message context ๐Ÿงš

media-type is basically type "/" subtype parameters, and both type and subtype are tokens ๐ŸŒธ

media-type = type "/" subtype parameters
type       = token
subtype    = token

And yes, the type and subtype tokens are case-insensitive, so Text and text are the same vibe ๐Ÿ’…

The type/subtype MAY be followed by semicolon-delimited parameters (Section 5.6.6) in the form of name/value pairs ๐ŸŽ€ Whether a parameter is present or absent might matter for processing, depending on how it's defined in the media type registry ๐Ÿ‘‘ And parameter values might or might not be case-sensitive, depending on what the parameter name means ๐Ÿ™ˆ

Here's an example. These four are all equivalent for describing HTML text encoded in UTF-8, but the first one is preferred for consistency โœจ (The charset parameter value is case-insensitive per [RFC2046], Section 4.1.2, so it's all good ๐Ÿซถ)

text/html;charset=utf-8
Text/HTML;Charset="utf-8"
text/html; charset="utf-8"
text/html;charset=UTF-8

Media types ought to be registered with IANA following the procedures in [BCP13] ๐ŸŒˆ Go register your types, bestie ๐Ÿ’œ

8.3.2. Charset โœจ

HTTP uses "charset" names to indicate or negotiate the character encoding scheme ([RFC6365], Section 2) of a textual representation ๐Ÿฆ‹ In the fields defined by this document, charset names show up either as parameters (Content-Type) or, for Accept-Encoding, as a plain token ๐Ÿ“ Either way, charset names are matched case-insensitively, so no drama ๐Ÿ’…

Charset names ought to be registered in the IANA "Character Sets" registry (<https://www.iana.org/assignments/character-sets>) following the procedures in Section 2 of [RFC2978] ๐ŸŒธ

๐Ÿ’€ Note: In theory, charset names are defined by the "mime-charset" ABNF rule in Section 2.3 of [RFC2978] (as corrected in [Err1912]). That rule allows two characters that aren't in "token", namely "{" and "}". But no charset name registered at the time of this writing includes braces (see [Err5433]). Iconic restraint, honestly ๐Ÿ™ˆ

8.3.3. Multipart Types โœจ

MIME has a bunch of "multipart" types, which are encapsulations of one or more representations inside a single message body ๐ŸŽ€ They all share a common syntax (Section 5.1.1 of [RFC2046]) and include a boundary parameter as part of the media type value ๐Ÿงš The message body is its own protocol element, and a sender MUST generate only CRLF to represent line breaks between body parts ๐Ÿ’–

HTTP message framing does NOT use the multipart boundary as an indicator of message body length, though implementations that generate or process the content might use it ๐ŸŒˆ For example, "multipart/form-data" is often used for carrying form data in a request, as described in [RFC7578] ๐Ÿ“ And the "multipart/byteranges" type is defined by this specification for use in some 206 (Partial Content) responses (see Section 15.3.7) ๐Ÿฆ‹

Wait, I need to keep the requirement exact, so let me fix that: framing does not use the boundary as a length indicator, and I wrote that in plain caps by mistake. Correcting it below ๐Ÿ’…

HTTP message framing does not use the multipart boundary as an indicator of message body length, though it might be used by implementations that generate or process the content ๐ŸŒˆ For example, "multipart/form-data" is often used for carrying form data in a request, as described in [RFC7578] ๐Ÿ“ And the "multipart/byteranges" type is defined by this specification for use in some 206 (Partial Content) responses (see Section 15.3.7) ๐Ÿฆ‹

8.4. Content-Encoding โœจ

The "Content-Encoding" header field tells you what content codings have been applied to the representation, beyond what's already baked into the media type ๐Ÿ’… So it also tells you what decoding has to happen to get back to the media type named in Content-Type ๐Ÿ‘‘ Content-Encoding is mainly there so a representation's data can be compressed without losing the identity of its underlying media type ๐Ÿซถ

Content-Encoding = #content-coding

Here's how it looks in action ๐ŸŽ€

Content-Encoding: gzip

If one or more encodings have been applied to a representation, the sender that applied them MUST generate a Content-Encoding header field listing the content codings in the order they were applied ๐Ÿ’– Note that the coding named "identity" is reserved for its special role in Accept-Encoding, so it SHOULD NOT be included ๐Ÿ™ˆ

Additional information about the encoding parameters can come through other header fields that this specification doesn't define ๐Ÿงš

Unlike Transfer-Encoding (Section 6.1 of [HTTP/1.1]), the codings in Content-Encoding are a characteristic of the representation ๐Ÿฆ‹ The representation is defined in terms of the coded form, and all other metadata about it refers to the coded form, unless the metadata definition says otherwise ๐ŸŒธ Typically, the representation only gets decoded right before rendering or something similar ๐Ÿ“

If the media type includes an inherent encoding, like a data format that's always compressed, then that encoding would NOT be restated in Content-Encoding, even if it happens to be the same algorithm as one of the content codings ๐Ÿ’€ A content coding like that would only be listed if, for some bizarre reason, it got applied a second time to form the representation ๐ŸŒˆ Likewise, an origin server might publish the same data as multiple representations that differ only in whether the coding is part of Content-Type or Content-Encoding ๐ŸŽ€ That's because some user agents handle each response differently (for example, they might open a "Save as ..." dialog instead of automatically decompressing and rendering the content) ๐Ÿ‘‘

An origin server MAY respond with a status code of 415 (Unsupported Media Type) if a representation in the request message has a content coding that is not acceptable ๐Ÿซถ

8.4.1. Content Codings โœจ

Content coding values name an encoding transformation that has been, or can be, applied to a representation ๐Ÿ’… Content codings are mainly used so a representation can be compressed or otherwise usefully transformed without losing the identity of its underlying media type and without any loss of information ๐Ÿฆ‹ Frequently, the representation is stored in coded form, sent along as-is, and only decoded by the final recipient ๐Ÿงš

content-coding   = token

All content codings are case-insensitive and ought to be registered within the "HTTP Content Coding Registry", as described in Section 16.6 ๐ŸŒˆ

Content-coding values are used in the Accept-Encoding (Section 12.5.3) and Content-Encoding (Section 8.4) header fields ๐Ÿ“

8.4.1.1. Compress Coding โœจ

The "compress" coding is an adaptive Lempel-Ziv-Welch (LZW) coding [Welch] that's commonly produced by the UNIX file compression program "compress" ๐ŸŒธ A recipient SHOULD consider "x-compress" to be equivalent to "compress" ๐Ÿ’œ

8.4.1.2. Deflate Coding โœจ

The "deflate" coding is a "zlib" data format [RFC1950] containing a "deflate" compressed data stream [RFC1951] that uses a combination of the Lempel-Ziv (LZ77) compression algorithm and Huffman coding ๐ŸŽ€

๐Ÿ™ˆ Note: Some non-conformant implementations send the "deflate" compressed data without the zlib wrapper. Messy, but it happens ๐Ÿ’€

8.4.1.3. Gzip Coding โœจ

The "gzip" coding is an LZ77 coding with a 32-bit Cyclic Redundancy Check (CRC) that's commonly produced by the gzip file compression program [RFC1952] ๐Ÿฆ‹ A recipient SHOULD consider "x-gzip" to be equivalent to "gzip" ๐Ÿ‘‘

8.5. Content-Language โœจ

The "Content-Language" header field describes the natural language(s) of the intended audience for the representation ๐ŸŒˆ Note that this might not be equivalent to all the languages used within the representation ๐Ÿซถ

Content-Language = #language-tag

Language tags are defined in Section 8.5.1 ๐Ÿ“ The main point of Content-Language is to let a user identify and tell apart representations according to their own preferred language ๐Ÿ’– So if the content is only meant for a Danish-literate audience, the right field is ๐ŸŽ€

Content-Language: da

If no Content-Language is specified, the default is that the content is intended for all language audiences ๐Ÿงš That might mean the sender doesn't consider it specific to any natural language, or that the sender doesn't know which language it's for ๐ŸŒธ

Multiple languages MAY be listed for content that's 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

However, just because multiple languages appear within a representation doesn't mean it's aimed at multiple linguistic audiences ๐Ÿ™ˆ Take a beginner's language primer like "A First Lesson in Latin", which is clearly meant for an English-literate audience ๐Ÿฆ‹ In that case, Content-Language would properly only include "en" ๐Ÿ‘‘

Content-Language MAY be applied to any media type, because it is not limited to textual documents ๐Ÿซถ

8.5.1. Language Tags โœจ

A language tag, as defined in [RFC5646], identifies a natural language spoken, written, or otherwise conveyed by human beings for communicating information to other human beings ๐Ÿ’œ Computer languages are explicitly excluded ๐Ÿ™…

HTTP uses language tags within the Accept-Language and Content-Language header fields ๐ŸŒธ Accept-Language uses the broader language-range production defined in Section 12.5.4, whereas Content-Language uses the language-tag production defined below ๐Ÿ“

language-tag = <Language-Tag, see [RFC5646], Section 2.1>

A language tag is a sequence of one or more case-insensitive subtags, each separated by a hyphen character ("-", %x2D) ๐ŸŽ€ In most cases, a language tag has a primary language subtag that identifies a broad family of related languages (for example, "en" = English), which can optionally be followed by subtags that refine or narrow that language's range (for example, "en-CA" = the variety of English as communicated in Canada) ๐Ÿงš Whitespace is NOT allowed within a language tag ๐Ÿ’… Example tags include:

fr, en-US, es-419, az-Arab, x-pig-latin, man-Nkoo-GN

See [RFC5646] for further information ๐ŸŒˆ

8.6. Content-Length ๐Ÿ’–

okay bestie, the Content-Length header field tells you the associated representation's data length as a decimal non-negative integer number of octets ๐Ÿ“. When a representation is being sent as content, Content-Length is talking specifically about how much data is enclosed, so it can be used to delimit framing (e.g., Section 6.2 of [HTTP/1.1]) โœจ. In every other case, it shows the selected representation's current length, which recipients can use to estimate transfer time or to compare against representations they stored before ๐Ÿฆ‹.

Content-Length = 1*DIGIT

Here's an example ๐ŸŽ€:

Content-Length: 3495

A user agent SHOULD send Content-Length in a request when the method gives meaning to enclosed content and it is not sending Transfer-Encoding ๐Ÿ“ค. For example, a user agent normally sends Content-Length in a POST request even when the value is 0, which means empty content ๐Ÿงบ. A user agent SHOULD NOT send a Content-Length header field when the request message has no content and the method semantics don't expect any ๐Ÿ™…โ€โ™€๏ธ.

A server MAY send a Content-Length header field in a response to a HEAD request (Section 9.3.2) ๐ŸŒธ. But a server MUST NOT send Content-Length in such a response unless its field value equals the decimal number of octets that would have been sent in the content of a response if the same request had used the GET method ๐Ÿ”ข.

A server MAY send a Content-Length header field in a 304 (Not Modified) response to a conditional GET request (Section 15.4.5) ๐ŸŒ™. A server MUST NOT send Content-Length in such a response unless its field value equals the decimal number of octets that would have been sent in the content of a 200 (OK) response to the same request ๐Ÿงฎ.

A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational) or 204 (No Content) ๐Ÿšซ. A server MUST NOT send a Content-Length header field in any 2xx (Successful) response to a CONNECT request (Section 9.3.6) ๐Ÿšซ.

Outside of the cases above, and when there's no Transfer-Encoding, an origin server SHOULD send a Content-Length header field once the content size is known before the complete header section goes out ๐Ÿ“ฆ. This lets downstream recipients track transfer progress, know when a received message is complete, and potentially reuse the connection for more requests ๐Ÿ”โœจ.

Any Content-Length field value greater than or equal to zero is valid ๐Ÿ’ฏ. Since there's no predefined limit on content length, a recipient MUST anticipate potentially large decimal numerals and prevent parsing errors caused by integer conversion overflows or precision loss from integer conversion (Section 17.5) ๐Ÿ›ก๏ธ. That part is seriously important, bestie ๐Ÿ˜ญ.

Because Content-Length is used for message delimitation in HTTP/1.1, its field value can change how downstream recipients parse the message, even when the immediate connection is not using HTTP/1.1 ๐Ÿ’€. If a downstream intermediary forwards the message and the Content-Length field value doesn't match the framing it received, that can cause a security failure through request smuggling or response splitting ๐Ÿšจ.

So, a sender MUST NOT forward a message with a Content-Length header field value that is known to be incorrect ๐Ÿ™…โ€โ™€๏ธ.

Likewise, a sender MUST NOT forward a message with a Content-Length header field value that doesn't match the ABNF above, with one exception ๐Ÿซถ. A recipient that gets a Content-Length field value made of the same decimal value repeated as a comma-separated list (e.g, Content-Length: 42, 42) MAY either reject the message as invalid or replace that invalid field value with a single instance of the decimal value ๐ŸŽฏ. That's because it probably means an upstream message processor generated or combined a duplicate ๐Ÿ‘€.


8.7. Content-Location ๐Ÿฆ‹

The Content-Location header field references a URI that can be used as an identifier for a specific resource corresponding to the representation in this message's content ๐ŸŒˆ. In other words, if you did a GET request on this URI when the message was generated, a 200 (OK) response would contain the same representation that's enclosed as content in this message ๐Ÿงš.

Content-Location = absolute-URI / partial-URI

The field value is either an absolute-URI or a partial-URI. In the latter case (Section 4), the referenced URI is relative to the target URI ([URI], Section 5) ๐Ÿ—บ๏ธ.

The Content-Location value is not a replacement for the target URI (Section 7.1) ๐Ÿ™…โ€โ™€๏ธ. It's representation metadata ๐Ÿท๏ธ. It has the same syntax and semantics as the header field with the same name defined for MIME body parts in Section 4 of [RFC2557] ๐Ÿ“Ž. But showing up in an HTTP message has some special implications for HTTP recipients, so pay attention ๐Ÿ‘€โœจ.

If Content-Location is included in a 2xx (Successful) response message and its value refers (after conversion to absolute form) to a URI that is the same as the target URI, then the recipient MAY consider the content to be a current representation of that resource at the time shown by the message origination date โฐ. For a GET (Section 9.3.1) or HEAD (Section 9.3.2) request, that's the same as the default semantics when the server doesn't provide any Content-Location ๐ŸŒŸ. For a state-changing request like PUT (Section 9.3.4) or POST (Section 9.3.3), it means the server's response contains the new representation of that resource ๐ŸŽ‰. That's what separates it from representations that only report on the action, like "It worked!" ๐Ÿ’…. It also lets authoring applications update their local copies without a follow-up GET request ๐Ÿ™Œ.

If Content-Location is included in a 2xx (Successful) response message and its field value refers to a URI that differs from the target URI, then the origin server is claiming that the URI identifies a different resource for the enclosed representation ๐Ÿซฃ. That claim can only be trusted if both identifiers share the same resource owner, and HTTP can't figure that out on its own ๐Ÿคทโ€โ™€๏ธ.

  • For a response to a GET or HEAD request, this means the target URI refers to a resource that is subject to content negotiation, and the Content-Location field value is a more specific identifier for the selected representation ๐ŸŽจ.
  • For a 201 (Created) response to a state-changing method, a Content-Location field value that is identical to the Location field value means this content is a current representation of the newly created resource ๐Ÿ†•.
  • Otherwise, a Content-Location like that means this content is a representation reporting on the status of the requested action, and the same report can be fetched later with GET at the given URI ๐Ÿ“. For example, a purchase made with a POST request might include a receipt document as the content of the 200 (OK) response ๐Ÿงพ. The Content-Location field value gives you an identifier for grabbing a copy of that same receipt later ๐Ÿ’œ.

A user agent that sends Content-Location in a request message is saying its value refers to where the user agent first got the content of the enclosed representation, before it made any changes ๐Ÿ”™. In other words, it's giving the server a back link to the source of the original representation ๐Ÿ”—.

An origin server that receives a Content-Location field in a request message MUST treat the information as transitory request context, not as metadata to be saved verbatim as part of the representation ๐Ÿง . An origin server MAY use that context to guide how it processes the request, or save it for other uses, such as source links or versioning metadata ๐Ÿ“š. But an origin server MUST NOT use that context information to change the request semantics ๐Ÿšง.

For example, say a client makes a PUT request on a negotiated resource and the origin server accepts it without redirecting ๐ŸŽฏ. The new state of that resource is expected to match the one representation supplied in that PUT ๐Ÿ’–. The Content-Location can't be used as a sort of reverse content selection identifier to update just one of the negotiated representations ๐Ÿ™…โ€โ™€๏ธ. If the user agent wanted that behaviour, it would have applied the PUT directly to the Content-Location URI instead ๐Ÿคญ.


8.8. Validator Fields ๐Ÿ”

Resource metadata is called a "validator" if it can be used within a precondition (Section 13.1) to make a conditional request (Section 13) ๐ŸŽŸ๏ธ. Validator fields carry a current validator for the selected representation (Section 3.2) ๐Ÿ’Œ.

In responses to safe requests, validator fields describe the selected representation the origin server picked while handling the response ๐Ÿ”. Depending on the method and status code semantics, the selected representation for a given response is not always the same as the representation enclosed as response content, so don't mix those up ๐Ÿซ .

In a successful response to a state-changing request, validator fields describe the new representation that replaced the prior selected representation as a result of processing the request ๐Ÿ”„.

For example, an ETag field in a 201 (Created) response tells you the entity tag of the newly created resource's representation ๐Ÿท๏ธ. That entity tag can then be used as a validator in later conditional requests to prevent the "lost update" problem ๐Ÿ™ˆ๐Ÿ’ฅ.

This specification defines two forms of metadata that are commonly used to observe resource state and test for preconditions: modification dates (Section 8.8.2) and opaque entity tags (Section 8.8.3) โณ๐Ÿ”–. Other metadata that reflects resource state has been defined by extensions to HTTP, such as Web Distributed Authoring and Versioning [WEBDAV], and those are beyond the scope of this specification ๐Ÿงฉ.

8.8.1. Weak versus Strong โœจ

Okay so validators come in two flavors: strong or weak ๐Ÿฆ‹ Weak ones are super easy to generate but honestly kinda useless for comparisons ๐Ÿ’€ Strong ones are ideal for comparisons but can be really hard (and sometimes straight up impossible) to generate efficiently ๐Ÿ˜ญ So instead of forcing every resource to use the same strength, HTTP shows you which type of validator is in use and sets rules for when weak validators can be used as preconditions ๐Ÿ’…

A "strong validator" is representation metadata that changes value whenever there's a change to the representation data that would be observable in the content of a 200 (OK) response to GET ๐Ÿ”ฅ

A strong validator might also change for other reasons, like when a semantically significant part of the representation metadata gets changed (e.g., Content-Type) ๐ŸŽ€ But it's in the origin server's best interests to only change the value when it's actually necessary to invalidate the stored responses held by remote caches and authoring tools ๐Ÿซถ

Cache entries can stick around for arbitrarily long periods, no matter what their expiration times say ๐Ÿ˜ญ So a cache might try to validate an entry using a validator it got way back in the distant past ๐Ÿ•ฐ๏ธ A strong validator is unique across all versions of all representations associated with a particular resource over time ๐Ÿ‘‘ However, there's no implication of uniqueness across representations of different resources. The same strong validator might be in use for representations of multiple resources at the same time, and that doesn't mean those representations are equivalent ๐Ÿ™ˆ

There are a bunch of strong validators used in practice โœจ The best ones are based on strict revision control, where every change to a representation always gets a unique node name and revision identifier assigned before it's made accessible to GET ๐Ÿ’– A collision-resistant hash function applied to the representation data is also good enough, as long as the data is available before the response header fields are sent and the digest doesn't need to be recalculated every time a validation request comes in ๐ŸŒธ But if a resource has distinct representations that only differ in their metadata (like content negotiation over media types that happen to share the same data format), then the origin server needs to put additional information in the validator to tell those representations apart ๐Ÿ“

In contrast, a "weak validator" is representation metadata that might not change for every change to the representation data ๐ŸŒˆ This weakness could come from limitations in how the value is calculated (e.g., clock resolution), from an inability to ensure uniqueness for all possible representations of the resource, or from the resource owner wanting to group representations by some self-determined set of equivalency instead of unique sequences of data ๐Ÿงš

An origin server SHOULD change a weak entity tag whenever it considers prior representations to be unacceptable as a substitute for the current representation ๐Ÿ’œ In other words, a weak entity tag ought to change whenever the origin server wants caches to throw out old responses ๐Ÿ—‘๏ธ

For example, a weather report that changes content every second based on dynamic measurements might be grouped into sets of equivalent representations (from the origin server's perspective) that share the same weak validator ๐ŸŒฆ๏ธ That way cached representations can stay valid for a reasonable period of time (maybe adjusted dynamically based on server load or weather quality) ๐Ÿฆ‹ Likewise, a representation's modification time, if it's only defined with one-second resolution, might be a weak validator if it's possible for the representation to be modified twice during a single second and retrieved between those modifications ๐Ÿ˜ญ

Also, a validator is weak if it's shared by two or more representations of a given resource at the same time, unless those representations have identical representation data ๐Ÿ™ˆ For example, if the origin server sends the same validator for a representation with a gzip content coding applied as it does for a representation with no content coding, then that validator is weak ๐Ÿ’€ However, two simultaneous representations might share the same strong validator if they only differ in the representation metadata, like when two different media types are available for the same representation data ๐ŸŽ€

Strong validators are usable for all conditional requests, including cache validation, partial content ranges, and "lost update" avoidance ๐Ÿ‘‘ Weak validators are only usable when the client doesn't require exact equality with previously obtained representation data, like when validating a cache entry or limiting a web traversal to recent changes ๐Ÿซถ


8.8.2. Last-Modified ๐Ÿ•ฐ๏ธ

The "Last-Modified" header field in a response gives a timestamp for the date and time at which the origin server believes the selected representation was last modified, as determined at the conclusion of handling the request ๐Ÿ’–

Last-Modified = HTTP-date

An example of its use is:

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

8.8.2.1. Generation ๐ŸŒธ

An origin server SHOULD send Last-Modified for any selected representation for which a last modification date can be reasonably and consistently determined ๐Ÿ’… Its use in conditional requests and evaluating cache freshness ([CACHING]) can substantially reduce unnecessary transfers and significantly improve service availability and scalability ๐Ÿ”ฅ

A representation is typically the sum of many parts behind the resource interface ๐Ÿงฉ The last-modified time would usually be the most recent time that any of those parts were changed ๐Ÿ•’ How that value is determined for any given resource is an implementation detail beyond the scope of this specification ๐Ÿคทโ€โ™€๏ธ

An origin server SHOULD obtain the Last-Modified value of the representation as close as possible to the time that it generates the Date field value for its response ๐Ÿ“ This lets a recipient make an accurate assessment of the representation's modification time, especially if the representation changes near the time the response is generated โœจ

An origin server with a clock (as defined in Section 5.6.7) MUST NOT generate a Last-Modified date that is later than the server's time of message origination (Date, Section 6.6.1). If the last modification time is derived from implementation-specific metadata that evaluates to some time in the future, according to the origin server's clock, then the origin server MUST replace that value with the message origination date. This prevents a future modification date from having an adverse impact on cache validation ๐Ÿšซ

An origin server without a clock MUST NOT generate a Last-Modified date for a response unless that date value was assigned to the resource by some other system (presumably one with a clock) ๐Ÿ•ฐ๏ธ

8.8.2.2. Comparison ๐Ÿ”

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

  • The validator is being compared by an origin server to the actual current validator for the representation and,
  • That origin server reliably knows that the associated representation 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, If-Unmodified-Since, or If-Range header field, because the client has a cache entry for the associated representation, and
  • That cache entry includes a Date value which is at least one second after the Last-Modified value and the client has reason to believe that they were generated by the same clock or that there is enough difference between the Last-Modified and Date values to make clock synchronization issues unlikely;

or

  • The validator is being compared by an intermediate cache to the validator stored in its cache entry for the representation, and
  • That cache entry includes a Date value which is at least one second after the Last-Modified value and the cache has reason to believe that they were generated by the same clock or that there is enough difference between the Last-Modified and Date values to make clock synchronization issues unlikely.

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 ๐Ÿงš


8.8.3. ETag ๐Ÿท๏ธ

The "ETag" field in a response gives the current entity tag for the selected representation, as determined at the conclusion of handling the request ๐Ÿ’œ An entity tag is an opaque validator for differentiating between multiple representations of the same resource, whether those representations come from resource state changes over time, content negotiation resulting in multiple representations being valid at the same time, or both ๐Ÿฆ‹ An entity tag consists of an opaque quoted string, possibly prefixed by a weakness indicator โœจ

ETag       = entity-tag

entity-tag = [ weak ] opaque-tag
weak       = %s"W/"
opaque-tag = DQUOTE *etagc DQUOTE
etagc      = %x21 / %x23-7E / obs-text
           ; VCHAR except double quotes, plus obs-text
Note: Previously, opaque-tag was defined to be a quoted-string ([RFC2616], Section 3.11); thus, some recipients might perform backslash unescaping. Servers therefore ought to avoid backslash characters in entity tags. โš ๏ธ

An entity tag can be more reliable for validation than a modification date in situations where it's inconvenient to store modification dates, where the one-second resolution of HTTP-date values isn't sufficient, or where modification dates aren't consistently maintained ๐ŸŒˆ

Examples:

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

An entity tag can be either a weak or strong validator, with strong being the default ๐Ÿ’ช If an origin server provides an entity tag for a representation and the generation of that entity tag doesn't satisfy all of the characteristics of a strong validator (Section 8.8.1), then the origin server MUST mark the entity tag as weak by prefixing its opaque value with "W/" (case-sensitive) ๐Ÿท๏ธ

A sender MAY send the ETag field in a trailer section (see Section 6.5) ๐ŸŽ€ However, since trailers are often ignored, it's preferable to send ETag as a header field unless the entity tag is generated while sending the content ๐Ÿซถ

8.8.3.1. Generation ๐Ÿงš

okay so the big idea here is that only the service author really knows their resource well enough to pick the most accurate and efficient validation trick for it ๐Ÿ’… and any trick can get squished down into a simple sequence of octets so it's easy to compare ๐Ÿซถ since the value is opaque, the client doesn't need to know how each entity tag was built. literally no homework for the client ๐Ÿ™ˆ

for example, a resource with implementation-specific versioning on every change might use an internal revision number, maybe paired with a variance identifier for content negotiation, to tell its representations apart โœจ other implementations might go with a collision-resistant hash of the representation content, a combo of various file attributes, or a modification timestamp with sub-second resolution. the vibes are all valid ๐ŸŒˆ

An origin server SHOULD send an ETag for any selected representation where detecting changes can be reasonably and consistently determined ๐Ÿ’– why? because the entity tag's use in conditional requests and in evaluating cache freshness ([CACHING]) can substantially reduce unnecessary transfers and significantly improve service availability, scalability, and reliability. it's giving main character energy for your server ๐Ÿ‘‘

8.8.3.2. Comparison ๐Ÿ”ฅ

there are two entity tag comparison functions, and which one you get depends on whether the comparison context allows the use of weak validators ๐Ÿฆ‹

  • "Strong comparison": two entity tags are equivalent if both are not weak and their opaque-tags match character-by-character.
  • "Weak comparison": two entity tags are equivalent if their opaque-tags match character-by-character, regardless of either or both being tagged as "weak".

the table below shows the results for a set of entity tag pairs under both the weak and strong comparison functions ๐Ÿ“Š

+========+========+===================+=================+
| ETag 1 | ETag 2 | Strong Comparison | Weak Comparison |
+========+========+===================+=================+
| W/"1"  | W/"1"  | no match          | match           |
+--------+--------+-------------------+-----------------+
| W/"1"  | W/"2"  | no match          | no match        |
+--------+--------+-------------------+-----------------+
| W/"1"  | "1"    | no match          | match           |
+--------+--------+-------------------+-----------------+
| "1"    | "1"    | match             | match           |
+--------+--------+-------------------+-----------------+

                            Table 3

8.8.3.3. Example: Entity Tags Varying on Content-Negotiated Resources ๐ŸŽ€

okay this one is so good ๐Ÿ˜ญ picture a resource that's subject to content negotiation (Section 12), where the representations sent back for a GET request vary based on the Accept-Encoding request header field (Section 12.5.3) ๐Ÿ’…

>> Request:

GET /index HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip

in this case, the response might or might not use the gzip content coding ๐Ÿคทโ€โ™€๏ธ if it doesn't, the response might look like:

>> Response:

HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-a"
Content-Length: 70
Vary: Accept-Encoding
Content-Type: text/plain

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

and an alternative representation that DOES use gzip content coding would be:

>> Response:

HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-b"
Content-Length: 43
Vary: Accept-Encoding
Content-Type: text/plain
Content-Encoding: gzip

...binary data...
๐Ÿ“ Note: content codings are a property of the representation data, so a strong entity tag for a content-encoded representation has to be distinct from the entity tag of an unencoded representation, to prevent potential conflicts during cache updates and range requests. in contrast, transfer codings (Section 7 of [HTTP/1.1]) apply only during message transfer and do not result in distinct entity tags. the plot twist is that they're totally different things ๐Ÿง 

9. Methods ๐ŸŒˆ

9.1. Overview โœจ

okay so the request method token is the primary source of request semantics ๐Ÿ’… it tells the server what the client is trying to do and what the client expects as a successful result ๐ŸŽฏ

the request method's semantics can get extra specialized by the semantics of some header fields when they're present in a request, as long as those extra semantics don't conflict with the method. for example, a client can send conditional request header fields (Section 13.1) to make the requested action conditional on the current state of the target resource ๐Ÿซถ

HTTP is designed to be usable as an interface to distributed object systems ๐Ÿงš the request method invokes an action to be applied to a target resource, kind of like how a remote method invocation can be sent to an identified object.

method = token

the method token is case-sensitive, because it might be used as a gateway to object-based systems with case-sensitive method names ๐Ÿ™ˆ by convention, standardized methods are defined in all-uppercase US-ASCII letters ๐Ÿ” 

unlike distributed objects, the standardized request methods in HTTP are not resource-specific, since uniform interfaces give better visibility and reuse in network-based systems [REST] ๐Ÿฆ‹ once a standardized method is defined, it ought to have the same semantics when applied to any resource, though each resource decides for itself whether those semantics are implemented or allowed ๐Ÿ’œ

this spec defines a bunch of standardized methods that are commonly used in HTTP, as outlined in this table ๐Ÿ’–

+=========+============================================+=========+
| Method  | Description                                | Section |
| Name    |                                            |         |
+=========+============================================+=========+
| GET     | Transfer a current representation of the   | 9.3.1   |
|         | target resource.                           |         |
+---------+--------------------------------------------+---------+
| HEAD    | Same as GET, but do not transfer the       | 9.3.2   |
|         | response content.                          |         |
+---------+--------------------------------------------+---------+
| POST    | Perform resource-specific processing on    | 9.3.3   |
|         | the request content.                       |         |
+---------+--------------------------------------------+---------+
| PUT     | Replace all current representations of the | 9.3.4   |
|         | target resource with the request content.  |         |
+---------+--------------------------------------------+---------+
| DELETE  | Remove all current representations of the  | 9.3.5   |
|         | target resource.                           |         |
+---------+--------------------------------------------+---------+
| CONNECT | Establish a tunnel to the server           | 9.3.6   |
|         | identified by the target resource.         |         |
+---------+--------------------------------------------+---------+
| OPTIONS | Describe the communication options for the | 9.3.7   |
|         | target resource.                           |         |
+---------+--------------------------------------------+---------+
| TRACE   | Perform a message loop-back test along the | 9.3.8   |
|         | path to the target resource.               |         |
+---------+--------------------------------------------+---------+

                                Table 4

okay now the important bit ๐Ÿšจ all general-purpose servers MUST support the GET and HEAD methods ๐Ÿ‘‘ all other methods are OPTIONAL, so no pressure ๐ŸŒธ

the set of methods allowed by a target resource can be listed in an Allow header field (Section 10.2.1) ๐Ÿ“‹ BUT the set of allowed methods can change dynamically, so stay alert ๐Ÿ‘€ an origin server that receives a request method that is unrecognized or not implemented SHOULD respond with the 501 (Not Implemented) status code ๐Ÿ™…โ€โ™€๏ธ and an origin server that receives a request method that is recognized and implemented, but not allowed for the target resource, SHOULD respond with the 405 (Method Not Allowed) status code ๐Ÿ’€

additional methods, outside the scope of this specification, have been specified for use in HTTP ๐ŸŒˆ all of them ought to be registered within the "Hypertext Transfer Protocol (HTTP) Method Registry", as described in Section 16.1 ๐Ÿงš

9.2. Common Method Properties ๐ŸŒธ

9.2.1. Safe Methods ๐Ÿฆ‹

okay so request methods are considered "safe" if their defined semantics are essentially read-only ๐Ÿ“– that means the client does not request, and does not expect, any state change on the origin server from applying a safe method to a target resource ๐Ÿซถ likewise, reasonable use of a safe method isn't expected to cause any harm, loss of property, or unusual burden on the origin server ๐Ÿ’…

this definition doesn't stop an implementation from including behavior that's potentially harmful, that isn't entirely read-only, or that causes side effects while invoking a safe method ๐Ÿ™ˆ what matters is that the client didn't ask for that extra behavior and can't be held accountable for it โš–๏ธ for example, most servers append request info to access log files at the end of every response, no matter the method, and that still counts as safe, even though the log storage might fill up and make the server fail ๐Ÿ“ and a safe request started by clicking an ad on the Web will often have the side effect of charging an advertising account ๐Ÿ’ธ

of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe โœจ

why do we even care? because the whole point of splitting safe from unsafe methods is to let automated retrieval processes (spiders) and cache performance optimization (pre-fetching) work without fear of causing harm ๐Ÿ•ท๏ธ it also lets a user agent apply appropriate constraints on the automated use of unsafe methods when it's processing potentially untrusted content ๐Ÿ›ก๏ธ

a user agent SHOULD distinguish between safe and unsafe methods when presenting potential actions to a user, so the user can be made aware of an unsafe action before it's requested ๐Ÿšฆ

โš ๏ธ when a resource is built so that parameters within the target URI have the effect of selecting an action, it's the resource owner's responsibility to make sure that action is consistent with the request method semantics. it's super common for web-based content editing software to use actions in query parameters, like page?do=delete ๐Ÿ˜ฌ if the purpose of such a resource is to perform an unsafe action, the resource owner MUST disable or disallow that action when it's accessed using a safe request method. if they don't, you'll get unfortunate side effects when automated processes do a GET on every URI reference for link maintenance, pre-fetching, building a search index, and so on ๐Ÿ’€

9.2.2. Idempotent Methods ๐Ÿ”

okay so a request method is "idempotent" if sending the same identical request many times has the same intended effect on the server as sending it once ๐Ÿซถ PUT, DELETE, and the safe request methods are idempotent, out of all the methods this spec defines ๐Ÿ’œ

Like safe, idempotent only covers what the user asked for. A server is totally free to log every request separately, keep a revision control history, or do other non-idempotent stuff for each idempotent request โœจ

Why do we even care? Because the request can be repeated automatically if the connection breaks before the client can read the response ๐Ÿฆ‹ Say a client sends a PUT and the connection gets closed before any response shows up. The client can open a new connection and retry, no stress ๐Ÿ’… It knows that repeating it has the same intended effect, even if the first one actually worked. The response might just look a bit different ๐ŸŒธ

A client SHOULD NOT automatically retry a request with a non-idempotent method unless it has some way to know the request semantics are actually idempotent, regardless of the method, or some way to detect that the original request was never applied ๐Ÿ™ˆ

For example, a user agent can repeat a POST request automatically if it knows (through design or configuration) that the request is safe for that resource ๐Ÿ“ Also, a user agent built specifically for a version control repository might recover from partial failures by checking the target resource revision(s) after a failed connection, reverting or fixing any changes that got partially applied, and then automatically retrying the requests that failed. Iconic behavior ๐Ÿ‘‘

Some clients take a riskier route and try to guess when an automatic retry is okay ๐Ÿ˜ฌ For example, a client might automatically retry a POST if the transport connection closed before any part of a response arrived, especially if an idle persistent connection was being used. Bold move, not gonna lie ๐Ÿ’€

A proxy MUST NOT automatically retry non-idempotent requests ๐Ÿ›‘ And a client SHOULD NOT automatically retry a failed automatic retry. Let it go, bestie ๐Ÿซ 

9.2.3. Methods and Caching ๐Ÿ—‚๏ธ

For a cache to store and use a response, the method has to explicitly allow caching and spell out the conditions under which a response can be used to answer later requests. If a method definition doesn't do that, it simply can't be cached ๐Ÿ™…โ€โ™€๏ธ For more requirements, check out [CACHING] ๐Ÿ“š

This spec defines caching semantics for GET, HEAD, and POST, even though the overwhelming majority of cache implementations only support GET and HEAD ๐Ÿฅฒ


9.3. Method Definitions ๐Ÿ“

9.3.1. GET ๐Ÿ”

The GET method asks for transfer of a current selected representation of the target resource ๐Ÿ’– A successful response reflects the quality of "sameness" that the target URI identifies (Section 1.2.2 of [URI]). So basically, if you want to grab identifiable info over HTTP, you usually make a GET request on an identifier that could give you that info in a 200 (OK) response โœจ

GET is the main way information gets retrieved, and it's the star of almost every performance optimization ๐Ÿ”ฅ Apps that give each important resource its own URI get all those optimizations, and other apps can reuse those URIs too. That creates a network effect that keeps the Web growing ๐ŸŒˆ

It's super tempting to think of resource identifiers as remote file system pathnames, with representations being copies of those files' contents ๐Ÿงš And honestly, that's how lots of resources are implemented (see Section 17.3 for related security considerations). But there are no such limits in practice ๐Ÿฆ‹

The HTTP interface for a resource could just as easily be a tree of content objects, a programmatic view over database records, or a gateway to other information systems ๐Ÿ’… Even when URI mapping is tied to a file system, an origin server might be set up to run the files with the request as input and send the output back as the representation, instead of transferring the files directly. Either way, only the origin server needs to know how each resource identifier maps to an implementation, and how that implementation picks and sends a current representation of the target resource ๐Ÿซถ

A client can turn GET into a "range request", asking for transfer of just some part(s) of the selected representation, by sending a Range header field in the request (Section 14.2) ๐ŸŽ€

Request message framing doesn't depend on the method, but content received in a GET request has no generally defined semantics. It can't change the meaning or target of the request, and it might make some implementations reject the request and close the connection, because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]) ๐Ÿ˜ฌ A client SHOULD NOT generate content in a GET request unless it's sent directly to an origin server that has already indicated, in or out of band, that such a request has a purpose and will be properly supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain ๐Ÿ™ˆ

The response to a GET request is cacheable, so a cache MAY use it to satisfy later GET and HEAD requests, unless the Cache-Control header field (Section 5.2 of [CACHING]) says otherwise ๐Ÿ’œ

Heads up, though! When info retrieval happens through a mechanism that builds a target URI from user-provided info, like the query fields of a form using GET, potentially sensitive data might end up in there, which wouldn't be appropriate to show in a URI (see Section 17.9) ๐Ÿšจ Sometimes the data can be filtered or transformed so it doesn't reveal that stuff. Other times, especially when caching a response wouldn't help anyway, using the POST method (Section 9.3.3) instead of GET can send that info in the request content rather than in the target URI ๐Ÿ”

9.3.2. HEAD ๐Ÿซฅ

The HEAD method is identical to GET, except that the server MUST NOT send content in the response ๐Ÿ›‘ HEAD is used to grab metadata about the selected representation without transferring its representation data. It's often used for testing hypertext links or finding recent modifications ๐Ÿ”—

The server SHOULD send the same header fields in response to a HEAD request as it would have sent for a GET request. However, a server MAY omit header fields whose value is only determined while generating the content ๐ŸŒธ For example, some servers buffer a dynamic response to GET until a minimum amount of data is generated, so they can more efficiently delimit small responses or make late decisions about content selection. A response to GET like that might contain Content-Length and Vary fields, for example, that aren't generated within a HEAD response. These minor inconsistencies are considered preferable to generating and discarding the content for a HEAD request, since HEAD is usually requested for the sake of efficiency โšก

Request message framing doesn't depend on the method, but content received in a HEAD request has no generally defined semantics either. It can't change the meaning or target of the request, and it might make some implementations reject the request and close the connection, because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]) ๐Ÿ˜ฌ A client SHOULD NOT generate content in a HEAD request unless it's sent directly to an origin server that has already indicated, in or out of band, that such a request has a purpose and will be properly supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain ๐Ÿ™ƒ

The response to a HEAD request is cacheable, so a cache MAY use it to satisfy later HEAD requests, unless the Cache-Control header field (Section 5.2 of [CACHING]) says otherwise ๐Ÿฉต A HEAD response might also affect previously cached responses to GET; see Section 4.3.5 of [CACHING] โœจ

9.3.3. POST ๐Ÿ“ฎ

The POST method asks that the target resource process the representation enclosed in the request, following the resource's own specific semantics ๐ŸŽ€ For example, POST is used for functions like these (among others):

  • Providing a block of data, such as the fields entered into an HTML form, to a data-handling process ๐Ÿ“‹
  • Posting a message to a bulletin board, newsgroup, mailing list, blog, or similar group of articles ๐Ÿ“ฃ
  • Creating a new resource that the origin server hasn't identified yet ๐Ÿ†•
  • Appending data to a resource's existing representation(s) โž•

An origin server shows response semantics by picking an appropriate status code based on the result of processing the POST request ๐Ÿท๏ธ Almost all of the status codes this spec defines could come back in a response to POST. The exceptions are 206 (Partial Content), 304 (Not Modified), and 416 (Range Not Satisfiable) ๐Ÿ™…โ€โ™€๏ธ

If one or more resources got created on the origin server because a POST request was processed successfully, the origin server SHOULD send a 201 (Created) response. That response contains a Location header field giving an identifier for the primary resource created (Section 10.2.2), plus a representation describing the status of the request while referring to the new resource(s) ๐ŸŽ‰

Responses to POST requests are only cacheable when they include explicit freshness information (see Section 4.2.1 of [CACHING]) and a Content-Location header field whose value is the same as the POST's target URI (Section 8.7) ๐Ÿง  A cached POST response can be reused to satisfy a later GET or HEAD request. But a POST request can't be satisfied by a cached POST response, because POST is potentially unsafe; see Section 4 of [CACHING] ๐Ÿšซ

If processing a POST would produce a result equivalent to a representation of an existing resource, an origin server MAY redirect the user agent to that resource by sending a 303 (See Other) response with the existing resource's identifier in the Location field ๐Ÿฆ‹ This gives the user agent a resource identifier and moves the representation over a method that's friendlier to shared caching. The tradeoff is an extra request if the user agent doesn't already have that representation cached ๐Ÿ’ซ

9.3.4. PUT ๐ŸŽ€

okay bestie, PUT is the method that says "make this resource look like THIS" ๐Ÿ’… The enclosed representation in the request message content is what the target resource gets created or replaced with. If that works, a GET on the same target later should get back an equivalent representation in a 200 (OK) response โœจ But ngl, there's no guarantee you'll see that change, because other user agents might be poking the same resource at the same time, or the origin server might be doing dynamic processing before your GET shows up ๐Ÿ˜ญ A success only means your intent was achieved at the moment the origin server processed it ๐Ÿซถ

If the target resource doesn't have a current representation and the PUT creates one, the origin server MUST inform the user agent by sending a 201 (Created) response ๐ŸŒธ If it already has a current representation and that gets successfully changed to match the enclosed one, the origin server MUST send either a 200 (OK) or a 204 (No Content) response to show the request finished ๐Ÿ’–

An origin server SHOULD verify that the PUT representation fits its configured constraints for the target resource ๐Ÿง For example, if the server works out a resource's representation metadata from the URI, then it needs to make sure whatever shows up in a successful PUT matches that metadata. When a PUT representation doesn't fit the target resource, the origin server SHOULD either make them match, by transforming the representation or changing the resource config, or send back an appropriate error message with enough info to explain why it's unsuitable ๐Ÿ”ฅ The 409 (Conflict) or 415 (Unsupported Media Type) status codes are suggested, and the 415 one is specifically for constraints on Content-Type values ๐Ÿ’…

For example, if the target resource is configured to always have a Content-Type of "text/html" and the representation being PUT has a Content-Type of "image/jpeg", the origin server ought to do one of:

a. reconfigure the target resource to reflect the new media type;

b. transform the PUT representation to a format consistent with that of the resource before saving it as the new resource state; or,

c. reject the request with a 415 (Unsupported Media Type) response indicating that the target resource is limited to "text/html", perhaps including a link to a different resource that would be a suitable target for the new representation.

HTTP doesn't define exactly how a PUT affects an origin server's state beyond what the user agent's intent and the origin server's response semantics can express ๐Ÿฆ‹ It also doesn't define what a resource might be, in any sense of that word, beyond the interface HTTP gives you. It doesn't define how resource state is "stored", how that storage might change when resource state changes, or how the origin server turns resource state into representations. Generally speaking, all the implementation details behind the resource interface are intentionally hidden by the server ๐Ÿ™ˆ

This extends to how header and trailer fields get stored ๐Ÿงš Common header fields like Content-Type will typically be stored and returned on later GET requests, but header and trailer field handling is specific to the resource that got the request. So an origin server SHOULD ignore unrecognized header and trailer fields received in a PUT request (i.e., not save them as part of the resource state) ๐ŸŒˆ

An origin server MUST NOT send a validator field (Section 8.8), such as an ETag or Last-Modified field, in a successful response to PUT unless the request's representation data was saved without any transformation applied to the content (i.e., the resource's new representation data is identical to the content received in the PUT request) and the validator field value reflects the new representation. This requirement lets a user agent know when the representation it sent (and still keeps in memory) is the result of the PUT, so it doesn't need to be fetched again from the origin server ๐Ÿ’œ The new validator(s) in the response can then be used for future conditional requests to prevent accidental overwrites (Section 13.1) โญ

The fundamental difference between POST and PUT is shown by the different intent behind the enclosed representation ๐Ÿ‘‘ The target resource in a POST request is meant to handle the enclosed representation according to the resource's own semantics, whereas the enclosed representation in a PUT request is defined as replacing the state of the target resource. Hence, the intent of PUT is idempotent and visible to intermediaries, even though the exact effect is only known by the origin server ๐Ÿซถ

Proper interpretation of a PUT request assumes the user agent knows which target resource it wants ๐ŸŽฏ A service that picks a proper URI on the client's behalf, after receiving a state-changing request, SHOULD be implemented using the POST method rather than PUT. If the origin server won't make the requested PUT state change to the target resource and instead wants it applied to a different resource, such as when the resource has moved to a different URI, then the origin server MUST send an appropriate 3xx (Redirection) response; the user agent MAY then decide for itself whether or not to redirect the request ๐Ÿฆ‹

A PUT request applied to the target resource can have side effects on other resources ๐ŸŒธ For example, an article might have a URI for identifying "the current version" (a resource) that is separate from the URIs identifying each particular version (different resources that at one point shared the same state as the current version resource). A successful PUT on "the current version" URI might therefore create a new version resource in addition to changing the state of the target resource, and might also cause links to be added between the related resources โœจ

Some origin servers support using the Content-Range header field (Section 14.4) as a request modifier to do a partial PUT, as described in Section 14.5 ๐ŸŽ€

Responses to the PUT method are not cacheable ๐Ÿ™… If a successful PUT request passes through a cache that has one or more stored responses for the target URI, those stored responses will be invalidated (see Section 4.4 of [CACHING]) ๐Ÿ’€

9.3.5. DELETE ๐Ÿงน

The DELETE method requests that the origin server remove the association between the target resource and its current functionality ๐Ÿ˜ค Basically this method is like the "rm" command in UNIX: it expresses a deletion operation on the URI mapping of the origin server, rather than an expectation that the previously associated information gets deleted ๐Ÿ’…

If the target resource has one or more current representations, they might or might not be destroyed by the origin server, and the associated storage might or might not be reclaimed. That depends entirely on the nature of the resource and how the origin server implements it (which is beyond the scope of this specification) ๐Ÿคทโ€โ™€๏ธ Likewise, other implementation aspects of a resource might need to be deactivated or archived as a result of a DELETE, like database or gateway connections. In general, it's assumed that the origin server will only allow DELETE on resources for which it has a prescribed mechanism for doing the deletion ๐Ÿ”

Relatively few resources allow the DELETE method, because its main use is in remote authoring environments where the user has some direction over its effect ๐Ÿ–Š๏ธ For example, a resource that was previously created using a PUT request, or that was identified via the Location header field after a 201 (Created) response to a POST request, might allow a matching DELETE request to undo those actions ๐Ÿฆ‹ Similarly, custom user agent implementations that do an authoring function, like revision control clients using HTTP for remote operations, might use DELETE on the assumption that the server's URI space has been crafted to match a version repository ๐Ÿ“š

If a DELETE method is successfully applied, the origin server SHOULD send:

  • a 202 (Accepted) status code if the action will likely succeed but has not yet been enacted,
  • a 204 (No Content) status code if the action has been enacted and no further information is to be supplied, or
  • a 200 (OK) status code if the action has been enacted and the response message includes a representation describing the status.

Although request message framing is independent of the method used, content received in a DELETE request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]) ๐Ÿšจ A client SHOULD NOT generate content in a DELETE request unless it's made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain ๐Ÿซ 

Responses to the DELETE method are not cacheable ๐Ÿ™… If a successful DELETE request passes through a cache that has one or more stored responses for the target URI, those stored responses will be invalidated (see Section 4.4 of [CACHING]) ๐Ÿ’œ

9.3.6. CONNECT ๐Ÿฆ‹

okay so CONNECT is the method that basically says "hey proxy, can you open a tunnel to this destination for me?" ๐Ÿš‡ If that works, the connection stops acting like HTTP and just blindly forwards data both ways until someone closes it ๐Ÿซถ. Tunnels are super popular for making an end-to-end virtual connection through one or more proxies, and then you can secure that connection with TLS (Transport Layer Security, [TLS13]) ๐Ÿ”. it's giving secure main character energy ๐Ÿ’…

CONNECT has its own special request target that only it uses ๐Ÿ‘‘. It's just the host and port number of the tunnel destination, separated by a colon. There's no default port, so a client MUST send the port number even if the CONNECT request is based on a URI reference whose authority component has an elided port (Section 4.1). For example:

CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com

A server MUST reject a CONNECT request that targets an empty or invalid port number, usually by responding with a 400 (Bad Request) status code ๐Ÿ™…โ€โ™€๏ธ

Because CONNECT changes the request/response vibe of an HTTP connection, specific HTTP versions might map its semantics onto the wire format in different ways ๐ŸŒ€

CONNECT is meant for requests to a proxy ๐ŸŽ€. The recipient can set up the tunnel either by connecting directly to the server named in the request target or, if it's configured to use another proxy, by forwarding the CONNECT request to the next inbound proxy ๐Ÿงš. An origin server MAY accept a CONNECT request, but most origin servers don't implement CONNECT, so don't hold your breath ๐Ÿ’€

Any 2xx (Successful) response means the sender (and all inbound proxies) will switch to tunnel mode right after the response header section ๐ŸŒˆ. Data received after that header section comes from the server named in the request target. Any response that isn't a successful one means the tunnel hasn't been formed yet ๐Ÿ™ˆ

A tunnel closes when a tunnel intermediary notices that either side has closed its connection. At that point the intermediary MUST attempt to send any outstanding data that came from the closed side to the other side, close both connections, and then discard any leftover data that never got delivered ๐Ÿ˜ญ

Proxy authentication might be used to prove you're allowed to create a tunnel ๐Ÿ”‘. For example:

CONNECT server.example.com:443 HTTP/1.1
Host: server.example.com:443
Proxy-Authorization: basic aGVsbG86d29ybGQ=
โš ๏ธ bestie, this part is serious. Setting up a tunnel to arbitrary servers is risky, especially when the destination is a well-known or reserved TCP port that isn't meant for Web traffic ๐Ÿšจ. For example, a CONNECT to "example.com:25" would make the proxy connect to the reserved port for SMTP traffic. If that's allowed, it could trick the proxy into relaying spam email ๐Ÿ“ง๐Ÿ’€. So proxies that support CONNECT SHOULD restrict its use to a limited set of known ports or a configurable list of safe request targets ๐Ÿ”’.

A server MUST NOT send any Transfer-Encoding or Content-Length header fields in a 2xx (Successful) response to CONNECT. And a client MUST ignore any Content-Length or Transfer-Encoding header fields it gets in a successful response to CONNECT ๐Ÿ™…โ€โ™‚๏ธโœจ

A CONNECT request message doesn't have content ๐Ÿซง. What the data sent after the header section of the CONNECT request message means depends on the version of HTTP in use ๐Ÿฆ‹

Responses to the CONNECT method are not cacheable ๐Ÿšซ๐Ÿ’พ


9.3.7. OPTIONS ๐Ÿงš

The OPTIONS method asks for info about the communication options available for the target resource, whether that's at the origin server or some intervening intermediary ๐Ÿ”. It lets a client figure out the options and/or requirements tied to a resource, or what a server is capable of, without implying any actual resource action ๐ŸŒธ

An OPTIONS request with an asterisk (*) as the request target (Section 7.1) applies to the server in general, not to one specific resource ๐ŸŒ. Since a server's options usually depend on the resource, the * request is only really useful as a "ping" or "no-op" kind of method ๐Ÿ“. It does nothing beyond letting the client test the server's capabilities. For example, you could use it to test a proxy for HTTP/1.1 conformance (or lack thereof) ๐Ÿ™ƒ

If the request target isn't an asterisk, the OPTIONS request applies to the options that are available when communicating with that target resource ๐Ÿ’…

A server generating a successful response to OPTIONS SHOULD send any header that might indicate optional features it implements and that apply to the target resource (for example, Allow). That includes potential extensions not defined by this specification ๐ŸŽ€. The response content, if there is any, might also describe the communication options in a machine or human-readable representation ๐Ÿค–. This specification doesn't define a standard format for that representation, but future HTTP extensions might ๐Ÿ”ฎ

A client MAY send a Max-Forwards header field in an OPTIONS request to target a specific recipient in the request chain (see Section 7.6.2) ๐ŸŽฏ. A proxy MUST NOT generate a Max-Forwards header field while forwarding a request, unless that request was received with a Max-Forwards field ๐Ÿšซ

A client that generates an OPTIONS request containing content MUST send a valid Content-Type header field describing the representation media type ๐Ÿ“. Heads up, though: this specification doesn't define any use for such content ๐Ÿ™ˆ

Responses to the OPTIONS method are not cacheable ๐Ÿšซ๐Ÿ’พ


9.3.8. TRACE ๐Ÿ”

The TRACE method asks for a remote, application-level loop-back of the request message ๐Ÿชž. The final recipient of the request SHOULD reflect the message it received back to the client as the content of a 200 (OK) response, minus some fields described below ๐Ÿ’–. The "message/http" format (Section 10.1 of [HTTP/1.1]) is one way to do that โœจ. The final recipient is either the origin server or the first server to receive a Max-Forwards value of zero (0) in the request (Section 7.6.2) ๐Ÿ

A client MUST NOT generate fields in a TRACE request that contain sensitive data the response might disclose. For example, it would be foolish for a user agent to send stored user credentials (Section 11) or cookies [COOKIE] in a TRACE request ๐Ÿ™…โ€โ™€๏ธ๐Ÿช. The final recipient SHOULD exclude any request fields that are likely to contain sensitive data when it generates the response content ๐Ÿ”

TRACE lets the client see what's being received at the other end of the request chain, and use that for testing or diagnostics ๐Ÿฉบ. The Via header field (Section 7.6.3) is especially interesting, since it acts as a trace of the request chain ๐Ÿ›ค๏ธ. The Max-Forwards header field lets the client limit how long the request chain gets, which is handy for testing a chain of proxies that's forwarding messages in an infinite loop ๐ŸŒ€โ™พ๏ธ

A client MUST NOT send content in a TRACE request ๐Ÿšซ

Responses to the TRACE method are not cacheable ๐Ÿšซ๐Ÿ’พ


10. Message Context ๐ŸŒท

10.1. Request Context Fields ๐Ÿง

The request header fields below give extra info about the request context ๐Ÿซถ. That includes details about the user, the user agent, and the resource behind the request ๐Ÿ‘‘

10.1.1. Expect

The "Expect" header field in a request indicates a certain set of behaviors (expectations) that need to be supported by the server in order to properly handle this request. ๐Ÿ’…โœจ

Expect =      #expectation
expectation = token [ "=" ( token / quoted-string ) parameters ]

The Expect field value is case-insensitive. ๐ŸŽ€

The only expectation defined by this specification is "100-continue" (with no defined parameters). ๐Ÿฆ‹

A server that receives an Expect field value containing a member other than 100-continue MAY respond with a 417 (Expectation Failed) status code to indicate that the unexpected expectation cannot be met. ๐Ÿ™ˆ

okay so a "100-continue" expectation basically tells the server "hey bestie, I'm about to send a big chunk of content, and I want a 100 (Continue) interim response first, but only if the method, target URI, and header fields aren't already enough for an immediate success, redirect, or error response." ๐Ÿซถ This lets the client pause and check that it's actually worth sending the data before it starts filling the pipes, which is super efficient when the data is huge or when the client expects an error, like when it's sending a state-changing method for the first time without previously verified authentication credentials. ๐Ÿ˜ญ๐Ÿ”ฅ

For example, a request that begins with

PUT /somewhere/fun HTTP/1.1
Host: origin.example.com
Content-Type: video/h264
Content-Length: 1234567890987
Expect: 100-continue

lets the origin server immediately respond with an error message, such as 401 (Unauthorized) or 405 (Method Not Allowed), before the client starts sending an unnecessary data transfer. ๐Ÿ’€๐Ÿ’–

Requirements for clients:

  • A client MUST NOT generate a 100-continue expectation in a request that does not include content. ๐Ÿ™…โ€โ™€๏ธ
  • A client that will wait for a 100 (Continue) response before sending the request content MUST send an Expect header field containing a 100-continue expectation. ๐ŸŽ€
  • A client that sends a 100-continue expectation is not required to wait for any specific length of time; such a client MAY proceed to send the content even if it has not yet received a response. Furthermore, since 100 (Continue) responses cannot be sent through an HTTP/1.0 intermediary, such a client SHOULD NOT wait for an indefinite period before sending the content. โณโœจ
  • A client that receives a 417 (Expectation Failed) status code in response to a request containing a 100-continue expectation SHOULD repeat that request without a 100-continue expectation, since the 417 response merely indicates that the response chain does not support expectations (e.g., it passes through an HTTP/1.0 server). ๐Ÿ”๐ŸŒธ

Requirements for servers:

  • A server that receives a 100-continue expectation in an HTTP/1.0 request MUST ignore that expectation. ๐Ÿ™ƒ
  • A server MAY omit sending a 100 (Continue) response if it has already received some or all of the content for the corresponding request, or if the framing indicates that there is no content. ๐Ÿงš
  • A server that sends a 100 (Continue) response MUST ultimately send a final status code, once it receives and processes the request content, unless the connection is closed prematurely. ๐Ÿ’œ
  • A server that responds with a final status code before reading the entire request content SHOULD indicate whether it intends to close the connection (e.g., see Section 9.6 of [HTTP/1.1]) or continue reading the request content. ๐Ÿ“

Upon receiving an HTTP/1.1 (or later) request that has a method, target URI, and complete header section that contains a 100-continue expectation and an indication that request content will follow, an origin server MUST send either:

  • an immediate response with a final status code, if that status can be determined by examining just the method, target URI, and header fields, or
  • an immediate 100 (Continue) response to encourage the client to send the request content.

The origin server MUST NOT wait for the content before sending the 100 (Continue) response. ๐Ÿ‘‘

Upon receiving an HTTP/1.1 (or later) request that has a method, target URI, and complete header section that contains a 100-continue expectation and indicates a request content will follow, a proxy MUST either:

  • send an immediate response with a final status code, if that status can be determined by examining just the method, target URI, and header fields, or
  • forward the request toward the origin server by sending a corresponding request-line and header section to the next inbound server.

If the proxy believes (from configuration or past interaction) that the next inbound server only supports HTTP/1.0, the proxy MAY generate an immediate 100 (Continue) response to encourage the client to begin sending the content. ๐ŸŒˆ


10.1.2. From

The "From" header field contains an Internet email address for a human user who controls the requesting user agent. The address ought to be machine-usable, as defined by "mailbox" in Section 3.4 of [RFC5322]: ๐Ÿ“ฌ

From    = mailbox

mailbox = <mailbox, see [RFC5322], Section 3.4>

An example is:

From: spider-admin@example.org

The From header field is rarely sent by non-robotic user agents. A user agent SHOULD NOT send a From header field without explicit configuration by the user, since that might conflict with the user's privacy interests or their site's security policy. ๐Ÿ”’

A robotic user agent SHOULD send a valid From header field so that the person responsible for running the robot can be contacted if problems occur on servers, such as if the robot is sending excessive, unwanted, or invalid requests. ๐Ÿค–๐Ÿ’Œ

A server SHOULD NOT use the From header field for access control or authentication, since its value is expected to be visible to anyone receiving or observing the request and is often recorded within logfiles and error reports without any expectation of privacy. ๐Ÿ™…โ€โ™€๏ธ๐Ÿชต


10.1.3. Referer

The "Referer" [sic] header field allows the user agent to specify a URI reference for the resource from which the target URI was obtained (i.e., the "referrer", though the field name is misspelled). ๐Ÿ™ˆ A user agent MUST NOT include the fragment and userinfo components of the URI reference [URI], if any, when generating the Referer field value. ๐Ÿ›ก๏ธ

Referer = absolute-URI / partial-URI

The field value is either an absolute-URI or a partial-URI. In the latter case (Section 4), the referenced URI is relative to the target URI ([URI], Section 5). ๐Ÿงญ

The Referer header field allows servers to generate back-links to other resources for simple analytics, logging, optimized caching, etc. It also allows obsolete or mistyped links to be found for maintenance. Some servers use the Referer header field as a means of denying links from other sites (so-called "deep linking") or restricting cross-site request forgery (CSRF), but not all requests contain it. ๐Ÿ•ต๏ธโ€โ™€๏ธ

Example:

Referer: http://www.example.org/hypertext/Overview.html

If the target URI was obtained from a source that does not have its own URI (e.g., input from the user keyboard, or an entry within the user's bookmarks/favorites), the user agent MUST either exclude the Referer header field or send it with a value of "about:blank". ๐Ÿ”–

The Referer header field value need not convey the full URI of the referring resource; a user agent MAY truncate parts other than the referring origin. โœ‚๏ธ

The Referer header field has the potential to reveal information about the request context or browsing history of the user, which is a privacy concern if the referring resource's identifier reveals personal information (such as an account name) or a resource that is supposed to be confidential (such as behind a firewall or internal to a secured service). Most general-purpose user agents do not send the Referer header field when the referring resource is a local "file" or "data" URI. A user agent SHOULD NOT send a Referer header field if the referring resource was accessed with a secure protocol and the request target has an origin differing from that of the referring resource, unless the referring resource explicitly allows Referer to be sent. A user agent MUST NOT send a Referer header field in an unsecured HTTP request if the referring resource was accessed with a secure protocol. See Section 17.9 for additional security considerations. ๐Ÿšจ๐Ÿ”

Some intermediaries have been known to indiscriminately remove Referer header fields from outgoing requests. This has the unfortunate side effect of interfering with protection against CSRF attacks, which can be far more harmful to their users. Intermediaries and user agent extensions that wish to limit information disclosure in Referer ought to restrict their changes to specific edits, such as replacing internal domain names with pseudonyms or truncating the query and/or path components. An intermediary SHOULD NOT modify or delete the Referer header field when the field value shares the same scheme and host as the target URI. ๐Ÿ˜ค๐Ÿ’…


10.1.4. TE

The "TE" header field describes capabilities of the client with regard to transfer codings and trailer sections. ๐ŸŽ

As described in Section 6.5, a TE field with a "trailers" member sent in a request indicates that the client will not discard trailer fields. ๐Ÿซง

TE is also used within HTTP/1.1 to advise servers about which transfer codings the client is able to accept in a response. As of publication, only HTTP/1.1 uses transfer codings (see Section 7 of [HTTP/1.1]). ๐Ÿฆ‹

The TE field value is a list of members, with each member (aside from "trailers") consisting of a transfer coding name token with an optional weight indicating the client's relative preference for that transfer coding (Section 12.4.2) and optional parameters for that transfer coding. ๐ŸŒธ

TE                 = #t-codings
t-codings          = "trailers" / ( transfer-coding [ weight ] )
transfer-coding    = token *( OWS ";" OWS transfer-parameter )
transfer-parameter = token BWS "=" BWS ( token / quoted-string )

A sender of TE MUST also send a "TE" connection option within the Connection header field (Section 7.6.1) to inform intermediaries not to forward this field. ๐Ÿ™Œโœจ

10.1.5. User-Agent โœจ

okay so the "User-Agent" header field is basically the little ID card a user agent hands over with each request ๐Ÿชช๐Ÿ’– servers read it to figure out which client caused a weird bug, to tailor responses around a particular client's quirks, and for analytics on which browsers and operating systems are popular ๐Ÿ“Š๐ŸŒธ bestie, a user agent SHOULD send a User-Agent header field in each request unless it's specifically configured not to ๐Ÿซถ

User-Agent = product *( RWS ( product / comment ) )

the field value is one or more product identifiers, each followed by zero or more comments (Section 5.6.5), and together they identify the user agent software and its important subproducts โœจ by convention, the product identifiers are listed from most significant to least significant for identifying the software ๐Ÿ‘‘ each product identifier is a name with an optional version ๐ŸŽ€

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

a sender SHOULD keep generated product identifiers limited to what's actually needed to identify the product ๐Ÿ’… and a sender MUST NOT put advertising or other nonessential info inside a product identifier ๐Ÿ™…โ€โ™€๏ธ a sender SHOULD NOT put anything in product-version that isn't a version identifier either, because successive versions of the same product name ought to differ only in the product-version part ๐Ÿฆ‹

Example:

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

a user agent SHOULD NOT generate a User-Agent header field with needlessly fine-grained detail, and SHOULD limit the addition of subproducts by third parties ๐Ÿ™ˆ overly long, detailed User-Agent values make requests slower and raise the risk of someone being identified against their wishes, which is called "fingerprinting" ๐Ÿ˜ญ๐Ÿ”ฅ

also, implementations are encouraged NOT to use other implementations' product tokens to claim compatibility with them, because that totally defeats the whole purpose of the field ๐Ÿ’€ if a user agent pretends to be a different one, recipients can assume the user actually wants responses tailored for that identified agent, even if those might not work as well for the real one ๐ŸŒˆ


10.2. Response Context Fields ๐ŸŽ€

these response header fields give extra info about the response beyond what the status code already says ๐Ÿงš that includes info about the server, the target resource, or related resources ๐Ÿ’œ

10.2.1. Allow ๐Ÿฆ‹

the "Allow" header field lists the set of methods the target resource advertises as supported ๐Ÿ’… its whole job is to tell the recipient which request methods are valid for the resource, and nothing more ๐Ÿซถ

Allow = #method

Example of use:

Allow: GET, HEAD, PUT

the actual set of allowed methods is decided by the origin server at the time of each request โฐ an origin server MUST generate an Allow header field in a 405 (Method Not Allowed) response and MAY do so in any other response ๐Ÿ“ an empty Allow field value means the resource allows no methods, which could happen in a 405 response if the resource was temporarily disabled by configuration ๐ŸŒธ

a proxy MUST NOT modify the Allow header field ๐Ÿ™…โ€โ™€๏ธ it doesn't need to understand every indicated method to handle them under the generic message handling rules, so it can just leave it alone โœจ

10.2.2. Location ๐Ÿ“

the "Location" header field shows up in some responses to point at a specific resource related to the response ๐Ÿ—บ๏ธ what the relationship means depends on the combo of request method and status code semantics ๐Ÿ’–

Location = URI-reference

the field value is a single URI-reference ๐ŸŽ€ when it looks like a relative reference ([URI], Section 4.2), the final value gets computed by resolving it against the target URI ([URI], Section 5) ๐Ÿงš

for 201 (Created) responses, the Location value refers to the primary resource created by the request ๐ŸŒŸ for 3xx (Redirection) responses, the Location value refers to the preferred target resource to automatically redirect the request to ๐Ÿฆ‹

if the Location value in a 3xx (Redirection) response doesn't have a fragment component, a user agent MUST process the redirection as if the value inherits the fragment component of the URI reference used to make the target URI (so the redirection inherits the original reference's fragment, if there is one) ๐Ÿซถ

for example, a GET request generated for the URI reference "http://www.example.org/~tim" might get a 303 (See Other) response with this header field:

Location: /People.html#tim

which suggests the user agent redirect to "http://www.example.org/People.html#tim" ๐Ÿ’œ

likewise, a GET request generated for the URI reference "http://www.example.org/index.html#larry" might get a 301 (Moved Permanently) response with this header field:

Location: http://www.example.net/index.html

which suggests the user agent redirect to "http://www.example.net/index.html#larry", preserving the original fragment identifier ๐ŸŒˆ

there are situations where a fragment identifier in a Location value wouldn't be appropriate ๐Ÿ™ˆ for example, the Location header field in a 201 (Created) response is supposed to give a URI that's specific to the created resource ๐Ÿ“

Note: some recipients try to recover from Location header fields that aren't valid URI references ๐Ÿ› ๏ธ this specification doesn't mandate or define that processing, but it does allow it for robustness โœจ a Location field value can't hold a list of members, because the comma list separator is a valid data character within a URI-reference ๐Ÿ˜ญ if an invalid message is sent with multiple Location field lines, a recipient along the path might combine those field lines into one value ๐Ÿ’€ recovering a valid Location field value from that mess is hard and not interoperable across implementations ๐Ÿ”ฅ
Note: the Content-Location header field (Section 8.7) differs from Location because Content-Location refers to the most specific resource corresponding to the enclosed representation ๐ŸŽ€ so it's totally possible for a response to contain both the Location and Content-Location header fields ๐Ÿ’…

10.2.3. Retry-After โณ

servers send the "Retry-After" header field to say how long the user agent ought to wait before making a follow-up request ๐Ÿ•ฐ๏ธ when it's sent with a 503 (Service Unavailable) response, Retry-After tells the client how long the service is expected to be unavailable ๐ŸŒธ when it's sent with any 3xx (Redirection) response, Retry-After gives the minimum time the user agent is asked to wait before issuing the redirected request ๐Ÿงš

the Retry-After field value can be either an HTTP-date or a number of seconds to delay after receiving the response ๐Ÿ’–

Retry-After = HTTP-date / delay-seconds

a delay-seconds value is a non-negative decimal integer representing time in seconds ๐Ÿฆ‹

delay-seconds  = 1*DIGIT

two examples of its use:

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

in the latter example, the delay is 2 minutes ๐ŸŽ€

10.2.4. Server ๐Ÿ–ฅ๏ธ

the "Server" header field contains info about the software the origin server used to handle the request ๐Ÿ’ป clients often use it to figure out the scope of reported interoperability problems, to work around or tailor requests to avoid particular server limitations, and for analytics on server or operating system use ๐Ÿ“Š an origin server MAY generate a Server header field in its responses โœจ

Server = product *( RWS ( product / comment ) )

the Server header field value is one or more product identifiers, each followed by zero or more comments (Section 5.6.5), which together identify the origin server software and its significant subproducts ๐Ÿ‘‘ by convention, the product identifiers are listed from most to least significant for identifying the origin server software ๐Ÿซถ each product identifier is a name and optional version, as defined in Section 10.1.5 ๐Ÿ’…

Example:

Server: CERN/3.0 libwww/2.17

an origin server SHOULD NOT generate a Server header field with needlessly fine-grained detail, and SHOULD limit the addition of subproducts by third parties ๐Ÿ™ˆ overly long, detailed Server values make responses slower and can reveal internal implementation details that might make it (slightly) easier for attackers to find and exploit known security holes ๐Ÿ˜ญ๐Ÿ”ฅ


11. HTTP Authentication ๐Ÿ”

11.1. Authentication Scheme ๐Ÿ—๏ธ

HTTP gives us a general framework for access control and authentication ๐Ÿ’– it's an extensible set of challenge-response authentication schemes, so a server can challenge a client request and a client can provide authentication info back ๐Ÿฆ‹ it uses a case-insensitive token to identify the authentication scheme โœจ

auth-scheme    = token

aside from the general framework, this document doesn't specify any authentication schemes ๐Ÿ™ˆ new and existing schemes are specified independently and ought to be registered in the "Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry" ๐Ÿ“‹ for example, the "basic" and "digest" schemes are defined by [RFC7617] and [RFC7616], respectively ๐ŸŒธ

11.2. Authentication Parameters ๐ŸŽ€

the authentication scheme is followed by any extra info needed to authenticate using that scheme ๐Ÿงš that info is either a comma-separated list of parameters or a single sequence of characters that can hold base64-encoded information ๐Ÿ’œ

token68        = 1*( ALPHA / DIGIT /
                     "-" / "." / "_" / "~" / "+" / "/" ) *"="

the token68 syntax allows the 66 unreserved URI characters ([URI]), plus a few others, so it can hold a base64, base64url (URL and filename safe alphabet), base32, or base16 (hex) encoding, with or without padding, but excluding whitespace ([RFC4648]) ๐ŸŒˆ

authentication parameters are name/value pairs, where the name token is matched case-insensitively, and each parameter name MUST only occur once per challenge ๐Ÿšซ

auth-param     = token BWS "=" BWS ( token / quoted-string )

parameter values can be written either as a "token" or as a "quoted-string" (Section 5.6) ๐Ÿซถ authentication scheme definitions need to accept both notations, for both senders and recipients, so recipients can use generic parsing components no matter which scheme it is โœจ

for backwards compatibility, authentication scheme definitions can restrict the format for senders to one of the two variants ๐Ÿ•ฐ๏ธ this can be important when it's known that deployed implementations will fail when they hit one of the two formats ๐Ÿ’€


11.3. Challenge and Response ๐Ÿ’Œ

okay so the 401 (Unauthorized) response is how an origin server says "wait, who even are you?" ๐Ÿ™ˆ It's basically a bouncer checking your ID. The server includes a WWW-Authenticate header field with at least one challenge that applies to the resource you asked for.

The 407 (Proxy Authentication Required) response is the same vibe, but it comes from a proxy instead. It challenges the client with a Proxy-Authenticate header field containing at least one challenge that applies to that proxy for the requested resource. ๐Ÿงš

  challenge   = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
Note: Many clients fail to parse a challenge that contains an unknown scheme. A workaround for this problem is to list well-supported schemes (such as "basic") first. ๐Ÿซถ

So a user agent that wants to prove who it is to an origin server (usually after a 401, but not always) can include an Authorization header field in its request. ๐ŸŽ€

A client that wants to authenticate with a proxy (usually after a 407, but not always) can do the same thing with a Proxy-Authorization header field. ๐Ÿฆ‹

11.4. Credentials ๐Ÿ”‘

The Authorization and Proxy-Authorization field values both hold the client's credentials for the realm of the requested resource. These are based on a challenge that was received in an earlier response, possibly way back in the past. ๐Ÿ’…

When the user agent makes these values, it ought to pick the challenge with the most secure auth-scheme that it understands, and get credentials from the user where that makes sense. Sending credentials inside header field values has big security implications for the confidentiality of the underlying connection, as described in Section 17.16.1. This is serious bestie stuff ๐Ÿ˜ญ

  credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]

Now, if a server gets a request for a protected resource and the credentials are missing, invalid (like a wrong password), or only partial (like when the scheme needs more than one round trip), the origin server SHOULD send a 401 (Unauthorized) response. That response has a WWW-Authenticate header field with at least one challenge that applies to the resource, and it can be a new one. ๐ŸŒธ

Same energy for proxies: if a request is missing proxy credentials or has invalid or partial ones, a proxy that needs authentication SHOULD generate a 407 (Proxy Authentication Required) response. That response carries a Proxy-Authenticate header field with at least one challenge that applies to the proxy, possibly a new one. โœจ

A server that gets valid credentials that still aren't enough to get in ought to respond with the 403 (Forbidden) status code (Section 15.5.4). Valid but not good enough, periodt ๐Ÿ’€

HTTP doesn't force applications into this simple challenge-response setup for access authentication. Other mechanisms can be used too, like authentication at the transport level or through message encapsulation, along with extra header fields that carry authentication info. This specification doesn't define any of those additional mechanisms though, so that's a separate story ๐Ÿงš

Also, a bunch of custom user authentication mechanisms pass their tokens around using the Set-Cookie and Cookie header fields, which are defined in [COOKIE]. Iykyk ๐Ÿ“

11.5. Establishing a Protection Space (Realm) ๐Ÿฐ

The "realm" authentication parameter is reserved for authentication schemes that want to indicate a scope of protection. It's like drawing a fence around a bunch of resources. ๐ŸŒˆ

A "protection space" is defined by the origin (see Section 4.3.1) of the server being accessed, combined with the realm value if there is one. Realms let a server split its protected resources into multiple protection spaces, and each one can have its own authentication scheme and/or authorization database. The realm value is a string, usually assigned by the origin server, and it can have extra meaning that depends on the authentication scheme. Also, a single response can have multiple challenges that use the same auth-scheme but have different realms. Wild, right? ๐Ÿ‘‘

The protection space decides where credentials can be applied automatically. If a prior request was authorized, the user agent MAY reuse those same credentials for every other request within that protection space, for however long the authentication scheme, its parameters, and/or user preferences allow (like a configurable inactivity timeout). ๐Ÿฆ‹

The size of a protection space, and therefore which requests might get credentials applied automatically, isn't always obvious to clients without extra info. An authentication scheme might define parameters that describe how big the protection space is. Unless the authentication scheme specifically allows it, a single protection space cannot extend outside the scope of its server. Boundaries are important, bestie ๐Ÿซถ

For historical reasons, a sender MUST only generate the quoted-string syntax. Recipients might have to support both token and quoted-string syntax to play nicely with existing clients, which have been accepting both notations for a long time. Very reliable of them ๐Ÿ™ˆ

11.6. Authenticating Users to Origin Servers ๐Ÿง‘โ€๐Ÿ’ป

11.6.1. WWW-Authenticate ๐Ÿชช

The WWW-Authenticate response header field tells you which authentication scheme(s) and parameters apply to the target resource.

  WWW-Authenticate = #challenge

A server that generates a 401 (Unauthorized) response MUST send a WWW-Authenticate header field with at least one challenge. A server MAY also generate a WWW-Authenticate header field in other response messages, to show that supplying credentials (or different ones) might change the response. ๐Ÿ’–

A proxy that forwards a response MUST NOT modify any WWW-Authenticate header fields in it. Hands off! ๐Ÿ™…โ€โ™€๏ธ

User agents should be extra careful when parsing this field value, because it might hold more than one challenge. Each challenge can also contain a comma-separated list of authentication parameters. On top of that, the header field itself can show up multiple times. It's a lot, so take your time ๐Ÿ’…

Here's an example:

WWW-Authenticate: Basic realm="simple", Newauth realm="apps",
                 type=1, title="Login to \"apps\""

This header field has two challenges. One is for the "Basic" scheme with a realm value of "simple", and the other is for the "Newauth" scheme with a realm value of "apps". It also includes two extra parameters, "type" and "title". โœจ

Some user agents don't recognize this form, though. So sending a WWW-Authenticate field value with more than one member on the same field line might not be interoperable. Plot twist ๐Ÿ˜ญ

Note: The challenge grammar production uses the list syntax as well. Therefore, a sequence of comma, whitespace, and comma can be considered either as applying to the preceding challenge, or to be an empty entry in the list of challenges. In practice, this ambiguity does not affect the semantics of the header field value and thus is harmless. ๐ŸŒธ

11.6.2. Authorization ๐Ÿ—๏ธ

The Authorization header field lets a user agent authenticate itself with an origin server, usually (but not always) after it gets a 401 (Unauthorized) response. Its value is made of credentials that hold the user agent's authentication info for the realm of the requested resource. ๐Ÿ’œ

  Authorization = credentials

If a request is authenticated and a realm is specified, the same credentials are presumed valid for all other requests within that realm. This assumes the authentication scheme itself doesn't require otherwise, like credentials that change based on a challenge value or that rely on synchronized clocks. ๐Ÿงš

A proxy that forwards a request MUST NOT modify any Authorization header fields in that request. For details and requirements on how HTTP caches handle the Authorization header field, see Section 3.5 of [CACHING]. ๐Ÿ™ˆ

11.6.3. Authentication-Info ๐ŸŽ

HTTP authentication schemes can use the Authentication-Info response field to share info after the client's credentials have been accepted. This can include a finalization message from the server, like server authentication. Ooh, mutual vibes ๐Ÿค

The field value is a list of parameters (name/value pairs) that use the "auth-param" syntax from Section 11.3. This specification only describes the generic format. Authentication schemes that use Authentication-Info define the individual parameters themselves. For instance, the "Digest" Authentication Scheme defines multiple parameters in Section 3.5 of [RFC7616]. ๐ŸŒˆ

  Authentication-Info = #auth-param

The Authentication-Info field can show up in any HTTP response, no matter the request method or status code. Its semantics come from the authentication scheme named by the Authorization header field (Section 11.6.2) of the corresponding request. ๐Ÿ‘‘

A proxy that forwards a response is not allowed to modify the field value in any way. Don't touch it ๐Ÿ™…โ€โ™€๏ธ

Authentication-Info can be sent as a trailer field (Section 6.5), but only when the authentication scheme explicitly allows it. ๐Ÿฆ‹

11.7. Authenticating Clients to Proxies ๐Ÿšช

11.7.1. Proxy-Authenticate ๐Ÿ›ก๏ธ

The Proxy-Authenticate header field has at least one challenge that shows which authentication scheme(s) and parameters apply to the proxy for this request. A proxy MUST send at least one Proxy-Authenticate header field in each 407 (Proxy Authentication Required) response it generates. ๐Ÿ‘

  Proxy-Authenticate = #challenge

Unlike WWW-Authenticate, the Proxy-Authenticate header field only applies to the next outbound client on the response chain. That's because only the client that picked a given proxy is likely to have the credentials needed to authenticate. ๐Ÿซถ

But when several proxies sit inside the same administrative domain, like office and regional caching proxies in a big corporate network, credentials are often generated by the user agent and passed down the hierarchy until someone uses them. So in that setup, it'll look like Proxy-Authenticate is being forwarded, because each proxy sends the same challenge set. Looks like forwarding, but it's a vibe check ๐Ÿ˜ญ

Note that the parsing considerations for WWW-Authenticate also apply to this header field. See Section 11.6.1 for the details. ๐Ÿ’…

11.7.2. Proxy-Authorization ๐Ÿ”

The Proxy-Authorization header field lets the client identify itself (or its user) to a proxy that requires authentication. Its value is made of credentials holding the client's authentication info for the proxy and/or the realm of the requested resource. ๐Ÿ’–

  Proxy-Authorization = credentials

Unlike Authorization, the Proxy-Authorization header field only applies to the next inbound proxy that asked for authentication with the Proxy-Authenticate header field. When multiple proxies are chained together, the first inbound proxy that was expecting credentials is the one that consumes the Proxy-Authorization header field. ๐ŸŒธ

A proxy MAY relay the credentials from the client request to the next proxy, if that's how the proxies cooperatively authenticate a given request. Teamwork makes the dream work ๐Ÿซถ๐Ÿฆ‹

11.7.3. Proxy-Authentication-Info ๐ŸŽ€

Okay bestie, Proxy-Authentication-Info is basically the twin of Authentication-Info ๐Ÿ‘ฏโ€โ™€๏ธ but it's for proxy auth (see Section 11.3) ๐Ÿ’…. Its meaning comes from whatever auth scheme the Proxy-Authorization header on the matching request used (Section 11.7.2) ๐Ÿ”ฅ:

Proxy-Authentication-Info = #auth-param

BUT, unlike the regular one, this header only applies to the next outbound client on the response chain ๐Ÿ˜ญ. Only the client that picked that proxy is likely to have the credentials it needs to do the auth, so it makes sense ๐Ÿงš. Now here's the plot twist: when a bunch of proxies live in the same administrative domain (like office and regional caching proxies in a big corporate network ๐Ÿข), it's super common for the user agent to generate credentials and pass them down the hierarchy until something consumes them ๐Ÿ”—. So in that setup, it'll look like Proxy-Authentication-Info is getting forwarded, because every proxy sends the same field value ๐Ÿ‘€.

Proxy-Authentication-Info can be sent as a trailer field (Section 6.5) when the authentication scheme explicitly allows this โœจ.

12. Content Negotiation ๐ŸŒˆ

When responses convey content, whether they're a success or an error, the origin server often has different ways of representing that info ๐Ÿ’–. Like, different formats, languages, or encodings ๐ŸŒธ. Different users or user agents might also have different capabilities, characteristics, or preferences that could change which representation, out of the ones available, would be best to deliver โœจ. That's why HTTP gives us mechanisms for content negotiation ๐Ÿซถ.

This specification defines three patterns of content negotiation that can be made visible within the protocol ๐Ÿ‘‘: "proactive" negotiation, where the server picks the representation based on the user agent's stated preferences; "reactive" negotiation, where the server gives a list of representations for the user agent to choose from; and "request content" negotiation, where the user agent picks the representation for a future request based on the server's stated preferences in past responses ๐Ÿฆ‹.

There are other patterns too ๐Ÿ’…. "Conditional content" is when the representation is made of multiple parts that get selectively rendered based on user agent parameters. "Active content" is when the representation has a script that makes extra, more specific requests based on user agent characteristics. And "Transparent Content Negotiation" ([RFC2295]) is when an intermediary does the selecting ๐Ÿงš. These patterns aren't mutually exclusive, and each one has trade-offs in how applicable and practical it is ๐Ÿ“.

Note that, in all cases, HTTP is not aware of the resource semantics ๐Ÿ™ˆ. How consistently an origin server responds to requests over time and across the different dimensions of content negotiation, and therefore how "same" a resource's observed representations stay over time, is decided entirely by whatever entity or algorithm picks or generates those responses ๐Ÿ’œ.

12.1. Proactive Negotiation ๐Ÿ”ฅ

When the user agent sends content negotiation preferences in a request to encourage an algorithm at the server to pick the preferred representation, it's called "proactive negotiation" (a.k.a., "server-driven negotiation") ๐Ÿ’–. Selection is based on the available representations for a response (the dimensions it might vary over, like language, content coding, etc.) compared against various info in the request. That includes both the explicit negotiation header fields below and implicit characteristics, like the client's network address or parts of the User-Agent field ๐Ÿ‘€.

Proactive negotiation is great when the algorithm for choosing among the available representations is hard to describe to a user agent ๐Ÿง . It's also useful when the server wants to send its "best guess" along with the first response. If that "best guess" is good enough for the user, this skips the round-trip delay of a follow-up request โญ. To improve the server's guess, a user agent MAY send request header fields that describe its preferences ๐ŸŽ€.

Proactive negotiation has some serious disadvantages, though ๐Ÿ˜ญ:

  • It's impossible for the server to accurately figure out what might be "best" for any given user, since that would need complete knowledge of both the user agent's capabilities and the intended use for the response (e.g., does the user want to view it on screen or print it on paper?);
  • Having the user agent describe its capabilities in every request can be both super inefficient (since only a small percentage of responses have multiple representations) and a potential risk to the user's privacy ๐Ÿ™ˆ;
  • It complicates the implementation of an origin server and the algorithms for generating responses to a request; and,
  • It limits how reusable responses are for shared caching.

A user agent can't rely on proactive negotiation preferences being consistently honored ๐Ÿ’€. The origin server might not implement proactive negotiation for the requested resource, or it might decide that sending a response that doesn't match the user agent's preferences is better than sending a 406 (Not Acceptable) response ๐Ÿคทโ€โ™€๏ธ.

A Vary header field (Section 12.5.5) is often sent in a response subject to proactive negotiation to show what parts of the request info were used in the selection algorithm ๐Ÿงš.

The request header fields Accept, Accept-Charset, Accept-Encoding, and Accept-Language are defined below so a user agent can do proactive negotiation of the response content ๐Ÿ’…. The preferences sent in these fields apply to any content in the response, including representations of the target resource, representations of error or processing status, and potentially even the miscellaneous text strings that might show up within the protocol ๐ŸŒˆ.

12.2. Reactive Negotiation ๐Ÿฆ‹

With "reactive negotiation" (a.k.a., "agent-driven negotiation"), the user agent does the selecting of content (no matter the status code) after it gets an initial response ๐Ÿซถ. The mechanism for reactive negotiation can be as simple as a list of references to alternative representations ๐Ÿ“.

If the user agent isn't satisfied by the initial response content, it can make a GET request on one or more of the alternative resources to get a different representation ๐Ÿƒโ€โ™€๏ธ. Picking those alternatives might happen automatically (by the user agent) or manually (e.g., the user picks from a hypertext menu) ๐Ÿ‘†.

A server might choose not to send an initial representation, other than the list of alternatives, and so signal that reactive negotiation by the user agent is preferred โœจ. For example, the alternatives listed in responses with the 300 (Multiple Choices) and 406 (Not Acceptable) status codes include info about the available representations, so the user or user agent can react by making a selection ๐Ÿ’–.

Reactive negotiation is a win when the response would vary over commonly used dimensions (like type, language, or encoding) ๐ŸŒธ, when the origin server can't figure out a user agent's capabilities just by looking at the request ๐Ÿ”, and generally when public caches are used to spread out server load and cut down on network usage ๐ŸŒ.

Reactive negotiation does have downsides ๐Ÿ˜ญ. Sending a list of alternatives to the user agent degrades user-perceived latency if it's sent in the header section, and you need a second request to get an alternate representation. Also, this specification doesn't define a mechanism for automatic selection, though it doesn't stop one from being developed later ๐Ÿ”ฎ.

12.3. Request Content Negotiation ๐ŸŒธ

When content negotiation preferences are sent in a server's response, the listed preferences are called "request content negotiation" because they're meant to influence which content gets picked for subsequent requests to that resource ๐Ÿ’œ. For example, the Accept (Section 12.5.1) and Accept-Encoding (Section 12.5.3) header fields can be sent in a response to indicate preferred media types and content codings for subsequent requests to that resource ๐ŸŽ€.

Similarly, Section 3.1 of [RFC5789] defines the "Accept-Patch" response header field ๐Ÿงš, which lets clients discover which content types are accepted in PATCH requests ๐Ÿ”.

12.4. Content Negotiation Field Features ๐Ÿ’…

12.4.1. Absence ๐Ÿ™ˆ

For each of the content negotiation fields, a request that doesn't contain the field implies the sender has no preference on that dimension of negotiation โœจ.

If a content negotiation header field is present in a request and none of the available representations for the response can be considered acceptable according to it, the origin server can either honor the header field by sending a 406 (Not Acceptable) response, or disregard the header field by treating the response as if it's not subject to content negotiation for that request header field ๐Ÿค”. That doesn't mean, though, that the client will actually be able to use the representation ๐Ÿ’€.

Note: A user agent sending these header fields makes it easier for a server to identify an individual by virtue of the user agent's request characteristics (Section 17.13). ๐Ÿ”

12.4.2. Quality Values ๐Ÿ’–

The content negotiation fields defined by this specification use a common parameter, named "q" (case-insensitive), to assign a relative "weight" to the preference for that associated kind of content ๐ŸŒˆ. This weight is called a "quality value" (or "qvalue") because the same parameter name is often used in server configurations to assign a weight to the relative quality of the various representations that can be selected for a resource โญ.

The weight is normalized to a real number in the range 0 through 1, where 0.001 is the least preferred and 1 is the most preferred. A value of 0 means "not acceptable". If no "q" parameter is present, the default weight is 1 ๐Ÿ“.

weight = OWS ";" OWS "q=" qvalue
qvalue = ( "0" [ "." 0*3DIGIT ] )
       / ( "1" [ "." 0*3("0") ] )

A sender of qvalue MUST NOT generate more than three digits after the decimal point ๐Ÿ™…โ€โ™€๏ธ. User configuration of these values ought to be limited in the same fashion ๐Ÿซถ.

12.4.3. Wildcard Values ๐Ÿฆ‹

Most of these header fields, where indicated, define a wildcard value ("*") to select unspecified values ๐ŸŒŸ. If no wildcard is present, values that aren't explicitly mentioned in the field are considered unacceptable ๐Ÿšซ. Within Vary, the wildcard value means the variance is unlimited ๐Ÿงš.

Note: In practice, using wildcards in content negotiation has limited practical value, because it's seldom useful to say, for example, "I prefer image/* more or less than (some other specific value)". By sending Accept: */*;q=0, clients can explicitly request a 406 (Not Acceptable) response if a more preferred format isn't available. But they still need to be able to handle a different response, since the server is allowed to ignore their preference ๐Ÿ˜ญ๐Ÿ’….

12.5. Content Negotiation Fields ๐Ÿ‘‘

12.5.1. Accept ๐Ÿ’Œ

okay so the Accept header field is how user agents tell the server what kinds of response media types they're into ๐Ÿ’– like, if you only want a tiny specific set of stuff, that's how you say it. it's giving "I'm here for an in-line image and NOTHING else" ๐Ÿ–ผ๏ธ

when a server sends Accept in a response, it's basically dropping a hint about which content types are preferred in the content of a later request to that same resource ๐Ÿงš

Accept = #( media-range [ weight ] )

media-range    = ( "*/*"
                   / ( type "/" "*" )
                   / ( type "/" subtype )
                 ) parameters

the asterisk * is how you group media types into ranges ๐ŸŒˆ */* means ALL media types and type/* means all the subtypes of that one type. a media-range can also carry media type parameters that apply to that range ๐ŸŽ€

each media-range can be followed by optional media type parameters (like charset), and then an optional q parameter for the relative weight (Section 12.4.2) โญ

earlier specs let extra extension parameters show up after the weight, but the accept extension grammar (accept-params, accept-ext) got removed ๐Ÿ’€ it was super complicated, nobody was actually using it, and it's way easier to ship stuff through brand new header fields instead. if you're sending weights, senders SHOULD put q last (after all the media-range parameters) ๐Ÿซถ and recipients SHOULD treat any parameter named q as the weight, no matter where it sits in the order โœจ

๐Ÿšจ Note: Using the q parameter name for content negotiation would clash with any media type parameter that has the same name. So the media type registry doesn't allow parameters named q ๐Ÿ’…

here's a cute one:

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

this basically means "I prefer audio/basic, but send me any audio type if it's the best available after an 80% markdown in quality" ๐ŸŽง

a more extra example:

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

so the vibe here is: text/html and text/x-c are tied for first place ๐Ÿ‘‘ but if neither exists, send the text/x-dvi version, and if THAT doesn't exist either, fall back to text/plain ๐Ÿ’œ

media ranges can get overridden by more specific media ranges or by specific media types ๐Ÿฆ‹ if more than one range applies to the same type, the most specific one wins. for example:

Accept: text/*, text/plain, text/plain;format=flowed, */*

has this precedence, highest first:

  1. text/plain;format=flowed
  2. text/plain
  3. text/*
  4. */*

the quality factor for a type comes from whichever matching media range has the highest precedence ๐ŸŒธ check this out:

Accept: text/*;q=0.3, text/plain;q=0.7, text/plain;format=flowed,
       text/plain;format=fixed;q=0.4, */*;q=0.5

which ends up giving these values:

+==========================+===============+
| Media Type               | Quality Value |
+==========================+===============+
| text/plain;format=flowed | 1             |
+--------------------------+---------------+
| text/plain               | 0.7           |
+--------------------------+---------------+
| text/html                | 0.3           |
+--------------------------+---------------+
| image/jpeg               | 0.5           |
+--------------------------+---------------+
| text/plain;format=fixed  | 0.4           |
+--------------------------+---------------+
| text/html;level=3        | 0.7           |
+--------------------------+---------------+

                 Table 5
๐Ÿšจ Note: A user agent might come with a default set of quality values for certain media ranges ๐Ÿ“ but unless the user agent is a closed system that can't talk to other rendering agents, that default set ought to be configurable by the user.

12.5.2. Accept-Charset ๐Ÿ”ค

the Accept-Charset header field can be sent by a user agent to show its charset preferences for textual response content ๐ŸŒท it lets user agents that understand fancier or special-purpose charsets say so to an origin server that can represent info in those charsets. main character energy ๐Ÿ‘‘

Accept-Charset = #( ( token / "*" ) [ weight ] )

charset names are defined in Section 8.3.2 ๐Ÿ’… a user agent MAY attach a quality value to each charset to show how much the user likes it, as defined in Section 12.4.2 โœจ here's a little example:

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

the special value *, if it shows up in the Accept-Charset field, matches every charset that isn't mentioned elsewhere in the field ๐Ÿฆ‹

๐Ÿšจ Note: Accept-Charset is deprecated, bestie ๐Ÿ’€ UTF-8 is basically everywhere now, and sending a long list of preferred charsets just wastes bandwidth, adds latency, and makes passive fingerprinting WAY too easy (Section 17.13). most general-purpose user agents don't send Accept-Charset unless they've been specifically configured to ๐Ÿ™ˆ

12.5.3. Accept-Encoding ๐Ÿ—œ๏ธ

the Accept-Encoding header field can be used to show preferences about using content codings (Section 8.4.1) ๐ŸŽ€

when a user agent sends it in a request, Accept-Encoding tells the server which content codings are acceptable in a response ๐Ÿ’–

when a server sends it in a response, Accept-Encoding tells you which content codings are preferred in the content of a later request to the same resource ๐Ÿงš

an "identity" token is used as a synonym for "no encoding", so you can say when no encoding is preferred ๐Ÿซง

Accept-Encoding  = #( codings [ weight ] )
codings          = content-coding / "identity" / "*"

each codings value MAY be given a quality value (weight) for how much that encoding is loved, as defined in Section 12.4.2 ๐ŸŒˆ the asterisk * in an Accept-Encoding field matches any available content coding that isn't explicitly listed in the field โญ

examples, because you know I love a good example ๐Ÿ’…

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

so here's how a server decides if a content coding is acceptable for a given representation ๐Ÿ”

  1. if there's no Accept-Encoding header field in the request, the user agent is considered fine with ANY content coding ๐Ÿฅฐ
  2. if the representation has no content coding, it's acceptable by default, UNLESS the Accept-Encoding header field specifically excludes it by saying either identity;q=0 or *;q=0 without a more specific entry for identity ๐Ÿ™ˆ
  3. if the representation's content coding is one of the codings listed in the Accept-Encoding field value, it's acceptable UNLESS it comes with a qvalue of 0. (As defined in Section 12.4.2, a qvalue of 0 means "not acceptable" ๐Ÿ’€)

a representation could be encoded with multiple content codings ๐Ÿฐ but most codings are just different ways to do the same job (like data compression). when you're picking between multiple codings with the same purpose, the acceptable content coding with the highest non-zero qvalue is the one that gets preferred ๐Ÿ‘‘

an Accept-Encoding header field with an empty field value means the user agent doesn't want any content coding in the response ๐Ÿซ  and if a non-empty Accept-Encoding header field is in a request and NONE of the available representations for the response have a content coding that's listed as acceptable, the origin server SHOULD send a response without any content coding, unless the identity coding has been marked as unacceptable ๐ŸŽ

when the Accept-Encoding header field is in a response, it shows what content codings the resource was willing to accept in the associated request ๐Ÿชž it gets evaluated the same way as it would in a request โœจ

just a heads up: this info is specific to the associated request ๐Ÿ‘€ the set of supported encodings might be different for other resources on the same server, and it could change over time or depend on other stuff about the request (like the request method) ๐ŸŒธ

servers that fail a request because of an unsupported content coding ought to respond with a 415 (Unsupported Media Type) status and include an Accept-Encoding header field in that response ๐Ÿ’Œ that way clients can tell content coding issues apart from media type issues ๐Ÿงฉ so, to avoid mixing those up, servers that fail a request with a 415 status for reasons unrelated to content codings MUST NOT include the Accept-Encoding header field ๐Ÿšซ

the most common use of Accept-Encoding is in responses with a 415 (Unsupported Media Type) status code, when a client was optimistically using a content coding ๐Ÿ˜ญ but the header field can also tell clients which content codings are supported so they can optimize future interactions ๐Ÿš€ for example, a resource might include it in a 2xx (Successful) response when the request content was big enough to justify a compression coding but the client failed do so ๐Ÿ—œ๏ธ๐Ÿ’–

12.5.4. Accept-Language

The "Accept-Language" header field can be used by user agents to indicate the set of natural languages that are preferred in the response. Language tags are defined in Section 8.5.1.

Accept-Language = #( language-range [ weight ] ) language-range = <language-range, see [RFC4647], Section 2.1>

Each language-range can be given an associated quality value representing an estimate of the user's preference for the languages specified by that range, as defined in Section 12.4.2. For example,

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

would mean: "I prefer Danish, but will accept British English and other types of English".

Note that some recipients treat the order in which language tags are listed as an indication of descending priority, particularly for tags that are assigned equal quality values (no value is the same as q=1). However, this behavior cannot be relied upon. For consistency and to maximize interoperability, many user agents assign each language tag a unique quality value while also listing them in order of decreasing quality. Additional discussion of language priority lists can be found in Section 2.3 of [RFC4647].

For matching, Section 3 of [RFC4647] defines several matching schemes. Implementations can offer the most appropriate matching scheme for their requirements. The "Basic Filtering" scheme ([RFC4647], Section 3.3.1) is identical to the matching scheme that was previously defined for HTTP in Section 14.4 of [RFC2616].

It might be contrary to the privacy expectations of the user to send an Accept-Language header field with the complete linguistic preferences of the user in every request (Section 17.13).

Since intelligibility is highly dependent on the individual user, user agents need to allow user control over the linguistic preference (either through configuration of the user agent itself or by defaulting to a user controllable system setting). A user agent that does not provide such control to the user MUST NOT send an Accept- Language header field.

Note: User agents ought to provide guidance to users when
setting a preference, since users are rarely familiar with the
details of language matching as described above. For example,
users might assume that on selecting "en-gb", they will be
served any kind of English document if British English is not
available. A user agent might suggest, in such a case, to add
"en" to the list for better matching behavior.

12.5.5. Vary

The "Vary" header field in a response describes what parts of a request message, aside from the method and target URI, might have influenced the origin server's process for selecting the content of this response.

Vary = #( "*" / field-name )

A Vary field value is either the wildcard member "*" or a list of request field names, known as the selecting header fields, that might have had a role in selecting the representation for this response. Potential selecting header fields are not limited to fields defined by this specification.

A list containing the member "" signals that other aspects of the request might have played a role in selecting the response representation, possibly including aspects outside the message syntax (e.g., the client's network address). A recipient will not be able to determine whether this response is appropriate for a later request without forwarding the request to the origin server. A proxy MUST NOT generate "" in a Vary field value.

For example, a response that contains

Vary: accept-encoding, accept-language

indicates that the origin server might have used the request's Accept-Encoding and Accept-Language header fields (or lack thereof) as determining factors while choosing the content for this response.

A Vary field containing a list of field names has two purposes:

  1. To inform cache recipients that they MUST NOT use this response to satisfy a later request unless the later request has the same values for the listed header fields as the original request (Section 4.1 of [CACHING]) or reuse of the response has been validated by the origin server. In other words, Vary expands the cache key required to match a new request to the stored cache entry.
  2. To inform user agent recipients that this response was subject to content negotiation (Section 12) and a different representation might be sent in a subsequent request if other values are provided in the listed header fields (proactive negotiation).

An origin server SHOULD generate a Vary header field on a cacheable response when it wishes that response to be selectively reused for subsequent requests. Generally, that is the case when the response content has been tailored to better fit the preferences expressed by those selecting header fields, such as when an origin server has selected the response's language based on the request's Accept-Language header field.

Vary might be elided when an origin server considers variance in content selection to be less significant than Vary's performance impact on caching, particularly when reuse is already limited by cache response directives (Section 5.2 of [CACHING]).

There is no need to send the Authorization field name in Vary because reuse of that response for a different user is prohibited by the field definition (Section 11.6.2). Likewise, if the response content has been selected or influenced by network region, but the origin server wants the cached response to be reused even if recipients move from one region to another, then there is no need for the origin server to indicate such variance in Vary.

13. Conditional Requests โœจ

okay bestie, so a conditional request is an HTTP request with one or more header fields that basically say "only do this IF this precondition checks out first" ๐ŸŽ€ Section 13.2 is where you find out when to check preconditions and what order to check them in if there's more than one ๐Ÿ’…

Conditional GET requests are the most efficient mechanism for HTTP cache updates [CACHING] ๐Ÿฆ‹ And conditionals can also be used on state-changing methods like PUT and DELETE ๐Ÿ’€ This stops the "lost update" problem, which is when one client accidentally overwrites the work of another client that was doing stuff at the same time ๐Ÿ˜ญ like the ultimate group project disaster ๐Ÿ™ˆ

13.1. Preconditions ๐ŸŒธ

okay so preconditions are usually defined based on the state of the target resource as a whole (its current set of values) OR the state as seen in a representation you got earlier (one value from that set) ๐Ÿงš If a resource has multiple current representations, each with its own observable state, a precondition will assume that mapping each request to a selected representation (Section 3.2) stays consistent over time โœจ Regardless, if the mapping is inconsistent or the server can't select an appropriate representation, then no harm will result when the precondition evaluates to false ๐Ÿซถ

Each precondition below compares a set of validators from earlier representations of the target resource to the current validators for the selected representation (Section 8.8) ๐Ÿ’œ So basically these preconditions check whether the resource has changed since the state your client last knew about ๐Ÿ‘‘ What happens after that check depends on the method semantics and the choice of conditional, as defined in Section 13.2 ๐Ÿ”ฅ

Other preconditions, defined by other specs as extension fields, might put conditions on all recipients, on the state of the target resource in general, or on a group of resources ๐ŸŒˆ For example, the "If" header field in WebDAV can make a request conditional on lots of different aspects of multiple resources, like locks, if the recipient understands and implements that field ([WEBDAV], Section 10.4) ๐Ÿฆ‹

Extensibility of preconditions is only possible when the precondition can be safely ignored if unknown (like If-Modified-Since), when deployment can be assumed for a given use case, or when implementation is signaled by some other property of the target resource ๐Ÿ“ This encourages a focus on mutually agreed deployment of common standards ๐Ÿซถโœจ

13.1.1. If-Match โœจ

okay so the If-Match header field makes the request method conditional on the recipient origin server either having at least one current representation of the target resource, when the field value is "*", or having a current representation of the target resource that has an entity tag matching a member of the list of entity tags provided in the field value. ๐Ÿ’…

An origin server MUST use the strong comparison function when comparing entity tags for If-Match (Section 8.8.3.2), since the client intends this precondition to prevent the method from being applied if there have been any changes to the representation data. this is the strict bestie check ๐Ÿ”’

If-Match = "*" / #entity-tag

Examples:

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

If-Match is most often used with state-changing methods (e.g., POST, PUT, DELETE) to prevent accidental overwrites when multiple user agents might be acting in parallel on the same resource (i.e., to prevent the "lost update" problem). ๐Ÿซถ In general, it can be used with any method that involves the selection or modification of a representation, to abort the request if the selected representation's current entity tag is not a member within the If-Match field value. no more messy overwrites, periodt ๐Ÿ™…โ€โ™€๏ธ

When an origin server receives a request that selects a representation and that request includes an If-Match header field, the origin server MUST evaluate the If-Match condition per Section 13.2 prior to performing the method.

To evaluate a received If-Match header field:

  1. If the field value is "*", the condition is true if the origin server has a current representation for the target resource.
  2. If the field value is a list of entity tags, the condition is true if any of the listed tags match the entity tag of the selected representation.
  3. Otherwise, the condition is false.

An origin server that evaluates an If-Match condition MUST NOT perform the requested method if the condition evaluates to false. Instead, the origin server MAY indicate that the conditional request failed by responding with a 412 (Precondition Failed) status code. Alternatively, if the request is a state-changing operation that appears to have already been applied to the selected representation, the origin server MAY respond with a 2xx (Successful) status code (i.e., the change requested by the user agent has already succeeded, but the user agent might not be aware of it, perhaps because the prior response was lost or an equivalent change was made by some other user agent). ๐ŸŽ€

Allowing an origin server to send a success response when a change request appears to have already been applied is more efficient for many authoring use cases, but comes with some risk if multiple user agents are making change requests that are very similar but not cooperative. ngl this is a lot of nuance ๐Ÿฅน For example, multiple user agents writing to a common resource as a semaphore (e.g., a nonatomic increment) are likely to collide and potentially lose important state transitions. For those kinds of resources, an origin server is better off being stringent in sending 412 for every failed precondition on an unsafe method. In other cases, excluding the ETag field from a success response might encourage the user agent to perform a GET as its next request to eliminate confusion about the resource's current state. ๐Ÿงš

A client MAY send an If-Match header field in a GET request to indicate that it would prefer a 412 (Precondition Failed) response if the selected representation does not match. However, this is only useful in range requests (Section 14) for completing a previously received partial representation when there is no desire for a new representation. If-Range (Section 13.1.5) is better suited for range requests when the client prefers to receive a new representation. ๐Ÿฆ‹

A cache or intermediary MAY ignore If-Match because its interoperability features are only necessary for an origin server. ๐Ÿ’œ

Note that an If-Match header field with a list value containing "*" and other values (including other instances of "*") is syntactically invalid (therefore not allowed to be generated) and furthermore is unlikely to be interoperable. ๐Ÿšซ

13.1.2. If-None-Match ๐Ÿฆ‹

the If-None-Match header field makes the request method conditional on a recipient cache or origin server either not having any current representation of the target resource, when the field value is "*", or having a selected representation with an entity tag that does not match any of those listed in the field value. ๐ŸŒˆ

A recipient MUST use the weak comparison function when comparing entity tags for If-None-Match (Section 8.8.3.2), since weak entity tags can be used for cache validation even if there have been changes to the representation data. โœจ basically the chill comparison for this one ๐Ÿ˜Œ

If-None-Match = "*" / #entity-tag

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: *

If-None-Match is primarily used in conditional GET requests to enable efficient updates of cached information with a minimum amount of transaction overhead. When a client desires to update one or more stored responses that have entity tags, the client SHOULD generate an If-None-Match header field containing a list of those entity tags when making a GET request. This allows recipient servers to send a 304 (Not Modified) response to indicate when one of those stored responses matches the selected representation. ๐Ÿ“

If-None-Match can also be used with a value of "*" to prevent an unsafe request method (e.g., PUT) from inadvertently modifying an existing representation of the target resource when the client believes that the resource does not have a current representation (Section 9.2.1). This is a variation on the "lost update" problem that might arise if more than one client attempts to create an initial representation for the target resource. ๐Ÿ‘‘

When an origin server receives a request that selects a representation and that request includes an If-None-Match header field, the origin server MUST evaluate the If-None-Match condition per Section 13.2 prior to performing the method.

To evaluate a received If-None-Match header field:

  1. If the field value is "*", the condition is false if the origin server has a current representation for the target resource.
  2. If the field value is a list of entity tags, the condition is false if one of the listed tags matches the entity tag of the selected representation.
  3. Otherwise, the condition is true.

An origin server that evaluates an If-None-Match condition MUST NOT perform the requested method if the condition evaluates to false. Instead, the origin server MUST respond with either a) the 304 (Not Modified) status code if the request method is GET or HEAD or b) the 412 (Precondition Failed) status code for all other request methods. ๐Ÿ’–

Requirements on cache handling of a received If-None-Match header field are defined in Section 4.3.2 of [CACHING]. ๐Ÿ—‚๏ธ

Note that an If-None-Match header field with a list value containing "*" and other values (including other instances of "*") is syntactically invalid (therefore not allowed to be generated) and furthermore is unlikely to be interoperable. ๐Ÿšซ

13.1.3. If-Modified-Since ๐ŸŒธ

the If-Modified-Since header field makes a GET or HEAD request method conditional on the selected representation's modification date being more recent than the date provided in the field value. Transfer of the selected representation's data is avoided if that data has not changed. it's giving "don't resend what they already have" ๐Ÿ™Œ

If-Modified-Since = HTTP-date

An example of the field is:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

A recipient MUST ignore If-Modified-Since if the request contains an If-None-Match header field. The condition in If-None-Match is considered to be a more accurate replacement for the condition in If-Modified-Since, and the two are only combined for the sake of interoperating with older intermediaries that might not implement If-None-Match. ๐Ÿงธ

A recipient MUST ignore the If-Modified-Since header field if the received field value is not a valid HTTP-date, the field value has more than one member, or if the request method is neither GET nor HEAD.

A recipient MUST ignore the If-Modified-Since header field if the resource does not have a modification date available.

A recipient MUST interpret an If-Modified-Since field value's timestamp in terms of the origin server's clock. โฐ

If-Modified-Since is typically used for two distinct purposes: 1) to allow efficient updates of a cached representation that does not have an entity tag and 2) to limit the scope of a web traversal to resources that have recently changed. two jobs, one header, iconic ๐Ÿ‘ฏโ€โ™€๏ธ

When used for cache updates, a cache will typically use the value of the cached message's Last-Modified header field to generate the field value of If-Modified-Since. This behavior is most interoperable for cases where clocks are poorly synchronized or when the server has chosen to only honor exact timestamp matches (due to a problem with Last-Modified dates that appear to go "back in time" when the origin server's clock is corrected or a representation is restored from an archived backup). However, caches occasionally generate the field value based on other data, such as the Date header field of the cached message or the clock time at which the message was received, particularly when the cached message does not contain a Last-Modified header field. ๐Ÿ•ฐ๏ธ

When used for limiting the scope of retrieval to a recent time window, a user agent will generate an If-Modified-Since field value based on either its own clock or a Date header field received from the server in a prior response. Origin servers that choose an exact timestamp match based on the selected representation's Last-Modified header field will not be able to help the user agent limit its data transfers to only those changed during the specified window. ๐ŸชŸ

When an origin server receives a request that selects a representation and that request includes an If-Modified-Since header field without an If-None-Match header field, the origin server SHOULD evaluate the If-Modified-Since condition per Section 13.2 prior to performing the method.

To evaluate a received If-Modified-Since header field:

  1. If the selected representation's last modification date is earlier or equal to the date provided in the field value, the condition is false.
  2. Otherwise, the condition is true.

An origin server that evaluates an If-Modified-Since condition SHOULD NOT perform the requested method if the condition evaluates to false. Instead, the origin server SHOULD generate a 304 (Not Modified) response, including only those metadata that are useful for identifying or updating a previously cached response. ๐Ÿญ

Requirements on cache handling of a received If-Modified-Since header field are defined in Section 4.3.2 of [CACHING]. ๐Ÿ’…

13.1.4. If-Unmodified-Since โœจ

okay so the If-Unmodified-Since header field makes the request method conditional on the selected representation's last modification date being earlier than or equal to the date in the field value ๐Ÿ•ฐ๏ธ it's basically If-Match's cousin ๐Ÿ’… and it shows up when the user agent doesn't have an entity tag for the representation ๐Ÿฆ‹

If-Unmodified-Since = HTTP-date

an example looks like this ๐ŸŒธ

If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT

ok so, a recipient MUST ignore If-Unmodified-Since if the request has an If-Match header field ๐Ÿ™ˆ If-Match is the more accurate version of this check, so the two only get combined so they can play nicely with older intermediaries that might not understand If-Match yet ๐Ÿซถ

a recipient MUST ignore the If-Unmodified-Since header field if the field value isn't a valid HTTP-date, and that includes when it looks like a list of dates ๐Ÿ’€

a recipient MUST ignore the If-Unmodified-Since header field if the resource doesn't have a modification date available ๐ŸŒˆ

a recipient MUST interpret the timestamp in an If-Unmodified-Since field value using the origin server's clock โฐ

If-Unmodified-Since is mostly used with state-changing methods (like POST, PUT, and DELETE) ๐Ÿ”ฅ it stops accidental overwrites when several user agents might be working on the same resource at once, especially when the resource doesn't give its representations entity tags. This is how you dodge the "lost update" problem ๐Ÿ˜ญ In general, it can go with any method that selects or modifies a representation, so the request gets aborted if the selected representation's last modification date has changed since the date in the If-Unmodified-Since field value ๐Ÿ’œ

when an origin server gets a request that selects a representation and that request has an If-Unmodified-Since header field but no If-Match header field, the origin server MUST evaluate the If-Unmodified-Since condition per Section 13.2 before performing the method ๐ŸŽ€

to evaluate a received If-Unmodified-Since header field:

  1. If the selected representation's last modification date is earlier than or equal to the date provided in the field value, the condition is true.
  2. Otherwise, the condition is false.

an origin server that evaluates an If-Unmodified-Since condition MUST NOT perform the requested method if the condition evaluates to false ๐Ÿ™…โ€โ™€๏ธ instead, the origin server MAY indicate that the conditional request failed by responding with a 412 (Precondition Failed) status code. Or, if the request is a state-changing operation that already seems to have been applied to the selected representation, the origin server MAY respond with a 2xx (Successful) status code. That means the change the user agent asked for already succeeded, even if the user agent doesn't know it ๐Ÿฅน maybe the earlier response got lost, or some other user agent made an equivalent change

letting an origin server send a success response when a change request already seems applied is way more efficient for lots of authoring use cases ๐Ÿ“ but it's risky if multiple user agents are sending change requests that are super similar but not cooperative ๐Ÿ‘€ in those cases the origin server is better off being strict and sending 412 for every failed precondition on an unsafe method ๐Ÿซก

a client MAY send an If-Unmodified-Since header field in a GET request to say it would prefer a 412 (Precondition Failed) response if the selected representation has been modified ๐Ÿงš but honestly this is only useful in range requests (Section 14) for finishing a partial representation the client already received, when it doesn't want a new representation. If-Range (Section 13.1.5) is the better pick for range requests when the client wants a new representation ๐Ÿ’–

a cache or intermediary MAY ignore If-Unmodified-Since, because its interoperability features are only needed for an origin server ๐Ÿงธ


13.1.5. If-Range

the If-Range header field is a special conditional request mechanism ๐Ÿฆ‹ it's similar to If-Match and If-Unmodified-Since, but it tells the recipient to ignore the Range header field if the validator doesn't match. That way the new selected representation gets sent instead of a 412 (Precondition Failed) response โœจ

here's the situation ๐Ÿฅบ if a client has a partial copy of a representation and wants an up-to-date copy of the whole thing, it could use the Range header field with a conditional GET (using either or both of If-Unmodified-Since and If-Match). But if the precondition fails because the representation changed, the client would then have to make a second request to get the entire current representation ๐Ÿ˜ฉ

the If-Range header field lets the client "short-circuit" that second request ๐Ÿƒโ€โ™€๏ธ informally, it means: if the representation hasn't changed, send me the part(s) I asked for in Range; otherwise, send me the entire representation ๐Ÿ’…

If-Range = entity-tag / HTTP-date

you can tell a valid entity-tag from a valid HTTP-date by checking whether the first three characters include a DQUOTE ๐Ÿ”

a client MUST NOT generate an If-Range header field in a request that doesn't contain a Range header field ๐Ÿšซ a server MUST ignore an If-Range header field received in a request that doesn't contain a Range header field. An origin server MUST ignore an If-Range header field received in a request for a target resource that doesn't support Range requests ๐Ÿ™ƒ

a client MUST NOT generate an If-Range header field containing an entity tag that is marked as weak ๐Ÿ’” a client MUST NOT generate an If-Range header field containing an HTTP-date unless the client has no entity tag for the corresponding representation AND the date is a strong validator in the sense defined by Section 8.8.2.2 โš ๏ธ

a server that receives an If-Range header field on a Range request MUST evaluate the condition per Section 13.2 before performing the method ๐Ÿซถ

to evaluate a received If-Range header field containing an HTTP-date:

  1. If the HTTP-date validator provided is not a strong validator in the sense defined by Section 8.8.2.2, the condition is false.
  2. If the HTTP-date validator provided exactly matches the Last-Modified field value for the selected representation, the condition is true.
  3. Otherwise, the condition is false.

to evaluate a received If-Range header field containing an entity-tag:

  1. If the entity-tag validator provided exactly matches the ETag field value for the selected representation using the strong comparison function (Section 8.8.3.2), the condition is true.
  2. Otherwise, the condition is false.

a recipient of an If-Range header field MUST ignore the Range header field if the If-Range condition evaluates to false ๐Ÿ™ˆ otherwise, the recipient SHOULD process the Range header field as requested ๐ŸŽ€

quick reminder bestie ๐Ÿ“ฃ the If-Range comparison is an exact match, even when the validator is an HTTP-date. That makes it different from the "earlier than or equal to" comparison used for an If-Unmodified-Since conditional ๐Ÿ’…โœจ


13.2. Evaluation of Preconditions

13.2.1. When to Evaluate

except when excluded below, a recipient cache or origin server MUST evaluate received request preconditions after it has successfully done its normal request checks, and just before it would process the request content (if there is any) or perform the action tied to the request method โณ a server MUST ignore all received preconditions if its response to the same request without those conditions, before processing the request content, would have been a status code other than a 2xx (Successful) or 412 (Precondition Failed). Basically, redirects and failures that can be spotted before any big processing happens take priority over evaluating preconditions ๐Ÿ‘‘

a server that is not the origin server for the target resource and can't act as a cache for requests on that target resource MUST NOT evaluate the conditional request header fields defined by this specification ๐Ÿ™…โ€โ™€๏ธ and it MUST forward them if the request gets forwarded, since the generating client wants a server that can provide a current representation to evaluate them ๐ŸŒธ likewise, a server MUST ignore the conditional request header fields defined by this specification when they come with a request method that doesn't involve selecting or modifying a selected representation, like CONNECT, OPTIONS, or TRACE ๐Ÿงš

protocol extensions can change the conditions under which preconditions get evaluated, or what happens when they are evaluated ๐ŸŒˆ for example, the immutable cache directive (defined by [RFC8246]) tells caches to skip forwarding conditional requests when they hold a fresh response ๐Ÿฆ‹

even though conditional request header fields can be used with the HEAD method (so HEAD's semantics match GET's), there's no point in sending a conditional HEAD ๐Ÿ™ƒ a successful response is around the same size as a 304 (Not Modified) response, and it's way more useful than a 412 (Precondition Failed) response ๐Ÿ’…

13.2.2. Precedence of Preconditions โœจ

okay so what happens when a request shows up with, like, more than one conditional header field? ๐Ÿ‘€ The ORDER they get checked in suddenly matters SO much bestie ๐Ÿ˜ญ The fields defined in this doc are consistently implemented in one single logical order (it's giving organization ๐Ÿ’…). The reasoning is that "lost update" preconditions have stricter requirements than cache validation, a validated cache is more efficient than a partial response, and entity tags are presumed to be more accurate than date validators. So the lost-update stuff goes first, then the cache checks, then the partial responses ๐Ÿซถ

A recipient cache or origin server MUST evaluate the request preconditions defined by this specification in the following order:

  1. When recipient is the origin server and If-Match is present, evaluate the If-Match precondition:
    • if true, continue to step 3
    • if false, respond 412 (Precondition Failed) unless it can be determined that the state-changing request has already succeeded (see Section 13.1.1)
  2. When recipient is the origin server, If-Match is not present, and If-Unmodified-Since is present, evaluate the If-Unmodified-Since precondition:
    • if true, continue to step 3
    • if false, respond 412 (Precondition Failed) unless it can be determined that the state-changing request has already succeeded (see Section 13.1.4)
  3. When If-None-Match is present, evaluate the If-None-Match precondition:
    • if true, continue to step 5
    • if false for GET/HEAD, respond 304 (Not Modified)
    • if false for other methods, respond 412 (Precondition Failed)
  4. When the method is GET or HEAD, If-None-Match is not present, and If-Modified-Since is present, evaluate the If-Modified-Since precondition:
    • if true, continue to step 5
    • if false, respond 304 (Not Modified)
  5. When the method is GET and both Range and If-Range are present, evaluate the If-Range precondition:
    • if true and the Range is applicable to the selected representation, respond 206 (Partial Content)
    • otherwise, ignore the Range header field and respond 200 (OK)
  6. Otherwise,
    • perform the requested method and respond according to its success or failure.

Any extension to HTTP that defines additional conditional request header fields ought to define the order for evaluating such fields in relation to those defined in this document and other conditionals that might be found in practice. ๐Ÿงš Future extensions, take note! ๐Ÿ“


14. Range Requests โœจ

Clients often encounter interrupted data transfers as a result of canceled requests or dropped connections ๐Ÿ˜ฉ When a client has stored a partial representation, it is desirable to request the remainder of that representation in a subsequent request rather than transfer the entire representation. Likewise, devices with limited local storage might benefit from being able to request only a subset of a larger representation, such as a single page of a very large document, or the dimensions of an embedded image ๐Ÿ–ผ๏ธ

Range requests are an OPTIONAL feature of HTTP, designed so that recipients not implementing this feature (or not supporting it for the target resource) can respond as if it is a normal GET request without impacting interoperability ๐Ÿฆ‹ Partial responses are indicated by a distinct status code so they are not mistaken for full responses by caches that might not implement the feature. The whole design is so considerate, I'm obsessed ๐Ÿฅน

14.1. Range Units

Representation data can be partitioned into subranges when there are addressable structural units inherent to that data's content coding or media type. For example, octet (a.k.a. byte) boundaries are a structural unit common to all representation data, allowing partitions of the data to be identified as a range of bytes at some offset from the start or end of that data ๐Ÿ“

This general notion of a "range unit" is used in the Accept-Ranges (Section 14.3) response header field to advertise support for range requests, the Range (Section 14.2) request header field to delineate the parts of a representation that are requested, and the Content-Range (Section 14.4) header field to describe which part of a representation is being transferred ๐Ÿ“ฆ

range-unit       = token

All range unit names are case-insensitive and ought to be registered within the "HTTP Range Unit Registry", as defined in Section 16.5.1. ๐Ÿ—‚๏ธ

Range units are intended to be extensible, as described in Section 16.5. โœจ

14.1.1. Range Specifiers

Ranges are expressed in terms of a range unit paired with a set of range specifiers. The range unit name determines what kinds of range-spec are applicable to its own specifiers. Hence, the following grammar is generic: each range unit is expected to specify requirements on when int-range, suffix-range, and other-range are allowed. It's giving flexible ๐Ÿ’–

A range request can specify a single range or a set of ranges within a single representation.

ranges-specifier = range-unit "=" range-set
range-set        = 1#range-spec
range-spec       = int-range
                 / suffix-range
                 / other-range

An int-range is a range expressed as two non-negative integers or as one non-negative integer through to the end of the representation data. The range unit specifies what the integers mean (e.g., they might indicate unit offsets from the beginning, inclusive numbered parts, etc.) ๐Ÿ”ข

int-range     = first-pos "-" [ last-pos ]
first-pos     = 1*DIGIT
last-pos      = 1*DIGIT

An int-range is invalid if the last-pos value is present and less than the first-pos. ๐Ÿšซ

A suffix-range is a range expressed as a suffix of the representation data with the provided non-negative integer maximum length (in range units). In other words, the last N units of the representation data. ๐ŸŽ€

suffix-range  = "-" suffix-length
suffix-length = 1*DIGIT

To provide for extensibility, the other-range rule is a mostly unconstrained grammar that allows application-specific or future range units to define additional range specifiers ๐ŸŒˆ

other-range   = 1*( %x21-2B / %x2D-7E )
              ; 1*(VCHAR excluding comma)

A ranges-specifier is invalid if it contains any range-spec that is invalid or undefined for the indicated range-unit. ๐Ÿ™…

A valid ranges-specifier is "satisfiable" if it contains at least one range-spec that is satisfiable, as defined by the indicated range-unit. Otherwise, the ranges-specifier is "unsatisfiable". ๐Ÿ’€ Big "rip" energy for the unsatisfiable ones.

14.1.2. Byte Ranges

The "bytes" range unit is used to express subranges of a representation data's octet sequence. Each byte range is expressed as an integer range at some offset, relative to either the beginning (int-range) or end (suffix-range) of the representation data. Byte ranges do not use the other-range specifier. ๐Ÿง

The first-pos value in a bytes int-range gives the offset of the first byte in a range. The last-pos value gives the offset of the last byte in the range; that is, the byte positions specified are inclusive. Byte offsets start at zero. Zero-indexed era, no cap ๐Ÿค“

If the representation data has a content coding applied, each byte range is calculated with respect to the encoded sequence of bytes, not the sequence of underlying bytes that would be obtained after decoding. ๐Ÿ”

Examples of bytes range specifiers:

  • The first 500 bytes (byte offsets 0-499, inclusive):
bytes=0-499
  • The second 500 bytes (byte offsets 500-999, inclusive):
bytes=500-999

A client can limit the number of bytes requested without knowing the size of the selected representation. If the last-pos value is absent, or if the value is greater than or equal to the current length of the representation data, the byte range is interpreted as the remainder of the representation (i.e., the server replaces the value of last-pos with a value that is one less than the current length of the selected representation). ๐Ÿซถ Lowkey the best feature ever.

A client can refer to the last N bytes (N > 0) of the selected representation using a suffix-range. If the selected representation is shorter than the specified suffix-length, the entire representation is used. ๐ŸŒธ

Additional examples, assuming a representation of length 10000:

  • 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
  • The first, middle, and last 1000 bytes:
bytes= 0-999, 4500-5499, -1000
  • Other valid (but not canonical) specifications of the second 500 bytes (byte offsets 500-999, inclusive):
bytes=500-600,601-999
bytes=500-700,601-999

For a GET request, a valid bytes range-spec is satisfiable if it is either:

  • an int-range with a first-pos that is less than the current length of the selected representation or
  • a suffix-range with a non-zero suffix-length.

When a selected representation has zero length, the only satisfiable form of range-spec in a GET request is a suffix-range with a non-zero suffix-length. ๐Ÿซ 

In the byte-range syntax, first-pos, last-pos, and suffix-length are expressed as decimal number of octets. Since there is no predefined limit to the length of content, recipients MUST anticipate potentially large decimal numerals and prevent parsing errors due to integer conversion overflows. ๐Ÿ”ข๐Ÿ’ฅ Big numbers deserve big respect, bestie ๐Ÿ‘‘

14.2. Range ๐ŸŽ€

okay so the "Range" header field ๐Ÿ’– is what a GET request uses to ask for only a piece (or a few pieces) of the selected representation data (Section 8.1), instead of the whole thing. it's giving "send me just the good part" ๐Ÿฆ‹

Range = ranges-specifier

A server MAY ignore the Range header field. ๐Ÿ™ˆ still, origin servers and intermediate caches ought to support byte ranges when they can, since byte ranges make it efficient to recover from transfers that partially failed and to grab just a chunk of a huge representation. โœจ

A server MUST ignore a Range header field it gets with a request method it doesn't recognize, or with one that has no range handling defined. ๐Ÿ’… For this spec, GET is the only method with range handling defined, so that's the only one that gets to play. ๐Ÿ‘‘

An origin server MUST ignore a Range header field that has a range unit it doesn't understand. ๐Ÿ˜ญ A proxy MAY throw away a Range header field with a range unit it doesn't understand. ๐Ÿงš

A server that supports range requests MAY ignore or reject a Range header field in any of these situations: the ranges-specifier is invalid (Section 14.1.1), it has more than two overlapping ranges, or it's a pile of tiny ranges that aren't in ascending order. ๐Ÿ’€ these are signs of either a broken client or a deliberate denial-of-service attack (Section 17.15), so the server is allowed to say "nope" ๐Ÿšซ. A client SHOULD NOT request multiple ranges that are inherently less efficient to process and transfer than one single range covering the same data. ๐Ÿซถ

A server that supports range requests MAY ignore a Range header field when the selected representation has no content (i.e., the selected representation's data is of zero length). ๐ŸŒธ

A client asking for multiple ranges SHOULD list them in ascending order (the order they'd usually show up in a complete representation) unless there's a specific reason to ask for a later part first. ๐Ÿ“ for example, a user agent working through a big representation with an internal catalog of parts might need to grab later parts first, especially when the representation is pages stored in reverse order and the user agent wants to transfer one page at a time. that's a whole vibe ๐ŸŒˆ

The Range header field gets evaluated after the precondition header fields from Section 13.1 have been evaluated, and only if the result without the Range header field would be a 200 (OK) response. ๐Ÿ“š in other words, Range is ignored when a conditional GET would end up as a 304 (Not Modified) response. ๐Ÿ™ˆ

The If-Range header field (Section 13.1.5) can be used as a precondition for applying the Range header field. ๐Ÿ”ฅ

If all of the preconditions are true, the server supports the Range header field for the target resource, the received Range field-value contains a valid ranges-specifier with a range-unit supported for that target resource, and that ranges-specifier is satisfiable with respect to the selected representation, then the server SHOULD send a 206 (Partial Content) response. ๐ŸŽ‰ the content in that response has one or more partial representations that match the satisfiable range-spec(s) that were requested. โœจ

The above does not mean a server will send every requested range. ๐Ÿ™ƒ sometimes it can only manage (or only do efficiently) a portion of the ranges first, and then it expects the client to re-request the rest later if they're still wanted (see Section 15.3.7). ๐Ÿ’œ

If all of the preconditions are true, the server supports the Range header field for the target resource, the received Range field-value contains a valid ranges-specifier, and either the range-unit isn't supported for that target resource or the ranges-specifier is unsatisfiable with respect to the selected representation, then the server SHOULD send a 416 (Range Not Satisfiable) response. ๐Ÿ’€ not it, bestie.


14.3. Accept-Ranges ๐Ÿฆ‹

the "Accept-Ranges" field in a response tells you whether an upstream server supports range requests for the target resource. ๐Ÿ’–

Accept-Ranges     = acceptable-ranges
acceptable-ranges = 1#range-unit

for example, a server that supports byte-range requests (Section 14.1.2) can send this field:

Accept-Ranges: bytes

which says it supports byte range requests for that target resource, and basically encourages the client to keep using them for future partial requests on the same request path. ๐Ÿงš range units are defined in Section 14.1. โœจ

A client MAY generate range requests even if it hasn't received an Accept-Ranges field. ๐ŸŒˆ the info is just advice, there to improve performance and cut down on unnecessary network transfers. ๐Ÿซถ

but the other way around is a big no. ๐Ÿšซ a client MUST NOT assume that getting an Accept-Ranges field means future range requests will return partial responses. ๐Ÿ˜ญ the content might change, the server might only do range requests at certain times or under certain conditions, or a different intermediary might handle the next request. chaos, I know ๐Ÿ’€

A server that doesn't support any kind of range request for the target resource MAY send this:

Accept-Ranges: none

to tell the client not to bother trying a range request on the same request path. ๐Ÿ™…โ€โ™€๏ธ the range unit "none" is reserved for exactly this purpose. ๐Ÿ‘‘

The Accept-Ranges field MAY be sent in a trailer section, but it's preferred as a header field, because the info is especially useful for restarting large transfers that failed partway through the content (before the trailer section gets received). ๐Ÿ“


14.4. Content-Range ๐ŸŒธ

the "Content-Range" header field gets sent in a single-part 206 (Partial Content) response to say which partial range of the selected representation is enclosed as the message content. ๐Ÿ’– it's also sent in each part of a multipart 206 response to show the range inside each body part (Section 14.6), and in 416 (Range Not Satisfiable) responses to give info about the selected representation. ๐Ÿ”ฅ

Content-Range       = range-unit SP
                      ( range-resp / unsatisfied-range )

range-resp          = incl-range "/" ( complete-length / "*" )
incl-range          = first-pos "-" last-pos
unsatisfied-range   = "*/" complete-length

complete-length     = 1*DIGIT

if a 206 (Partial Content) response has a Content-Range header field with a range unit (Section 14.1) that the recipient doesn't understand, the recipient MUST NOT try to recombine it with a stored representation. ๐Ÿ™…โ€โ™€๏ธ a proxy that gets a message like that SHOULD forward it downstream. ๐Ÿงš

Content-Range might also be sent as a request modifier to ask for a partial PUT, as described in Section 14.5, based on private agreements between the client and origin server. ๐Ÿคซ a server MUST ignore a Content-Range header field received in a request with a method that doesn't define Content-Range support. ๐Ÿ’…

for byte ranges, a sender SHOULD indicate the complete length of the representation the range came from, unless that complete length is unknown or hard to figure out. ๐Ÿฆ‹ an asterisk character ("*") in place of the complete-length means the representation length was unknown when the header field got generated. ๐Ÿ™ˆ

here's an example for when the sender knows the complete length of the selected representation is 1234 bytes:

Content-Range: bytes 42-1233/1234

and this second one is for when the complete length is unknown:

Content-Range: bytes 42-1233/*

a Content-Range field value is invalid if it has a range-resp where the last-pos value is less than its first-pos value, or a complete-length value that's less than or equal to its last-pos value. ๐Ÿ’€ the recipient of an invalid Content-Range MUST NOT try to recombine the received content with a stored representation. ๐Ÿšซ

a server generating a 416 (Range Not Satisfiable) response to a byte-range request SHOULD send a Content-Range header field with an unsatisfied-range value, like in this example:

Content-Range: bytes */1234

the complete-length in a 416 response tells you the current length of the selected representation. โœจ

The Content-Range header field has no meaning for status codes that don't explicitly describe its semantics. ๐ŸŒˆ for this spec, only the 206 (Partial Content) and 416 (Range Not Satisfiable) status codes give Content-Range a meaning. ๐Ÿ‘‘

these are examples of Content-Range values where the selected representation has 1234 bytes total: ๐ŸŽ€

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

14.5. Partial PUT ๐Ÿงš

some origin servers support PUT of a partial representation when the user agent sends a Content-Range header field (Section 14.4) in the request. ๐Ÿซถ but that support is inconsistent and depends on private agreements with user agents, so it's a bit of a mixed bag. ๐Ÿ™ƒ generally, it asks that the state of the target resource be partly replaced with the enclosed content, at an offset and length given by the Content-Range value, where the offset is relative to the current selected representation. ๐Ÿ’œ

An origin server SHOULD respond with a 400 (Bad Request) status code if it receives Content-Range on a PUT for a target resource that doesn't support partial PUT requests. ๐Ÿ˜ญ

Partial PUT is not backwards compatible with the original definition of PUT. ๐Ÿ’€ it might end up writing the content as a complete replacement for the current representation, so be careful out there ๐Ÿšจ

partial resource updates are also possible by targeting a separately identified resource whose state overlaps or extends a portion of the larger resource, or by using a different method that's specifically defined for partial updates (for example, the PATCH method defined in [RFC5789]). ๐ŸŒธโœจ

14.6. Media Type multipart/byteranges ๐ŸŽ€

okay so when a 206 (Partial Content) response is carrying the content of multiple ranges, each range gets sent as its own body part inside a multipart message body ([RFC2046], Section 5.1). The media type for that is multipart/byteranges ๐Ÿ’…

The multipart/byteranges media type holds one or more body parts, and every part has its own Content-Type and Content-Range fields ๐Ÿงš. There's a boundary parameter that is required, and it's the string that separates each body part from the next ๐ŸŒธ

Implementation Notes โœจ

  1. Additional CRLFs might precede the first boundary string in the body.
  2. Although [RFC2046] lets the boundary string be quoted, some existing implementations mishandle a quoted boundary string ๐Ÿ™ˆ
  3. A bunch of clients and servers were coded against an early draft of the byteranges spec, which used a media type of multipart/x-byteranges. That one is almost compatible with this type, but not quite ๐Ÿ’€

Now, despite the name, multipart/byteranges isn't only for byte ranges! ๐Ÿฆ‹ Here's an example using an exampleunit range unit:

HTTP/1.1 206 Partial Content
Date: Tue, 14 Nov 1995 06:25:24 GMT
Last-Modified: Tue, 14 July 04:58:08 GMT
Content-Length: 2331785
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES
Content-Type: video/example
Content-Range: exampleunit 1.2-4.3/25

...the first range...
--THIS_STRING_SEPARATES
Content-Type: video/example
Content-Range: exampleunit 11.2-14.3/25

...the second range
--THIS_STRING_SEPARATES--

The registration form for the multipart/byteranges media type is below, copied as-is ๐Ÿ“‹

Type name:  multipart

Subtype name:  byteranges

Required parameters:  boundary

Optional parameters:  N/A

Encoding considerations:  only "7bit", "8bit", or "binary" are
   permitted

Security considerations:  see Section 17

Interoperability considerations:  N/A

Published specification:  RFC 9110 (see Section 14.6)

Applications that use this media type:  HTTP components supporting
   multiple ranges in a single request

Fragment identifier considerations:  N/A

Additional information:  Deprecated alias names for this type:  N/A

                         Magic number(s):  N/A

                         File extension(s):  N/A

                         Macintosh file type code(s):  N/A

Person and email address to contact for further information:  See Aut
   hors' Addresses section.

Intended usage:  COMMON

Restrictions on usage:  N/A

Author:  See Authors' Addresses section.

Change controller:  IESG

15. Status Codes โœจ

The status code of a response is a three-digit integer code ๐Ÿ”ข that describes the result of the request and the semantics of the response. That includes whether the request was successful and what content is enclosed (if any) ๐Ÿ“ฆ All valid status codes are within the range of 100 to 599, inclusive ๐Ÿ’–

The first digit of the status code defines the class of response ๐Ÿ‘‘ The last two digits don't have any categorization role at all. There are five values for the first digit:

  • 1xx (Informational): The request was received, continuing process
  • 2xx (Successful): The request was successfully received, understood, and accepted
  • 3xx (Redirection): Further action needs to 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

HTTP status codes are extensible ๐ŸŒˆ A client is not required to understand the meaning of all registered status codes, though such understanding is obviously desirable. However, a client MUST understand the class of any status code, as indicated by the first digit, and treat an unrecognized status code as being equivalent to the x00 status code of that class.

For example, if a client receives an unrecognized status code of 471, it can see from the first digit that something went wrong with its request, so it can treat the response as if it had received a 400 (Bad Request) status code. The response message will usually contain a representation that explains the status ๐Ÿซถ

Values outside the range 100..599 are invalid. Implementations often use three-digit integer values outside of that range (i.e., 600..999) for internal communication of non-HTTP status (e.g., library errors) ๐Ÿ™ˆ A client that receives a response with an invalid status code SHOULD process the response as if it had a 5xx (Server Error) status code.

A single request can have multiple associated responses: zero or more "interim" (non-final) responses with status codes in the "informational" (1xx) range, followed by exactly one "final" response with a status code in one of the other ranges โœจ It's giving relay race ๐Ÿƒโ€โ™€๏ธ

15.1. Overview of Status Codes ๐Ÿฆ‹

The status codes listed below are defined in this specification. The reason phrases listed here are only recommendations ๐Ÿ’… They can be replaced by local equivalents or left out altogether without affecting the protocol, so no stress!

Responses with status codes that are defined as heuristically cacheable (e.g., 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, and 501 in this specification) can be reused by a cache with heuristic expiration, unless otherwise indicated by the method definition or explicit cache controls [CACHING]. All other status codes are not heuristically cacheable ๐Ÿ“

Additional status codes, outside the scope of this specification, have been specified for use in HTTP. All such status codes ought to be registered within the "Hypertext Transfer Protocol (HTTP) Status Code Registry", as described in Section 16.2 ๐Ÿ“‹

15.2. Informational 1xx ๐ŸŒธ

The 1xx (Informational) class of status code indicates an interim response for communicating connection status or request progress. This happens prior to completing the requested action and sending a final response โญ Since HTTP/1.0 did not define any 1xx status codes, a server MUST NOT send a 1xx response to an HTTP/1.0 client ๐Ÿ™…โ€โ™€๏ธ

A 1xx response is terminated by the end of the header section, so it cannot contain content or trailers ๐Ÿ’€

A client MUST be able to parse one or more 1xx responses received prior to a final response, even if the client doesn't expect one. A user agent MAY ignore unexpected 1xx responses ๐Ÿงš

A proxy MUST forward 1xx responses unless the proxy itself requested the generation of the 1xx response. For example, if a proxy adds an Expect: 100-continue header field when it forwards a request, then it need not forward the corresponding 100 (Continue) response(s) ๐ŸŽ€

15.2.1. 100 Continue ๐Ÿ’–

The 100 (Continue) status code indicates that the initial part of a request has been received and has not yet been rejected by the server ๐Ÿซถ The server intends to send a final response after the request has been fully received and acted upon.

When the request contains an Expect header field that includes a 100-continue expectation, the 100 response indicates that the server wishes to receive the request content, as described in Section 10.1.1. The client ought to continue sending the request and discard the 100 response โœจ

If the request did not contain an Expect header field containing the 100-continue expectation, the client can simply discard this interim response ๐Ÿ’…

15.2.2. 101 Switching Protocols ๐Ÿฆ‹

The 101 (Switching Protocols) status code indicates that the server understands and is willing to comply with the client's request, via the Upgrade header field (Section 7.8), for a change in the application protocol being used on this connection ๐Ÿ‘‘ The server MUST generate an Upgrade header field in the response that indicates which protocol(s) will be in effect after this response.

It is assumed that the server will only agree to switch protocols when it's advantageous to do so ๐ŸŒˆ For example, switching to a newer version of HTTP might be advantageous over older versions, and switching to a real-time, synchronous protocol might be advantageous when delivering resources that use such features ๐Ÿ”ฅ

15.3. Successful 2xx ๐Ÿ’œ

The 2xx (Successful) class of status code indicates that the client's request was successfully received, understood, and accepted โœจ

15.3.1. 200 OK ๐Ÿ“

The 200 (OK) status code indicates that the request has succeeded ๐ŸŽ€ The content sent in a 200 response depends on the request method. For the methods defined by this specification, the intended meaning of the content can be summarized as:

+================+============================================+
| Request Method | Response content is a representation of:   |
+================+============================================+
| GET            | the target resource                        |
+----------------+--------------------------------------------+
| HEAD           | the target resource, like GET, but without |
|                | transferring the representation data       |
+----------------+--------------------------------------------+
| POST           | the status of, or results obtained from,   |
|                | the action                                 |
+----------------+--------------------------------------------+
| PUT, DELETE    | the status of the action                   |
+----------------+--------------------------------------------+
| OPTIONS        | communication options for the target       |
|                | resource                                   |
+----------------+--------------------------------------------+
| TRACE          | the request message as received by the     |
|                | server returning the trace                 |
+----------------+--------------------------------------------+

                             Table 6

Aside from responses to CONNECT, a 200 response is expected to contain message content, unless the message framing explicitly indicates that the content has zero length ๐Ÿ“ฆ If some aspect of the request indicates a preference for no content upon success, the origin server ought to send a 204 (No Content) response instead. For CONNECT, there is no content, because the successful result is a tunnel, which begins immediately after the 200 response header section ๐Ÿš‡

A 200 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]) ๐Ÿ’พ

In 200 responses to GET or HEAD, an origin server SHOULD send any available validator fields (Section 8.8) for the selected representation, with both a strong entity tag and a Last-Modified date being preferred ๐Ÿท๏ธ

In 200 responses to state-changing methods, any validator fields (Section 8.8) sent in the response convey the current validators for the new representation formed as a result of successfully applying the request semantics. Note that the PUT method (Section 9.3.4) has additional requirements that might preclude sending such validators ๐Ÿ™ˆ

15.3.2. 201 Created โœจ

okay bestie, so the 201 (Created) status code means the request got fulfilled AND it made one or more brand new resources ๐ŸŽ€๐ŸŒธ literally a whole new thing exists now, iconic. The main resource that got created is pointed to either by a Location header field in the response or, if there isn't one, by the target URI. no cap, that's the whole vibe check ๐Ÿ’…

The 201 response usually describes and links to whatever got created ๐Ÿงš Any validator fields (Section 8.8) sent back convey the current validators for the brand new representation the request made. ngl this is so cute ๐Ÿฆ‹ BUT the PUT method (Section 9.3.4) has extra requirements that might mean you can't send those validators at all, so not me being like "wait, the PUT rules are different" ๐Ÿ™ˆ check Section 9.3.4 before you assume.

15.3.3. 202 Accepted ๐Ÿ“

okay so the 202 (Accepted) status code says the request got accepted for processing, but the processing is NOT finished yet ๐Ÿ˜ญ The request might or might not eventually get acted upon, because it could be disallowed once processing actually happens. And there's no facility in HTTP for re-sending a status code from an asynchronous operation, so don't wait for a follow-up code to show up ๐Ÿ’€

The 202 response is intentionally noncommittal, and honestly that's the whole point ๐Ÿ’œ It lets a server accept a request for some other process (like a batch job that only runs once a day ๐ŸŒˆ) without making the user agent's connection stick around until the process is done. The representation sent with this response ought to describe the request's current status and point to (or embed) a status monitor that can give the user an estimate of when the request will be fulfilled โญ that's the glow-up ๐Ÿซถ

15.3.4. 203 Non-Authoritative Information โœจ

the 203 (Non-Authoritative Information) status code means the request was successful, but the enclosed content got modified from what the origin server's 200 (OK) response had, by a transforming proxy (Section 7.7) ๐Ÿฆ‹ This code lets the proxy tell recipients that a transformation happened, since that knowledge might change later decisions about the content. For example, future cache validation requests for the content might only apply along the same request path (through the same proxies) ๐Ÿงš

A 203 response is heuristically cacheable, i.e., unless the method definition or explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) ๐Ÿ’–

15.3.5. 204 No Content ๐ŸŒธ

the 204 (No Content) status code says the server successfully fulfilled the request and there's no additional content to send in the response content ๐Ÿ’… Metadata in the response header fields refers to the target resource and its selected representation after the requested action got applied ๐Ÿ”ฅ

For example, if a 204 status code comes back from a PUT request and the response has an ETag field, then the PUT worked, and the ETag field value is the entity tag for the new representation of that target resource ๐Ÿ’œ very aesthetic

The 204 response lets a server say the action got applied to the target resource, while implying the user agent doesn't need to leave its current "document view" (if it has one) ๐ŸŽ€ The server assumes the user agent will show some kind of success indication to its user, following its own interface, and apply any new or updated metadata to its active representation ๐Ÿ‘‘

For example, a 204 status code is commonly used with document editing interfaces for a "save" action, so the document being saved stays available for editing ๐Ÿ“ It's also frequently used with interfaces that expect automated data transfers to be prevalent, like in distributed version control systems ๐Ÿค–

A 204 response is terminated by the end of the header section; it cannot contain content or trailers. no content, no trailers, nothing ๐Ÿ™…โ€โ™€๏ธ

A 204 response is heuristically cacheable, i.e., unless the method definition or explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) ๐Ÿฆ‹

15.3.6. 205 Reset Content ๐Ÿงš

the 205 (Reset Content) status code means the server fulfilled the request and wants the user agent to reset the "document view" that caused the request to be sent back to its original state as received from the origin server ๐ŸŒˆ This is built for a super common data entry situation: the user gets content that supports data entry (a form, notepad, canvas, etc.), types or manipulates stuff in there, submits it in a request, and then the entry mechanism resets so they can easily start another input ๐Ÿ’…

Since the 205 status code implies no additional content will be provided, a server MUST NOT generate content in a 205 response. ๐Ÿšซ no content allowed, bestie, seriously ๐Ÿ˜ญ

15.3.7. 206 Partial Content ๐Ÿ’œ

the 206 (Partial Content) status code means the server is successfully fulfilling a range request for the target resource by transferring one or more parts of the selected representation โœจ so it's giving "here's your piece, not the whole thing" ๐Ÿฐ

A server that supports range requests (Section 14) will usually try to satisfy all of the requested ranges, since sending less data will likely lead to another client request for the rest ๐Ÿ” BUT a server might want to send only a subset for its own reasons, like temporary unavailability, cache efficiency, load balancing, etc. ๐Ÿซถ Since a 206 response is self-descriptive, the client can still understand a response that only partially satisfies its range request ๐Ÿฆ‹

A client MUST inspect a 206 response's Content-Type and Content-Range field(s) to figure out what parts are enclosed and whether more requests are needed ๐Ÿ” non-negotiable, bestie ๐Ÿ‘‘

A server that generates a 206 response MUST generate the following header fields, in addition to the ones required in the subsections below, if the field would have been sent in a 200 (OK) response to the same request: Date, Cache-Control, ETag, Expires, Content-Location, and Vary ๐ŸŒˆ

A Content-Length header field in a 206 response shows the number of octets in the content of this message, which is usually NOT the complete length of the selected representation ๐Ÿง Each Content-Range header field includes info about the selected representation's complete length ๐Ÿ’–

A sender that generates a 206 response to a request with an If-Range header field SHOULD NOT generate other representation header fields beyond the ones required, because the client already has a prior response containing those header fields ๐ŸŽ€ Otherwise, a sender MUST generate all of the representation header fields that would have been sent in a 200 (OK) response to the same request ๐Ÿ’…

A 206 response is heuristically cacheable, i.e., unless explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) ๐ŸŒธ

15.3.7.1. Single Part ๐Ÿฆ‹

if a single part is being transferred, the server generating the 206 response MUST generate a Content-Range header field describing what range of the selected representation is enclosed, plus content consisting of that range ๐ŸŽฏ 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

... 26012 bytes of partial image data ...

15.3.7.2. Multiple Parts ๐Ÿงš

if multiple parts are being transferred, the server generating the 206 response MUST generate "multipart/byteranges" content, as defined in Section 14.6, plus a Content-Type header field containing the "multipart/byteranges" media type and its required boundary parameter ๐ŸŒˆ To avoid confusion with single-part responses, a server MUST NOT generate a Content-Range header field in the HTTP header section of a multiple part response (this field gets sent in each part instead) ๐Ÿ™…โ€โ™€๏ธ

Within the header area of each body part in the multipart content, the server MUST generate a Content-Range header field corresponding to the range being enclosed in that body part ๐Ÿ’œ If the selected representation would have had a Content-Type header field in a 200 (OK) response, the server SHOULD generate that same Content-Type header field in the header area of each body part ๐ŸŽ€ 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-Length: 1741
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--

When multiple ranges are requested, a server MAY coalesce any of the ranges that overlap, or that are separated by a gap smaller than the overhead of sending multiple parts, regardless of the order in which the corresponding range-spec appeared in the received Range header field ๐Ÿงฉ Since the typical overhead between each part of a "multipart/byteranges" is around 80 bytes, depending on the selected representation's media type and the chosen boundary parameter length, it can be less efficient to transfer many small disjoint parts than to transfer the entire selected representation ๐Ÿ“ฆ

A server MUST NOT generate a multipart response to a request for a single range, since a client that doesn't request multiple parts might not support multipart responses ๐Ÿšซ HOWEVER, a server MAY generate a "multipart/byteranges" response with only a single body part if multiple ranges were requested and only one range was found to be satisfiable or only one range remained after coalescing ๐ŸŒŸ A client that cannot process a "multipart/byteranges" response MUST NOT generate a request that asks for multiple ranges ๐Ÿ™ˆ

A server that generates a multipart response SHOULD send the parts in the same order that the corresponding range-spec appeared in the received Range header field, excluding those ranges that were deemed unsatisfiable or that were coalesced into other ranges ๐ŸŽ€ A client that receives a multipart response MUST inspect the Content-Range header field present in each body part to determine which range is contained in that body part ๐Ÿ” a client can't rely on getting the same ranges it requested, or in the same order it requested them ๐Ÿซ 


15.3.7.3. Combining Parts ๐Ÿงฉ

okay so a response might only carry a subrange of a representation if the connection closed too early ๐Ÿ˜ญ or if the request used one or more Range specifications. after a few of these, a client might've collected several ranges of the same representation. they can only be safely combined if they all share the same strong validator (Section 8.8.1). no cap, that's the vibe check ๐Ÿ’…

A client that has received multiple partial responses to GET requests on a target resource MAY combine those responses into a larger continuous range if they share the same strong validator. โœจ

If the most recent response is an incomplete 200 (OK) response, then the header fields of that response are used for any combined response and replace those of the matching stored responses. ๐ŸŒธ

If the most recent response is a 206 (Partial Content) response and at least one of the matching stored responses is a 200 (OK), then the combined response header fields consist of the most recent 200 response's header fields. ๐Ÿ’– If all of the matching stored responses are 206 responses, then the stored response with the most recent header fields is used as the source of header fields for the combined response. the plot twist is that the client MUST use other header fields provided in the new response, aside from Content-Range, to replace all instances of the corresponding header fields in the stored response. ๐Ÿ”ฅ

The combined response content is the union of partial content ranges within the new response and all of the matching stored responses. if that union covers the entire range of the representation, then the client MUST process the combined response as if it were a complete 200 (OK) response, including a Content-Length header field that reflects the complete length. ๐Ÿ‘‘ Otherwise, the client MUST process the set of continuous ranges as one of the following: an incomplete 200 (OK) response if the combined response is a prefix of the representation, a single 206 (Partial Content) response containing multipart/byteranges content, or multiple 206 (Partial Content) responses, each with one continuous range that is indicated by a Content-Range header field. ๐Ÿงš


15.4. Redirection 3xx ๐Ÿฆ‹

The 3xx (Redirection) class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request. there are several types of redirects, bestie:

  1. Redirects that indicate this resource might be available at a different URI, as provided by the Location header field, as in the status codes 301 (Moved Permanently), 302 (Found), 307 (Temporary Redirect), and 308 (Permanent Redirect).
  2. Redirection that offers a choice among matching resources capable of representing this resource, as in the 300 (Multiple Choices) status code.
  3. Redirection to a different resource, identified by the Location header field, that can represent an indirect response to the request, as in the 303 (See Other) status code.
  4. Redirection to a previously stored result, as in the 304 (Not Modified) status code.
Note: In HTTP/1.0, the status codes 301 (Moved Permanently) and 302 (Found) were originally defined as method-preserving ([HTTP/1.0], Section 9.3) to match their implementation at CERN; 303 (See Other) was defined for a redirection that changed its method to GET. however, early user agents split on whether to redirect POST requests as POST (according to then-current specification) or as GET (the safer alternative when redirected to a different site). prevailing practice eventually converged on changing the method to GET. 307 (Temporary Redirect) and 308 (Permanent Redirect) [RFC7538] were later added to unambiguously indicate method-preserving redirects, and status codes 301 and 302 have been adjusted to allow a POST request to be redirected as GET. ๐Ÿ™ˆ

If a Location header field (Section 10.2.2) is provided, the user agent MAY automatically redirect its request to the URI referenced by the Location field value, even if the specific status code is not understood. automatic redirection needs to be done with care for methods not known to be safe, as defined in Section 9.2.1, since the user might not wish to redirect an unsafe request. โš ๏ธ

When automatically following a redirected request, the user agent SHOULD resend the original request message with the following modifications:

  1. Replace the target URI with the URI referenced by the redirection response's Location header field value after resolving it relative to the original request's target URI.
  2. Remove header fields that were automatically generated by the implementation, replacing them with updated values as appropriate to the new request. This includes:
    1. Connection-specific header fields (see Section 7.6.1),
    2. Header fields specific to the client's proxy configuration, including (but not limited to) Proxy-Authorization,
    3. Origin-specific header fields (if any), including (but not limited to) Host,
    4. Validating header fields that were added by the implementation's cache (e.g., If-None-Match, If-Modified-Since), and
    5. Resource-specific header fields, including (but not limited to) Referer, Origin, Authorization, and Cookie.
  3. Consider removing header fields that were not automatically generated by the implementation (i.e., those present in the request because they were added by the calling context) where there are security implications; this includes but is not limited to Authorization and Cookie. ๐Ÿ”
  4. Change the request method according to the redirecting status code's semantics, if applicable.
  5. If the request method has been changed to GET or HEAD, remove content-specific header fields, including (but not limited to) Content-Encoding, Content-Language, Content-Location, Content-Type, Content-Length, Digest, Last-Modified. ๐Ÿงน

A client SHOULD detect and intervene in cyclical redirections (i.e., "infinite" redirection loops). ๐Ÿ”

Note: An earlier version of this specification recommended a maximum of five redirections ([RFC2068], Section 10.3). content developers need to be aware that some clients might implement such a fixed limitation. ๐Ÿ’€

15.4.1. 300 Multiple Choices ๐ŸŒธ

The 300 (Multiple Choices) status code indicates that the target resource has more than one representation, each with its own more specific identifier. information about the alternatives is being provided so that the user (or user agent) can select a preferred representation by redirecting its request to one or more of those identifiers. in other words, the server desires that the user agent engage in reactive negotiation to select the most appropriate representation(s) for its needs (Section 12). ๐Ÿง 

If the server has a preferred choice, the server SHOULD generate a Location header field containing a preferred choice's URI reference. the user agent MAY use the Location field value for automatic redirection. ๐ŸŽฏ

For request methods other than HEAD, the server SHOULD generate content in the 300 response containing a list of representation metadata and URI reference(s) from which the user or user agent can choose the one most preferred. the user agent MAY make a selection from that list automatically if it understands the provided media type. a specific format for automatic selection is not defined by this specification because HTTP tries to remain orthogonal to the definition of its content. in practice, the representation is provided in some easily parsed format believed to be acceptable to the user agent, as determined by shared design or content negotiation, or in some commonly accepted hypertext format. ๐Ÿ“‹

A 300 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]). ๐Ÿ’พ

Note: The original proposal for the 300 status code defined the URI header field as providing a list of alternative representations, such that it would be usable for 200, 300, and 406 responses and be transferred in responses to the HEAD method. however, lack of deployment and disagreement over syntax led to both URI and Alternates (a subsequent proposal) being dropped from this specification. it is possible to communicate the list as a Link header field value [RFC8288] whose members have a relationship of "alternate", though deployment is a chicken-and-egg problem. ๐Ÿฅš

15.4.2. 301 Moved Permanently ๐Ÿฆ‹

The 301 (Moved Permanently) status code indicates that the target resource has been assigned a new permanent URI, and any future references to this resource ought to use one of the enclosed URIs. the server is suggesting that a user agent with link-editing capability can permanently replace references to the target URI with one of the new references sent by the server. however, this suggestion is usually ignored unless the user agent is actively editing references (e.g., engaged in authoring content), the connection is secured, and the origin server is a trusted authority for the content being edited. ๐Ÿค

The server SHOULD generate a Location header field in the response containing a preferred URI reference for the new permanent URI. the user agent MAY use the Location field value for automatic redirection. the server's response content usually contains a short hypertext note with a hyperlink to the new URI(s). ๐Ÿ”—

Note: For historical reasons, a user agent MAY change the request method from POST to GET for the subsequent request. If this behavior is undesired, the 308 (Permanent Redirect) status code can be used instead. ๐Ÿ™ƒ

A 301 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]). ๐Ÿ’…


15.4.3. 302 Found ๐ŸŽ€

The 302 (Found) status code indicates that the target resource resides temporarily under a different URI. since the redirection might be altered on occasion, the client ought to continue to use the target URI for future requests. ๐ŸŒˆ

The server SHOULD generate a Location header field in the response containing a URI reference for the different URI. the user agent MAY use the Location field value for automatic redirection. the server's response content usually contains a short hypertext note with a hyperlink to the different URI(s). โœจ

Note: For historical reasons, a user agent MAY change the request method from POST to GET for the subsequent request. If this behavior is undesired, the 307 (Temporary Redirect) status code can be used instead. ๐Ÿซถ

15.4.4. 303 See Other โœจ

okay so 303 (See Other) is the server going "not me, go check over there ๐Ÿ‘‰๐Ÿ’…" ๐ŸŽ€ It tells the user agent to redirect to a different resource, the one whose URI is in the Location header field, so it's kind of an indirect answer to what you originally asked for. The user agent can then make a retrieval request on that URI (a GET or HEAD request if we're talking HTTP), which might also get redirected, and show whatever comes back as the answer to the original request ๐Ÿฆ‹ Also ngl, the new URI in Location is not considered equivalent to the target URI, so don't mix them up ๐Ÿ™ˆ

This status code works with any HTTP method ๐ŸŒˆ It's mainly used so a POST can redirect the user agent to a different resource, because that gives the POST response info as a resource you can separately identify, bookmark, and cache. main character energy for POST responses ๐Ÿ’œ

A 303 response to a GET request means the origin server doesn't have a representation of the target resource that it can transfer over HTTP ๐Ÿ˜ญ BUT the Location value points to a resource that describes the target resource, so a retrieval request on that other resource might give a representation that's useful to recipients, without implying it represents the original target resource. Note that what can be represented, which representations are adequate, and what counts as a useful description are all outside the scope of HTTP ๐Ÿงš

Except for responses to a HEAD request, the representation of a 303 response ought to contain a short hypertext note with a hyperlink to the same URI reference provided in the Location header field ๐Ÿซถ


15.4.5. 304 Not Modified ๐ŸŒธ

The 304 (Not Modified) status code says a conditional GET or HEAD request came in and would have gotten a 200 (OK) response, if the condition hadn't evaluated to false ๐Ÿ™ƒ In other words, there's no need to send the representation again, because the client already has a valid one. So the server redirects the client to use its stored copy as if it were the content of a 200 (OK) response. iykyk ๐Ÿ’–

The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request:

  • Content-Location, Date, ETag, and Vary
  • Cache-Control and Expires (see [CACHING])

Since the whole goal of a 304 is to minimize info transfer when the recipient already has cached representations, a sender SHOULD NOT generate representation metadata other than the fields listed above, unless that metadata exists to guide cache updates (e.g., Last-Modified might be useful if the response does not have an ETag field) โœจ

Requirements on a cache that receives a 304 response are defined in Section 4.3.4 of [CACHING]. If the conditional request came from an outbound client, like a user agent with its own cache sending a conditional GET to a shared proxy, then the proxy SHOULD forward the 304 response to that client ๐Ÿซถ

A 304 response is terminated by the end of the header section. It cannot contain content or trailers ๐Ÿšซ


15.4.6. 305 Use Proxy ๐Ÿฅ€

The 305 (Use Proxy) status code was defined in a previous version of this specification and is now deprecated (Appendix B of [RFC7231]). bye bye ๐Ÿ‘‹

15.4.7. 306 (Unused) ๐Ÿซฅ

The 306 status code was defined in a previous version of this specification, it's no longer used, and the code is reserved.

15.4.8. 307 Temporary Redirect ๐Ÿ”

The 307 (Temporary Redirect) status code means the target resource lives temporarily under a different URI. The user agent MUST NOT change the request method if it performs an automatic redirection to that URI ๐Ÿ’… Since the redirection can change over time, the client ought to keep using the original target URI for future requests.

The server SHOULD generate a Location header field in the response containing a URI reference for the different URI. The user agent MAY use the Location field value for automatic redirection. The server's response content usually contains a short hypertext note with a hyperlink to the different URI(s) ๐ŸŽ€

15.4.9. 308 Permanent Redirect ๐Ÿฆ‹

The 308 (Permanent Redirect) status code means the target resource has been assigned a new permanent URI, and any future references to this resource ought to use one of the enclosed URIs. The server is suggesting that a user agent with link-editing capability can permanently replace references to the target URI with one of the new references sent by the server. However, this suggestion is usually ignored unless the user agent is actively editing references (e.g., engaged in authoring content), the connection is secured, and the origin server is a trusted authority for the content being edited ๐Ÿ”’

The server SHOULD generate a Location header field in the response containing a preferred URI reference for the new permanent URI. The user agent MAY use the Location field value for automatic redirection. The server's response content usually contains a short hypertext note with a hyperlink to the new URI(s).

A 308 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]).

Note: This status code is much younger (June 2014) than its sibling codes and thus might not be recognized everywhere. See Section 4 of [RFC7538] for deployment considerations.

15.5. Client Error 4xx ๐Ÿ™…

The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation 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 representation to the user ๐Ÿ’–

15.5.1. 400 Bad Request ๐Ÿ™ˆ

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

15.5.2. 401 Unauthorized ๐Ÿ”

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 11.6.1) containing at least one challenge applicable to the target resource.

If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The user agent MAY repeat the request with a new or replaced Authorization header field (Section 11.6.2). If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user agent SHOULD present the enclosed representation to the user, since it usually contains relevant diagnostic information.

15.5.3. 402 Payment Required ๐Ÿ’ธ

The 402 (Payment Required) status code is reserved for future use.

15.5.4. 403 Forbidden ๐Ÿšซ

The 403 (Forbidden) status code indicates that the server understood the request but refuses to fulfill it. A server that wishes to make public why the request has been forbidden can describe that reason in the response content (if any).

If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials. The client MAY repeat the request with new or different credentials. However, a request might be forbidden for reasons unrelated to the credentials.

An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

15.5.5. 404 Not Found ๐Ÿ•ต๏ธ

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent.

A 404 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]).

15.5.6. 405 Method Not Allowed ๐Ÿšท

The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.

A 405 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]).

15.5.7. 406 Not Acceptable ๐Ÿ™…โ€โ™€๏ธ

The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 12.1), and the server is unwilling to supply a default representation.

The server SHOULD generate content containing a list of available representation characteristics and corresponding resource identifiers from which the user or user agent can choose the one most appropriate. A user agent MAY automatically select the most appropriate choice from that list. However, this specification does not define any standard for such automatic selection, as described in Section 15.4.1.

15.5.8. 407 Proxy Authentication Required ๐Ÿ›ก๏ธ

The 407 (Proxy Authentication Required) status code is similar to 401 (Unauthorized), but it indicates that the client needs to authenticate itself in order to use a proxy for this request. The proxy MUST send a Proxy-Authenticate header field (Section 11.7.1) containing a challenge applicable to that proxy for the request. The client MAY repeat the request with a new or replaced Proxy-Authorization header field (Section 11.7.2).

15.5.9. 408 Request Timeout โฐ

The 408 (Request Timeout) status code indicates that the server did not receive a complete request message within the time that it was prepared to wait.

If the client has an outstanding request in transit, it MAY repeat that request. If the current connection is not usable (e.g., as it would be in HTTP/1.1 because request delimitation is lost), a new connection will be used.

15.5.10. 409 Conflict ๐ŸŽ€

okay bestie, 409 is the "hold up, someone else already changed this" code ๐Ÿ’… The request couldn't be completed because it clashes with the current state of the target resource. The good news is that the user might be able to fix the clash and send the request again ๐Ÿซถ So the server SHOULD generate content that includes enough info for the user to figure out where the clash came from โœจ

Conflicts usually happen with a PUT request ๐Ÿ’œ Say versioning is in use and the representation being PUT has changes that clash with an earlier request from a third party. The origin server might send a 409 to say it can't finish the request ๐Ÿ™ˆ In that case the response body would probably help merge the differences using the revision history, which is so helpful ๐Ÿ“

15.5.11. 410 Gone ๐Ÿฆ‹

410 means the target resource is no longer available on the origin server, and this is likely permanent ๐Ÿ’€ If the origin server doesn't know, or has no way of figuring out, whether the situation is permanent, it ought to use 404 (Not Found) instead ๐ŸŒธ

A 410 is basically the server saying "I did this on purpose, please stop linking to it" ๐Ÿงš It's mostly there to help with web maintenance. This is super common for limited-time promos and for pages belonging to people who aren't with the origin server's site anymore ๐Ÿ˜ญ You don't have to mark every permanently gone resource as "gone," and you don't have to keep that mark forever. That's up to the server owner ๐Ÿ’…

A 410 response is heuristically cacheable, meaning unless the method definition or explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) โœจ

15.5.12. 411 Length Required ๐ŸŒˆ

411 means the server won't accept the request without a defined Content-Length (Section 8.6) ๐Ÿ™…โ€โ™€๏ธ The client MAY send the request again if it adds a valid Content-Length header field with the length of the request content ๐Ÿ’–

15.5.13. 412 Precondition Failed ๐Ÿ’œ

412 means one or more conditions in the request header fields evaluated to false when the server tested them (Section 13) ๐Ÿ”ฅ This status lets the client set preconditions on the current resource state (its current representations and metadata) so the request method doesn't get applied if the target resource is in a state it didn't expect ๐Ÿ‘‘ Iconic self-protection ๐Ÿ˜ค

15.5.14. 413 Content Too Large ๐Ÿ“

413 means the server is refusing to process the request because the request content is bigger than what the server is willing or able to handle ๐Ÿ˜ญ The server MAY end the request if the protocol version in use allows it. If not, the server MAY close the connection ๐Ÿซฃ

If the problem is temporary, the server SHOULD generate a Retry-After header field to say it's temporary and after what time the client MAY try again โญ

15.5.15. 414 URI Too Long ๐Ÿงš

414 means the server is refusing to service the request because the target URI is longer than the server is willing to interpret ๐Ÿ“ This is a rare one ๐Ÿ’€ It mostly shows up when a client accidentally turned a POST into a GET with a ton of query info, when the client got stuck in an infinite redirect loop (like a redirected URI prefix that points to a suffix of itself), or when the server is under attack from someone trying to exploit security holes ๐Ÿšจ

A 414 response is heuristically cacheable too, unless the method definition or explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) ๐Ÿฆ‹

15.5.16. 415 Unsupported Media Type ๐ŸŽ€

415 means the origin server is refusing to handle the request because the content is in a format this method doesn't support on the target resource ๐Ÿ™…โ€โ™€๏ธ

The format problem might come from the request's Content-Type or Content-Encoding, or from the server inspecting the data directly ๐Ÿ”

If the issue is an unsupported content coding, the Accept-Encoding response header field (Section 12.5.3) ought to be used to say which content codings (if any) would have been accepted in the request ๐Ÿ’… If the issue is an unsupported media type instead, the Accept response header field (Section 12.5.1) can be used to show which media types would have been accepted ๐ŸŒธ

15.5.17. 416 Range Not Satisfiable ๐Ÿ’œ

416 means the set of ranges in the request's Range header field (Section 14.2) got rejected. Either none of the requested ranges can be satisfied, or the client asked for way too many small or overlapping ranges (a potential denial of service attack, yikes) ๐Ÿ˜ฑ

Each range unit defines what its own range sets need to be satisfiable. For example, Section 14.1.2 explains what makes a bytes range set satisfiable ๐ŸŒˆ

A server that sends a 416 to a byte-range request SHOULD generate a Content-Range header field that specifies the current length of the selected representation (Section 14.4) โœจ

For example:

HTTP/1.1 416 Range Not Satisfiable
Date: Fri, 20 Jan 2012 15:41:54 GMT
Content-Range: bytes */47022
Note: Servers are free to ignore Range, so lots of implementations just send the whole selected representation in a 200 (OK) response ๐Ÿซ  Partly because most clients can handle a 200 to finish the task (just less efficiently), and partly because clients might keep making an invalid range request until they've got a complete representation. So clients can't count on getting a 416 (Range Not Satisfiable) response, even when it's the most appropriate one ๐Ÿฅฒ

15.5.18. 417 Expectation Failed ๐Ÿฆ‹

417 means the expectation given in the request's Expect header field (Section 10.1.1) couldn't be met by at least one of the inbound servers ๐Ÿ™ƒ

15.5.19. 418 (Unused) ๐Ÿ“

[RFC2324] was an April 1 RFC that poked fun at all the ways HTTP got misused ๐Ÿคก One of those misuses was an application-specific 418 status code, which got used as a joke so often that it's basically unusable for anything else now ๐Ÿ’€

So the 418 status code is reserved in the IANA HTTP Status Code Registry ๐Ÿ”’ That means it can't be assigned to other applications right now. If future circumstances need it (like running out of 4NN status codes), it can be reassigned to another use ๐Ÿงš

15.5.20. 421 Misdirected Request ๐ŸŒˆ

421 means the request was aimed at a server that can't or won't give an authoritative response for the target URI ๐Ÿงญ An origin server (or a gateway acting on its behalf) sends 421 to reject a target URI that doesn't match an origin the server has been configured for (Section 4.3.1), or that doesn't match the connection context the request came in on (Section 7.4) ๐Ÿซฃ

A client that gets a 421 (Misdirected Request) response MAY retry the request, whether or not the request method is idempotent, over a different connection. That could be a fresh connection specific to the target resource's origin, or an alternative service [ALTSVC] ๐Ÿ’–

A proxy MUST NOT generate a 421 response ๐Ÿ™…โ€โ™€๏ธ (proxies, know your place ๐Ÿ˜ค)

15.5.21. 422 Unprocessable Content ๐Ÿ’…

422 means the server gets the content type of the request content (so a 415 (Unsupported Media Type) would be the wrong call), and the syntax of the request content is correct, but it couldn't process the instructions inside ๐Ÿง  For example, this can be sent when XML request content is well-formed (syntactically correct) but has semantically wrong XML instructions ๐ŸŒธ

15.5.22. 426 Upgrade Required โญ

426 means the server won't do the request using the current protocol, but it might be willing to do it after the client upgrades to a different protocol ๐Ÿš€ The server MUST send an Upgrade header field in a 426 response to say which protocol(s) are required (Section 7.8) ๐Ÿ’œ

Example:

HTTP/1.1 426 Upgrade Required
Upgrade: HTTP/3.0
Connection: Upgrade
Content-Length: 53
Content-Type: text/plain

This service requires use of the HTTP/3.0 protocol.

15.6. Server Error 5xx ๐Ÿ’ฅ

The 5xx (Server Error) class of status code means the server knows it messed up or can't perform the requested method ๐Ÿ˜ฌ Except when responding to a HEAD request, the server SHOULD send a representation that explains the error situation and whether it's a temporary or permanent condition ๐Ÿ“ A user agent SHOULD display any included representation to the user ๐Ÿ‘€ These status codes apply to any request method ๐ŸŒˆ

15.6.1. 500 Internal Server Error ๐Ÿ”ฅ

500 means the server ran into an unexpected condition that stopped it from fulfilling the request ๐Ÿซ 

15.6.2. 501 Not Implemented ๐ŸŒธ

501 means 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 ๐Ÿ™…โ€โ™€๏ธ

A 501 response is heuristically cacheable too, unless the method definition or explicit cache controls say otherwise (see Section 4.2.2 of [CACHING]) ๐Ÿฆ‹

15.6.3. 502 Bad Gateway ๐ŸŽ€

502 means the server, while acting as a gateway or proxy, got an invalid response from an inbound server it accessed while trying to fulfill the request ๐ŸŒ‰

15.6.4. 503 Service Unavailable ๐Ÿ’œ

503 means the server can't handle the request right now because of a temporary overload or scheduled maintenance, which will probably clear up after some delay โณ The server MAY send a Retry-After header field (Section 10.2.3) to suggest how long the client should wait before retrying the request โญ

Note: Getting a 503 doesn't mean the server has to use it when it's overloaded ๐Ÿ™ƒ Some servers might just refuse the connection instead.

15.6.5. 504 Gateway Timeout ๐Ÿงš

504 means the server, while acting as a gateway or proxy, didn't get a timely response from an upstream server it needed to reach in order to complete the request โŒ› Rip ๐Ÿ˜ญ

15.6.6. 505 HTTP Version Not Supported ๐Ÿ’…

okay bestie, this one is the "wrong version, sorry not sorry" code ๐Ÿ™ˆ The 505 (HTTP Version Not Supported) status code means the server does not support, or refuses to support, the major version of HTTP that was used in the request message. The server is basically saying it can't or won't finish the request using the same major version as the client, as described in Section 2.5, and the only thing it's sending back is this error message ๐Ÿ’€

The server SHOULD generate a representation for the 505 response that describes why that version is not supported and what other protocols are supported by that server. ๐Ÿซถ

16. Extending HTTP โœจ

HTTP has a bunch of built-in extension points so new capabilities can slide in without a whole new version. That includes methods, status codes, field names, and more extensibility points inside certain fields, like authentication schemes and cache directives (see Cache-Control extensions in Section 5.2.3 of [CACHING]). Since HTTP's semantics aren't versioned, these extension points are persistent. The protocol version in use doesn't change what they mean ๐Ÿฆ‹

Version-independent extensions are discouraged from relying on or talking to the specific version of the protocol in use. When that can't be avoided, they need careful thought about how they'll interoperate across versions ๐Ÿง 

Specific versions of HTTP can also have their own extensibility points, like transfer codings in HTTP/1.1 (Section 6.1 of [HTTP/1.1]) and HTTP/2 SETTINGS or frame types ([HTTP/2]). These extension points are specific to the version of the protocol they occur within ๐ŸŒธ

Version-specific extensions cannot override or modify the semantics of a version-independent mechanism or extension point (like a method or header field) without explicitly being allowed by that protocol element. For example, the CONNECT method (Section 9.3.6) allows this ๐Ÿ‘‘

These guidelines make sure the protocol operates correctly and predictably, even when parts of the path implement different versions of HTTP. no chaos allowed ๐ŸŒˆ

16.1. Method Extensibility ๐Ÿ“

16.1.1. Method Registry

The "Hypertext Transfer Protocol (HTTP) Method Registry", maintained by IANA at https://www.iana.org/assignments/http-methods, registers method names ๐Ÿ“‹

HTTP method registrations MUST include the following fields:

  • Method Name (see Section 9)
  • Safe ("yes" or "no", see Section 9.2.1)
  • Idempotent ("yes" or "no", see Section 9.2.2)
  • Pointer to specification text

Values to be added to this namespace require IETF Review (see [RFC8126], Section 4.8). ๐Ÿ’…

16.1.2. Considerations for New Methods

Standardized methods are generic. That means they can potentially apply to any resource, not just one particular media type, kind of resource, or application. So it's preferred that new methods get registered in a document that isn't specific to a single application or data format, since orthogonal technologies deserve orthogonal specification ๐Ÿ’œ

Message parsing (Section 6) needs to be independent of method semantics (aside from responses to HEAD). That's why definitions of new methods cannot change the parsing algorithm or prohibit the presence of content on either the request or the response message. A definition of a new method can say that only zero-length content is allowed, by requiring a Content-Length header field with a value of "0" ๐Ÿ™Œ

Likewise, new methods cannot use the special host:port and asterisk forms of request target that are allowed for CONNECT and OPTIONS, respectively (Section 7.1). A full URI in absolute form is needed for the target URI. That means either the request target gets sent in absolute form, or the target URI gets rebuilt from the request context the same way it is for other methods ๐Ÿงฉ

A new method definition needs to say whether it is safe (Section 9.2.1), idempotent (Section 9.2.2), and cacheable (Section 9.2.3). It also needs to cover what semantics go with the request content (if any), and what refinements the method makes to header field or status code semantics. If the new method is cacheable, its definition ought to describe how, and under what conditions, a cache can store a response and use it to satisfy a subsequent request. The new method ought to describe whether it can be made conditional (Section 13.1) and, if so, how a server responds when the condition is false. And if the new method might have some use for partial response semantics (Section 14.2), it ought to document that too ๐Ÿ“

๐Ÿšจ Note: Avoid defining a method name that starts with "M-", since that prefix might be misinterpreted as having the semantics assigned to it by [RFC2774].

16.2. Status Code Extensibility ๐ŸŒˆ

16.2.1. Status Code Registry

The "Hypertext Transfer Protocol (HTTP) Status Code Registry", maintained by IANA at https://www.iana.org/assignments/http-status-codes, registers status code numbers ๐Ÿ”ข

A registration MUST include the following fields:

  • Status Code (3 digits)
  • Short Description
  • Pointer to specification text

Values to be added to the HTTP status code namespace require IETF Review (see [RFC8126], Section 4.8). โœจ

16.2.2. Considerations for New Status Codes

When it's necessary to express semantics for a response that aren't defined by current status codes, a new status code can be registered. Status codes are generic too. They can potentially apply to any resource, not just one particular media type, kind of resource, or application of HTTP. So it's preferred that new status codes get registered in a document that isn't specific to a single application ๐ŸŽ€

New status codes are required to fall under one of the categories defined in Section 15. To let existing parsers process the response message, new status codes cannot disallow content, although they can mandate a zero-length content ๐Ÿงธ

Proposals for new status codes that aren't widely deployed yet ought to avoid allocating a specific number until there is clear consensus that it will be registered. Instead, early drafts can use a notation like "4NN", or "3N0" .. "3N9", to show the class of the proposed status code(s) without using up a number too early ๐Ÿฃ

The definition of a new status code ought to explain the request conditions that would cause a response containing that status code (for example, combinations of request header fields and/or method(s)). It should also cover any dependencies on response header fields (for example, which fields are required, which fields can modify the semantics, and which field semantics get further refined when used with the new status code) ๐Ÿ”

By default, a status code applies only to the request corresponding to the response it occurs within. If a status code applies to a larger scope of applicability (for example, all requests to the resource in question or all requests to a server), this must be explicitly specified. When doing so, it should be noted that not all clients can be expected to consistently apply a larger scope, because they might not understand the new status code. scope drama, but make it clear ๐Ÿ™ˆ

The definition of a new final status code ought to specify whether or not it is heuristically cacheable. Any response with a final status code can be cached if the response has explicit freshness information. A status code defined as heuristically cacheable is allowed to be cached without explicit freshness information. And the definition of a status code can place constraints upon cache behavior if the must-understand cache directive is used. See [CACHING] for more information ๐Ÿ“ฆ

Finally, the definition of a new status code ought to indicate whether the content has any implied association with an identified resource (Section 6.4.2). ๐Ÿซถ

16.3. Field Extensibility ๐Ÿงš

HTTP's most widely used extensibility point is the definition of new header and trailer fields. Main character energy ๐Ÿ’–

New fields can be defined so that, when a recipient understands them, they override or enhance the interpretation of previously defined fields, define preconditions on request evaluation, or refine the meaning of responses ๐Ÿช„

However, defining a field doesn't guarantee that it gets deployed or recognized by recipients. Most fields are designed with the expectation that a recipient can safely ignore (but forward downstream) any field it doesn't recognize. In other cases, the sender's ability to understand a given field might be shown by its prior communication, like the protocol version or the fields it sent in earlier messages, or by its use of a specific media type. Direct inspection of support might also be possible through an OPTIONS request, or by interacting with a defined well-known URI [RFC8615], if that inspection is defined along with the field being introduced ๐Ÿ”Ž

16.3.1. Field Name Registry

The "Hypertext Transfer Protocol (HTTP) Field Name Registry" defines the namespace for HTTP field names ๐Ÿ—‚๏ธ

Any party can request registration of an HTTP field. See Section 16.3.2 for considerations to take into account when creating a new HTTP field ๐Ÿ’Œ

The "Hypertext Transfer Protocol (HTTP) Field Name Registry" is located at https://www.iana.org/assignments/http-fields/. You can request registration by following the instructions there, or by sending an email to the "ietf-http-wg@w3.org" mailing list ๐Ÿ“ง

Field names are registered on the advice of a designated expert (appointed by the IESG or their delegate). Fields with the status 'permanent' are Specification Required ([RFC8126], Section 4.6). ๐Ÿง

Registration requests consist of the following information:

  • Field name: The requested field name. It MUST conform to the field-name syntax defined in Section 5.1, and it SHOULD be restricted to just letters, digits, and hyphen ('-') characters, with the first character being a letter. ๐Ÿ”ค
  • Status: "permanent", "provisional", "deprecated", or "obsoleted". ๐Ÿšฆ
  • Specification document(s): Reference to the document that specifies the field, preferably including a URI that can be used to retrieve a copy of the document. Optional but encouraged for provisional registrations. An indication of the relevant section(s) can also be included, but it's not required. ๐Ÿ“š

And optionally:

  • Comments: Additional information, such as about reserved entries. ๐Ÿ—’๏ธ

The expert(s) can define additional fields to be collected in the registry, in consultation with the community. ๐Ÿค

Standards-defined names have a status of "permanent". Other names can also be registered as permanent if the expert(s) finds that they are in use, in consultation with the community. Other names should be registered as "provisional". ๐ŸŒท

Provisional entries can be removed by the expert(s) if, in consultation with the community, the expert(s) find that they are not in use. The expert(s) can change a provisional entry's status to permanent at any time. โณ

Note that names can be registered by third parties (including the expert(s)) if the expert(s) determines that an unregistered name is widely deployed and not likely to be registered in a timely manner otherwise. that's the tea ๐Ÿซ–

16.3.2. Considerations for New Fields โœจ

Okay bestie, HTTP header and trailer fields are the extension point for the whole protocol ๐Ÿฆ‹ People totally use them in an ad hoc way, but fields meant for wider use need careful docs so everyone can actually interoperate. Main character energy only works if everyone's on the same page ๐Ÿ’…

Authors writing specs for new fields are advised to think through and, where it makes sense, document these things:

  • Under what conditions the field can be used. For example, only in responses or requests, in all messages, or only on responses to a particular request method.
  • Whether the field's semantics get refined by context, like use with certain request methods or status codes.
  • The scope of applicability for the info it carries. By default, a field only applies to the message it's attached to ๐ŸŽ€ But some response fields are meant to apply to all representations of a resource, the resource itself, or an even broader scope. If a spec expands the scope of a response field, it'll need to think carefully about content negotiation, how long the info applies, and (in some cases) multi-tenant server deployments ๐ŸŒˆ
  • Under what conditions intermediaries are allowed to insert, delete, or modify the field's value.
  • If the field is allowed in trailers. By default it won't be (see Section 6.5.1).
  • Whether it's appropriate, or even required, to list the field name in the Connection header field. That's the case if the field is meant to be hop-by-hop (see Section 7.6.1) ๐Ÿ“
  • Whether the field brings any extra security considerations, like disclosing privacy-related data ๐Ÿ™ˆ

Request header fields have a few extra things to document if the default behavior isn't right for them:

  • Whether it's appropriate to list the field name in a Vary response header field. For example, when the request header field is used by an origin server's content selection algorithm (see Section 12.5.5) ๐Ÿงš
  • Whether the field is meant to be stored when it's received in a PUT request (see Section 9.3.4).
  • Whether the field ought to be removed when a request gets automatically redirected because of security concerns (see Section 15.4) ๐Ÿ”’

16.3.2.1. Considerations for New Field Names ๐Ÿท๏ธ

Authors writing specs for new fields are advised to pick a name that's short but still descriptive. Short names avoid pointless data over the wire, and descriptive names avoid confusion and "squatting" on names that might have broader uses later ๐Ÿ’–

So limited-use fields (like a header that's confined to one application or use case) are encouraged to use a name that includes that use, or an abbreviation of it, as a prefix. For example, if the Foo Application needs a Description field, it might use Foo-Desc. Description is way too generic, and Foo-Description is needlessly long ๐Ÿ˜ญ

The field-name syntax is defined to allow any token character, but in practice some implementations limit which characters they accept in field names. To be interoperable, new field names SHOULD constrain themselves to alphanumeric characters, "-", and ".", and SHOULD begin with a letter. For example, the underscore ("_") character can be problematic when it gets passed through non-HTTP gateway interfaces (see Section 17.10) โš ๏ธ

Field names ought not be prefixed with "X-". See [BCP178] for more info ๐ŸŒธ

Other prefixes show up in HTTP field names sometimes. For example, Accept- is used in lots of content negotiation headers, and Content- is used the way Section 6.4 explains. These prefixes are only there to help you recognize what a field is for. They don't trigger any automatic processing โœจ

16.3.2.2. Considerations for New Field Values ๐Ÿงƒ

A huge part of defining a new HTTP field is specifying its field value syntax: what senders should generate, and how recipients should figure out the semantics from what they receive ๐Ÿ”ฅ

Authors are encouraged (but not required) to use either the ABNF rules in this specification or the ones in [RFC8941] to define the syntax of new field values ๐Ÿ’œ

Authors are advised to think carefully about how combining multiple field lines will affect their field (see Section 5.3). Senders might accidentally send multiple values, and both intermediaries and HTTP libraries can combine them automatically. So this applies to all field values, even when only a single value is expected ๐Ÿ‘‘

That's why authors are advised to delimit or encode values that contain commas. For example, use the quoted-string rule of Section 5.6.4, the String data type of [RFC8941], or a field-specific encoding. This makes sure commas inside the field data don't get mixed up with the commas that separate list values ๐Ÿซถ

For example, the Content-Type field value only allows commas inside quoted strings, so it can be reliably parsed even when multiple values are present โœ… The Location field value is a counter-example that should not be emulated ๐Ÿ™…โ€โ™€๏ธ URIs can include commas, so you can't reliably tell a single value that has a comma apart from two values.

Authors of fields with a singleton value (see Section 5.5) are also advised to document how to handle messages where multiple members are present. A sensible default would be to ignore the field, but that might not always be the right choice ๐Ÿคทโ€โ™€๏ธ

16.4. Authentication Scheme Extensibility ๐Ÿ”

16.4.1. Authentication Scheme Registry ๐Ÿ“’

The "Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry" defines the namespace for the authentication schemes used in challenges and credentials. It's maintained at https://www.iana.org/assignments/http-authschemes.

Registrations MUST include the following fields:

  • Authentication Scheme Name
  • Pointer to specification text
  • Notes (optional)

Values added to this namespace require IETF Review (see [RFC8126], Section 4.8) ๐Ÿ’…

16.4.2. Considerations for New Authentication Schemes ๐Ÿชช

There are some aspects of the HTTP Authentication framework that put constraints on how new authentication schemes can work, so pay attention bestie:

  • HTTP authentication is presumed to be stateless. All of the info needed to authenticate a request MUST be provided in the request itself, instead of depending on the server remembering earlier requests ๐Ÿง  Authentication based on, or bound to, the underlying connection is outside the scope of this specification, and it's inherently flawed unless steps are taken to make sure nobody except the authenticated user can use that connection (see Section 3.3). Not me trusting a connection ๐Ÿ’€
  • The authentication parameter "realm" is reserved for defining protection spaces as described in Section 11.5. New schemes MUST NOT use it in a way that's incompatible with that definition ๐Ÿšซ
  • The token68 notation was introduced for compatibility with existing authentication schemes, and it can only be used once per challenge or credential. So new schemes ought to use the auth-param syntax instead, because otherwise future extensions would be impossible ๐Ÿ˜ค
  • The parsing of challenges and credentials is defined by this specification and can't be modified by new authentication schemes. When the auth-param syntax is used, all parameters ought to support both token and quoted-string syntax, and syntactical constraints ought to be defined on the field value after parsing (i.e., quoted-string processing). This is necessary so recipients can use a generic parser that applies to all authentication schemes ๐Ÿงฉ

Note: The fact that the value syntax for the "realm" parameter is restricted to quoted-string was a bad design choice, and it's not to be repeated for new parameters. Iconic regret moment ๐Ÿ™ƒ

  • Definitions of new schemes ought to define how unknown extension parameters get treated. In general, a "must-ignore" rule is preferable to a "must-understand" rule, because otherwise it'll be hard to introduce new parameters when legacy recipients are around ๐Ÿฆ• It's also good to describe the policy for defining new parameters, like "update the specification" or "use this registry" ๐Ÿ“
  • Authentication schemes need to document whether they're usable in origin-server authentication (i.e., using WWW-Authenticate), in proxy authentication (i.e., using Proxy-Authenticate), or both ๐ŸŒ—
  • The credentials carried in an Authorization header field are specific to the user agent. So, within the scope of the request they appear in, they have the same effect on HTTP caches as the "private" cache response directive (Section 5.2.2.7 of [CACHING]) ๐Ÿ”

Therefore, new authentication schemes that choose not to carry credentials in the Authorization header field (e.g., by using a newly defined header field) will need to explicitly disallow caching, by mandating the use of cache response directives (e.g., "private") ๐Ÿšท

  • Schemes using Authentication-Info, Proxy-Authentication-Info, or any other authentication-related response header field need to consider and document the related security considerations (see Section 17.16.4). Don't skip this one, it's serious ๐Ÿšจ

16.5. Range Unit Extensibility ๐Ÿ“

16.5.1. Range Unit Registry ๐Ÿ—‚๏ธ

The "HTTP Range Unit Registry" defines the namespace for the range unit names and refers to their corresponding specifications. It's maintained at https://www.iana.org/assignments/http-parameters.

Registration of an HTTP Range Unit MUST include the following fields:

  • Name
  • Description
  • Pointer to specification text

Values added to this namespace require IETF Review (see [RFC8126], Section 4.8) ๐ŸŽ€

16.5.2. Considerations for New Range Units ๐Ÿฐ

Other range units, like format-specific boundaries such as pages, sections, records, rows, or time, could be usable in HTTP for application-specific purposes. But they aren't commonly used in practice ๐Ÿค” Anyone implementing alternative range units ought to think about how they'd work with content codings and general-purpose intermediaries ๐Ÿฆ‹

16.6. Content Coding Extensibility ๐Ÿ—œ๏ธ

16.6.1. Content Coding Registry ๐Ÿงพ

The "HTTP Content Coding Registry" is maintained by IANA at https://www.iana.org/assignments/http-parameters/, and it registers content-coding names ๐Ÿ“š

Content coding registrations MUST include the following fields:

  • Name
  • Description
  • Pointer to specification text

Names of content codings MUST NOT overlap with names of transfer codings (per the "HTTP Transfer Coding Registry" located at https://www.iana.org/assignments/http-parameters/), unless the encoding transformation is identical. That's the case for the compression codings defined in Section 8.4.1 ๐Ÿ™Œ

Values added to this namespace require IETF Review (see Section 4.8 of [RFC8126]) and MUST conform to the purpose of content coding defined in Section 8.4.1 โœ…

16.6.2. Considerations for New Content Codings ๐ŸŒˆ

New content codings ought to be self-descriptive whenever possible, with optional parameters discoverable within the coding format itself. That's better than relying on external metadata that might get lost in transit ๐Ÿ’œ

16.7. Upgrade Token Registry โœจ

okay so bestie, this registry is the official little guest list for the Upgrade header field ๐ŸŽ€ It's the namespace for protocol-name tokens, the names people use to say "hey, switch me over to this protocol" ๐Ÿฆ‹ You can find it at https://www.iana.org/assignments/http-upgrade-tokens ๐Ÿ’…

Every registered protocol name gets contact info and, optionally, a set of specs that explains how the connection gets handled after the upgrade happens ๐ŸŒธ It's giving organized, no cap ๐Ÿ’–

Registrations are First Come First Served (see Section 4.4 of [RFC8126]), and the rules are lowkey strict ๐Ÿ˜ญ

  1. A protocol-name token, once registered, stays registered forever. Forever means forever bestie ๐Ÿ’€
  2. A protocol-name token is case-insensitive, but it gets registered with a preferred case that senders are supposed to generate ๐Ÿ“
  3. The registration MUST name a responsible party for the registration. No ghosting allowed ๐Ÿ‘‘
  4. The registration MUST name a point of contact ๐Ÿซถ
  5. The registration MAY name a set of specifications associated with that token. Those specs don't have to be publicly available, which is kinda iconic for private projects ๐Ÿ™ˆ
  6. The registration SHOULD name a set of expected "protocol-version" tokens associated with that token at the time of registration โœจ
  7. The responsible party MAY change the registration at any time. IANA keeps a record of all those changes and makes them available upon request, so the receipts are always there ๐Ÿงš
  8. The IESG MAY reassign responsibility for a protocol token. This will normally only happen when a responsible party can't be contacted, so it's the last-resort glow-up ๐ŸŒˆ

17. Security Considerations ๐Ÿ”ฅ

okay this section is giving serious protective energy, and it's meant to inform developers, information providers, and users about known security concerns relevant to HTTP semantics and using it to move information across the Internet ๐Ÿ’œ Caching considerations live in Section 7 of [CACHING], and HTTP/1.1 message syntax and parsing considerations live in Section 11 of [HTTP/1.1] ๐Ÿฆ‹

The list below is not exhaustive ๐Ÿ’… Most security concerns with HTTP semantics are about securing server-side apps (the code behind the HTTP interface), securing how user agents process content they receive over HTTP, or just using the Internet safely in general, rather than the protocol itself ๐ŸŒธ URI security considerations, which are fundamental to HTTP, are in Section 7 of [URI] โœจ Various organizations keep topical info and links to current research on Web application security (e.g., [OWASP]) ๐Ÿซถ

17.1. Establishing Authority ๐Ÿ‘‘

HTTP depends on the idea of an "authoritative response": a response that the origin server named in the target URI has determined (or directed to be made) is the most appropriate response for that request, given the state of the target resource when the response was generated ๐Ÿ”ฅ

When a registered name is used in the authority component, the "http" URI scheme (Section 4.2.1) relies on the user's local name resolution service to figure out where authoritative responses can be found ๐Ÿ˜ญ That means any attack on a user's network host table, cached names, or name resolution libraries becomes a way in for attacking authority for "http" URIs ๐Ÿ’€ Same vibe with the user's choice of Domain Name Service (DNS) server and the hierarchy of servers it gets resolution results from, since those could mess with the authenticity of address mappings ๐Ÿ™ˆ DNS Security Extensions (DNSSEC, [RFC4033]) are one way to improve authenticity, and so are the various ways of making DNS requests over more secure transfer protocols ๐Ÿงš

Also, once an IP address is obtained, establishing authority for an "http" URI is vulnerable to attacks on Internet Protocol routing ๐ŸŒˆ

The "https" scheme (Section 4.2.2) is meant to prevent (or at least reveal) lots of these authority attacks, as long as the negotiated connection is secured and the client properly checks that the communicating server's identity matches the target URI's authority component (Section 4.3.4) ๐Ÿ’– Doing that check correctly can be genuinely tricky (see [Georgiev]) ๐Ÿ˜ญ

Authority for a given origin server can be delegated through protocol extensions, for example [ALTSVC] ๐Ÿฆ‹ And the set of servers a connection is considered authoritative for can be changed with a protocol extension like [RFC8336] โœจ

Giving a response from a non-authoritative source, like a shared proxy cache, is often useful for performance and availability ๐ŸŒธ It only works, though, to the extent that the source can be trusted or the untrusted response can be safely used ๐Ÿ‘€

Unfortunately, communicating authority to users can be hard ๐Ÿ’… For example, "phishing" attacks the user's perception of authority, where similar branding in hypertext can mislead that perception, possibly with help from userinfo hiding the authority component (see Section 4.2.1) ๐Ÿ™ˆ User agents can reduce the impact of phishing by letting users easily inspect a target URI before taking action, by prominently distinguishing (or rejecting) userinfo when it's present, and by not sending stored credentials and cookies when the referring document comes from an unknown or untrusted source ๐Ÿซถ

17.2. Risks of Intermediaries ๐Ÿงš

HTTP intermediaries are inherently in a spot where on-path attacks are possible ๐Ÿ˜ญ If the systems the intermediaries run on get compromised, that can cause serious security and privacy problems ๐Ÿ’€ Intermediaries might have access to security-related information, personal info about individual users and organizations, and proprietary info belonging to users and content providers ๐Ÿ”ฅ A compromised intermediary, or one that was implemented or configured without regard to security and privacy, might get used for a wide range of potential attacks ๐ŸŒˆ

Intermediaries with a shared cache are especially vulnerable to cache poisoning attacks, as described in Section 7 of [CACHING] ๐Ÿ’œ

Implementers need to think about the privacy and security implications of their design and coding decisions, and of the configuration options they give to operators (especially the default configuration) ๐Ÿ‘‘

Intermediaries are no more trustworthy than the people and policies they operate under, and HTTP cannot solve that problem for them ๐Ÿ’…

17.3. Attacks Based on File and Path Names ๐Ÿ“

Origin servers often use their local file system to manage the mapping from target URI to resource representations ๐ŸŒธ Most file systems aren't designed to guard against malicious file or path names ๐Ÿ˜ญ So an origin server needs to avoid accessing names that have special significance to the system when mapping the target resource to files, folders, or directories ๐Ÿ™ˆ

For example, UNIX, Microsoft Windows, and other operating systems use ".." as a path component to mean one directory level above the current one, and they use specially named paths or file names to send data to system devices ๐Ÿ’€ Other storage systems might have similar naming conventions too โœจ Local storage systems also have an annoying tendency to prefer user-friendliness over security when handling invalid or unexpected characters, recomposing decomposed characters, and case-normalizing case-insensitive names ๐Ÿ™„

Attacks based on these special names tend to focus on either denial-of-service (e.g., telling the server to read from a COM port) or disclosure of configuration and source files that aren't meant to be served ๐Ÿ”ฅ

17.4. Attacks Based on Command, Code, or Query Injection ๐Ÿ’‰

Origin servers often use parameters within the URI to identify system services, select database entries, or choose a data source ๐Ÿฆ‹ However, data received in a request can't be trusted ๐Ÿ˜ญ An attacker could build any of the request data elements (method, target URI, header fields, or content) to contain data that might be misread as a command, code, or query when passed through a command invocation, language interpreter, or database interface ๐Ÿ’€

For example, SQL injection is a super common attack where extra query language gets inserted into some part of the target URI or header fields (e.g., Host, Referer, etc.) ๐Ÿ™ˆ If the received data is used directly within a SELECT statement, the query language might get interpreted as a database command instead of a simple string value ๐Ÿ‘‘ This type of implementation vulnerability is extremely common, even though it's really easy to prevent ๐Ÿ˜ค

In general, resource implementations ought to avoid using request data in contexts that get processed or interpreted as instructions ๐Ÿซถ Parameters ought to be compared to fixed strings and acted upon based on that comparison, rather than passed through an interface that isn't prepared for untrusted data ๐ŸŒˆ Received data that isn't based on fixed parameters ought to be carefully filtered or encoded so it doesn't get misinterpreted ๐Ÿ’–

Similar considerations apply to request data when it's stored and processed later, like in log files, monitoring tools, or a data format that allows embedded scripts ๐Ÿงš

17.5. Attacks via Protocol Element Length ๐Ÿ“

Because HTTP uses mostly textual, character-delimited fields, parsers are often vulnerable to attacks that send very long (or very slow) streams of data ๐Ÿ˜ญ This is especially true when an implementation expects a protocol element with no predefined length (Section 2.3) ๐Ÿ’€

To promote interoperability, specific recommendations are made for minimum size limits on fields (Section 5.4) โœจ These are minimum recommendations, chosen to be supportable even by implementations with limited resources, and it's expected that most implementations will choose substantially higher limits ๐Ÿ’…

A server can reject a message that has a target URI that's too long (Section 15.5.15) or request content that's too large (Section 15.5.14) ๐ŸŒธ Additional status codes related to capacity limits have been defined by extensions to HTTP [RFC6585] ๐Ÿฆ‹

Recipients ought to carefully limit how far they process other protocol elements, including (but not limited to) request methods, response status phrases, field names, numeric values, and chunk lengths ๐Ÿ”ฅ Failing to limit that processing can lead to arbitrary code execution through buffer or arithmetic overflows, and increased vulnerability to denial-of-service attacks ๐Ÿ˜ฑ

17.6. Attacks Using Shared-Dictionary Compression ๐Ÿ—œ๏ธ

Some attacks on encrypted protocols use the size differences created by dynamic compression to reveal confidential information, for example [BREACH] ๐Ÿ’œ These attacks rely on creating redundancy between attacker-controlled content and the confidential information, so a dynamic compression algorithm using the same dictionary for both will compress more efficiently when the attacker-controlled content matches parts of the confidential content ๐Ÿ™ˆ

HTTP messages can be compressed in a number of ways, including TLS compression, content codings, transfer codings, and other extension or version-specific mechanisms ๐ŸŒˆ

The most effective mitigation for this risk is to disable compression on sensitive data, or to strictly separate sensitive data from attacker-controlled data so they can't share the same compression dictionary ๐Ÿซถ With careful design, a compression scheme can be built so it isn't considered exploitable in limited use cases, such as HPACK ([HPACK]) โœจ

17.7. Disclosure of Personal Information ๐ŸŽ€

Okay so clients are literally privy to SO much personal info ๐Ÿ˜ญ There's the stuff the user types in to interact with resources (their name, location, mail address, passwords, encryption keys, etc.), and there's info about their browsing activity over time (history, bookmarks, etc.) ๐Ÿ“ Implementations need to prevent unintentional disclosure of personal information, bestie. This one is a big deal ๐Ÿ’…

17.8. Privacy of Server Log Information ๐Ÿฆ‹

A server is in the position to save personal data about a user's requests over time, which might identify their reading patterns or subjects of interest ๐Ÿ‘€ Lowkey scary, right? Log info gathered at an intermediary is especially spicy because it often contains a history of user agent interaction across a multitude of sites, and that can be traced back to individual users ๐Ÿ™ˆ

HTTP log information is confidential in nature, and its handling is often constrained by laws and regulations โš–๏ธ Log information needs to be securely stored, and appropriate guidelines need to be followed for its analysis. Anonymizing personal info within individual entries helps, but it is generally not sufficient to stop real log traces from being re-identified based on correlation with other access characteristics. As such, access traces keyed to a specific client are unsafe to publish, even if the key is pseudonymous. Not safe, no cap ๐Ÿ™…โ€โ™€๏ธ

To minimize the risk of theft or accidental publication, log information ought to be purged of personally identifiable information, including user identifiers, IP addresses, and user-provided query parameters, as soon as that information is no longer necessary to support operational needs for security, auditing, or fraud control ๐Ÿงนโœจ

17.9. Disclosure of Sensitive Information in URIs ๐ŸŒธ

URIs are intended to be shared, not secured, even when they identify secure resources. Main character energy for URIs is "I'm public, deal with it" ๐Ÿ’โ€โ™€๏ธ They get shown on displays, added to templates when a page is printed, and stored in a variety of unprotected bookmark lists. Many servers, proxies, and user agents log or display the target URI in places where third parties might see it. It is therefore unwise to put anything sensitive, personally identifiable, or risky to disclose inside a URI ๐Ÿšซ

When an application uses client-side mechanisms to build a target URI out of user-provided info, such as the query fields of a form using GET, potentially sensitive data might end up in there that would not be appropriate to disclose within a URI ๐Ÿ˜ฌ POST is often preferred in those cases because it usually doesn't construct a URI. Instead, a POST of a form sends the potentially sensitive data in the request content ๐Ÿ“ฆ However, this hinders caching, and it uses an unsafe method for what would otherwise be a safe request. Alternative workarounds include transforming the user-provided data before constructing the URI, or filtering the data so only common, non-sensitive values get included ๐Ÿง  Likewise, redirecting the result of a query to a different (server-generated) URI can remove potentially sensitive data from later links and provide a cacheable response for later reuse โœจ

Since the Referer header field tells a target site about the context that resulted in a request, it has the potential to reveal info about the user's immediate browsing history, plus any personal info that might be found in the referring resource's URI ๐Ÿ‘€ Limitations on the Referer header field are described in Section 10.1.3 to address some of its security considerations ๐Ÿ›ก๏ธ

17.10. Application Handling of Field Names ๐Ÿงš

Servers often use non-HTTP gateway interfaces and frameworks to process a received request and produce content for the response. For historical reasons, these interfaces often pass received field names as external variable names, using a name mapping suitable for environment variables ๐Ÿ•ฐ๏ธ

For example, the Common Gateway Interface (CGI) mapping of protocol-specific meta-variables, defined by Section 4.1.18 of [RFC3875], is applied to received header fields that don't correspond to one of CGI's standard variables. The mapping consists of prepending HTTP_ to each name and changing all instances of hyphen (-) to underscore (_). This same mapping has been inherited by many other application frameworks, so moving apps from one platform to the next is easier ๐Ÿ’œ

In CGI, a received Content-Length field would be passed as the meta-variable CONTENT_LENGTH, with a string value matching the received field's value. In contrast, a received Content_Length header field would be passed as the protocol-specific meta-variable HTTP_CONTENT_LENGTH. That might cause some confusion if an application mistakenly reads the protocol-specific meta-variable instead of the default one ๐Ÿ˜ตโ€๐Ÿ’ซ (This historical practice is why Section 16.3.2.1 discourages the creation of new field names that contain an underscore ๐Ÿ™ƒ)

Unfortunately, mapping field names to different interface names can lead to security vulnerabilities if the mapping is incomplete or ambiguous ๐Ÿšจ For example, if an attacker sent a field named Transfer_Encoding, a naive interface might map that to the same variable name as the Transfer-Encoding field. That could result in a potential request smuggling vulnerability (Section 11.2 of [HTTP/1.1]). Yikes, bestie ๐Ÿ’€

To mitigate the associated risks, implementations that perform such mappings are advised to make the mapping unambiguous and complete for the full range of potential octets received as a name. That includes the octets that the HTTP grammar discourages or forbids. For example, a field with an unusual name character might result in the request being blocked, the specific field being removed, or the name being passed with a different prefix to tell it apart from other fields ๐Ÿ”

17.11. Disclosure of Fragment after Redirects ๐Ÿงฉ

Fragment identifiers used within URI references are not sent in requests, but implementers ought to be aware that they will be visible to the user agent and to any extensions or scripts running as a result of the response ๐Ÿ‘๏ธ In particular, when a redirect occurs and the original request's fragment identifier is inherited by the new reference in Location (Section 10.2.2), this might have the effect of disclosing one site's fragment to another site ๐Ÿ˜ฑ If the first site uses personal information in fragments, it ought to make sure that redirects to other sites include a (possibly empty) fragment component, which blocks that inheritance ๐Ÿซถ

17.12. Disclosure of Product Information ๐Ÿ•ต๏ธโ€โ™€๏ธ

The User-Agent (Section 10.1.5), Via (Section 7.6.3), and Server (Section 10.2.4) header fields often reveal info about the respective sender's software systems ๐Ÿ–ฅ๏ธ In theory, this can make it easier for an attacker to exploit known security holes. In practice, attackers tend to try all potential holes regardless of the apparent software versions being used ๐Ÿคทโ€โ™€๏ธ

Proxies that serve as a portal through a network firewall ought to take special precautions regarding the transfer of header information that might identify hosts behind the firewall ๐Ÿงฑ The Via header field lets intermediaries swap sensitive machine names for pseudonyms ๐ŸŽญ

17.13. Browser Fingerprinting ๐Ÿฆ‹

Browser fingerprinting is a set of techniques for identifying a specific user agent over time through its unique set of characteristics ๐Ÿ” These characteristics might include info about how it uses the underlying transport protocol, its feature capabilities, and its scripting environment. Of particular interest here is the set of unique characteristics that might be communicated via HTTP. Fingerprinting is considered a privacy concern because it enables tracking of a user agent's behavior over time ([Bujlow]) without the corresponding controls that the user might have over other forms of data collection (e.g., cookies) ๐Ÿช Many general-purpose user agents (i.e., Web browsers) have taken steps to reduce their fingerprints ๐Ÿ™Œ

A number of request header fields might reveal info to servers that is unique enough to enable fingerprinting ๐Ÿซฃ The From header field is the most obvious one, though From is expected to only be sent when the user wants to self-identify ๐Ÿ™‹โ€โ™€๏ธ Likewise, Cookie header fields are deliberately designed to enable re-identification, so fingerprinting concerns only apply to situations where cookies are disabled or restricted by the user agent's configuration ๐Ÿญ

The User-Agent header field might contain enough info to uniquely identify a specific device, usually when combined with other characteristics. That's especially true if the user agent sends excessive details about the user's system or extensions ๐Ÿ“ฑ However, the source of unique info that users expect least is proactive negotiation (Section 12.1), including the Accept, Accept-Charset, Accept-Encoding, and Accept-Language header fields. Plot twist, bestie ๐Ÿ˜ญ๐ŸŒˆ

Beyond fingerprinting, detailed use of the Accept-Language header field can reveal info the user might consider private. For example, understanding a given language set might be strongly correlated to membership in a particular ethnic group ๐ŸŒ An approach that limits this loss of privacy would be for a user agent to omit sending Accept-Language except to sites that have been explicitly permitted. That permission might come from interaction after detecting a Vary header field that indicates language negotiation might be useful ๐Ÿ’ฌ

In environments where proxies are used to enhance privacy, user agents ought to be conservative about sending proactive negotiation header fields ๐Ÿ›ก๏ธ General-purpose user agents that offer a high degree of header field configurability ought to inform users about the loss of privacy that might result if too much detail is provided ๐Ÿ“ข As an extreme privacy measure, proxies could filter the proactive negotiation header fields in relayed requests ๐Ÿงผ

17.14. Validator Retention ๐Ÿ’–

The validators defined by this specification are not intended to ensure the validity of a representation, guard against malicious changes, or detect on-path attacks. At best, they enable more efficient cache updates and optimistic concurrent writes when all participants are behaving nicely ๐Ÿฅฐ At worst, the conditions will fail and the client will receive a response that is no more harmful than an HTTP exchange without conditional requests ๐Ÿคž

An entity tag can be abused in ways that create privacy risks ๐Ÿ˜ณ For example, a site might deliberately construct a semantically invalid entity tag that is unique to the user or user agent. It could send that tag in a cacheable response with a long freshness time, then read it back in later conditional requests to re-identify that user or user agent ๐Ÿ•ต๏ธโ€โ™€๏ธ Such an identifying tag would become a persistent identifier for as long as the user agent kept the original cache entry. User agents that cache representations ought to make sure the cache is cleared or replaced whenever the user does privacy-maintaining things, like clearing stored cookies or switching to a private browsing mode ๐Ÿงน๐Ÿซง

17.15. Denial-of-Service Attacks Using Range ๐Ÿ’…

okay bestie, unconstrained multiple range requests are a whole vibe for attackers ๐Ÿ˜ญ asking for a ton of overlapping ranges of the same data costs the attacker basically nothing, but the server has to burn time, memory, and bandwidth serving it all in pieces. so servers ought to ignore, coalesce, or reject egregious range requests โœจ like anything asking for more than two overlapping ranges, or a pile of tiny ranges in one set, especially if they're out of order for no apparent reason ๐Ÿ™ˆ and multipart range requests are not designed for random access, so don't treat them like that ๐Ÿซถ

17.16. Authentication Considerations ๐Ÿ”

okay so authentication is a security consideration in its entirety ๐Ÿ’€ this list is not exhaustive (sorry not sorry). also it only covers the authentication framework in general, not every single scheme, because specific schemes should be documented in the specs that define them ๐ŸŽ€ if you want the current research and common pitfalls for using auth schemes in the wild, go check out the Web application security stuff from [OWASP] ๐ŸŒธ

17.16.1. Confidentiality of Credentials ๐Ÿคซ

the HTTP authentication framework does not define one single mechanism for keeping credentials confidential ๐Ÿ™…โ€โ™€๏ธ instead, each auth scheme decides how credentials get encoded before they're sent. that's flexible for future schemes, but it's not enough for existing schemes that give zero confidentiality on their own, or that don't really protect against replay attacks ๐Ÿ˜ญ also, if the server expects credentials specific to each individual user, the exchange itself identifies that user, even if the credential contents stay secret ๐Ÿ‘€

HTTP leans on the security of the underlying transport- or session-level connection to keep fields confidential ๐Ÿ”’ so services that rely on individual user auth MUST... no wait, they require a secured connection before exchanging credentials (Section 4.2.2) ๐Ÿ’œ

17.16.2. Credentials and Idle Clients ๐Ÿซ 

existing HTTP clients and user agents typically hold onto auth info forever ngl ๐Ÿ’€ HTTP has no way for the origin server to tell clients to toss those cached credentials, since the protocol doesn't know how the user agent gets or manages them ๐Ÿ™ƒ if a scheme wants to expire or revoke credentials, it can spell that out in its own definition ๐Ÿฆ‹

credential caching can mess with the app's security model in a few ways (but this list isn't everything, babe):

  • clients that have been idle for a long time, after which the server might want to make the client re-prompt the user for credentials ๐Ÿ˜ค
  • apps with a session-ending indicator (like a "logout" or "commit" button on a page), after which the server side "knows" the client has no further reason to keep the credentials ๐Ÿ’…

user agents that cache credentials are encouraged to provide an easy-to-reach way to discard them under user control ๐ŸŒˆ that's the main character move โœจ

17.16.3. Protection Spaces ๐Ÿฐ

auth schemes that only use the "realm" mechanism to set up a protection space will expose credentials to every resource on an origin server ๐Ÿ˜ฑ clients that already made authenticated requests to one resource can reuse those same credentials on other resources on the same origin server. which means a different resource can literally harvest auth credentials meant for others ๐Ÿ’€

this is especially concerning when an origin server hosts resources for multiple parties under the same origin (Section 11.5) ๐Ÿšฉ possible mitigations include restricting direct access to auth credentials (aka not making the content of the Authorization request header field available) ๐Ÿ”, and separating protection spaces by giving each party a different host name (or port number) ๐Ÿงš

17.16.4. Additional Response Fields ๐Ÿ“จ

adding info to responses sent over an unencrypted channel can affect security and privacy, so be careful ๐Ÿ‘€ just the presence of the Authentication-Info and Proxy-Authentication-Info header fields tells everyone HTTP authentication is in use ๐Ÿ™ˆ and extra info could leak through the contents of the authentication-scheme specific parameters, so those definitions will have to take that into account ๐Ÿซถ

18. IANA Considerations ๐Ÿ—‚๏ธ

the change controller for the following registrations is: "IETF (iesg@ietf.org) - Internet Engineering Task Force" ๐ŸŒธ

18.1. URI Scheme Registration ๐Ÿ”—

IANA has updated the "Uniform Resource Identifier (URI) Schemes" registry [BCP35] at https://www.iana.org/assignments/uri-schemes/ with the permanent schemes listed in Table 2 in Section 4.2 โœจ

18.2. Method Registration ๐Ÿงพ

IANA has updated the "Hypertext Transfer Protocol (HTTP) Method Registry" at https://www.iana.org/assignments/http-methods with the registration procedure of Section 16.1.1 and the method names summarized in the following table ๐ŸŽ€

              +=========+======+============+=========+
              | Method  | Safe | Idempotent | Section |
              +=========+======+============+=========+
              | CONNECT | no   | no         | 9.3.6   |
              +---------+------+------------+---------+
              | DELETE  | no   | yes        | 9.3.5   |
              +---------+------+------------+---------+
              | GET     | yes  | yes        | 9.3.1   |
              +---------+------+------------+---------+
              | HEAD    | yes  | yes        | 9.3.2   |
              +---------+------+------------+---------+
              | OPTIONS | yes  | yes        | 9.3.7   |
              +---------+------+------------+---------+
              | POST    | no   | no         | 9.3.3   |
              +---------+------+------------+---------+
              | PUT     | no   | yes        | 9.3.4   |
              +---------+------+------------+---------+
              | TRACE   | yes  | yes        | 9.3.8   |
              +---------+------+------------+---------+
              | *       | no   | no         | 18.2    |
              +---------+------+------------+---------+

                               Table 7

the method name "" is reserved because using "" as a method name would conflict with its usage as a wildcard in some fields (e.g., Access-Control-Request-Method) ๐ŸŒŸ

18.3. Status Code Registration

IANA has updated the "Hypertext Transfer Protocol (HTTP) Status Code Registry" at <https://www.iana.org/assignments/http-status-codes> with the registration procedure of Section 16.2.1 and the status code values summarized in the following table. ๐Ÿ’…โœจ So IANA went in and gave the status code registry a glow-up, using the registration procedure from Section 16.2.1, and everything in the table below is now officially on the list. ๐ŸŽ€

Here's the whole status code lineup, bestie. ๐ŸŒˆ Each one has its own section number so you can jump straight to the good stuff:

            +=======+===============================+=========+
            | Value | Description                   | Section |
            +=======+===============================+=========+
            | 100   | Continue                      | 15.2.1  |
            +-------+-------------------------------+---------+
            | 101   | Switching Protocols           | 15.2.2  |
            +-------+-------------------------------+---------+
            | 200   | OK                            | 15.3.1  |
            +-------+-------------------------------+---------+
            | 201   | Created                       | 15.3.2  |
            +-------+-------------------------------+---------+
            | 202   | Accepted                      | 15.3.3  |
            +-------+-------------------------------+---------+
            | 203   | Non-Authoritative Information | 15.3.4  |
            +-------+-------------------------------+---------+
            | 204   | No Content                    | 15.3.5  |
            +-------+-------------------------------+---------+
            | 205   | Reset Content                 | 15.3.6  |
            +-------+-------------------------------+---------+
            | 206   | Partial Content               | 15.3.7  |
            +-------+-------------------------------+---------+
            | 300   | Multiple Choices              | 15.4.1  |
            +-------+-------------------------------+---------+
            | 301   | Moved Permanently             | 15.4.2  |
            +-------+-------------------------------+---------+
            | 302   | Found                         | 15.4.3  |
            +-------+-------------------------------+---------+
            | 303   | See Other                     | 15.4.4  |
            +-------+-------------------------------+---------+
            | 304   | Not Modified                  | 15.4.5  |
            +-------+-------------------------------+---------+
            | 305   | Use Proxy                     | 15.4.6  |
            +-------+-------------------------------+---------+
            | 306   | (Unused)                      | 15.4.7  |
            +-------+-------------------------------+---------+
            | 307   | Temporary Redirect            | 15.4.8  |
            +-------+-------------------------------+---------+
            | 308   | Permanent Redirect            | 15.4.9  |
            +-------+-------------------------------+---------+
            | 400   | Bad Request                   | 15.5.1  |
            +-------+-------------------------------+---------+
            | 401   | Unauthorized                  | 15.5.2  |
            +-------+-------------------------------+---------+
            | 402   | Payment Required              | 15.5.3  |
            +-------+-------------------------------+---------+
            | 403   | Forbidden                     | 15.5.4  |
            +-------+-------------------------------+---------+
            | 404   | Not Found                     | 15.5.5  |
            +-------+-------------------------------+---------+
            | 405   | Method Not Allowed            | 15.5.6  |
            +-------+-------------------------------+---------+
            | 406   | Not Acceptable                | 15.5.7  |
            +-------+-------------------------------+---------+
            | 407   | Proxy Authentication Required | 15.5.8  |
            +-------+-------------------------------+---------+
            | 408   | Request Timeout               | 15.5.9  |
            +-------+-------------------------------+---------+
            | 409   | Conflict                      | 15.5.10 |
            +-------+-------------------------------+---------+
            | 410   | Gone                          | 15.5.11 |
            +-------+-------------------------------+---------+
            | 411   | Length Required               | 15.5.12 |
            +-------+-------------------------------+---------+
            | 412   | Precondition Failed           | 15.5.13 |
            +-------+-------------------------------+---------+
            | 413   | Content Too Large             | 15.5.14 |
            +-------+-------------------------------+---------+
            | 414   | URI Too Long                  | 15.5.15 |
            +-------+-------------------------------+---------+
            | 415   | Unsupported Media Type        | 15.5.16 |
            +-------+-------------------------------+---------+
            | 416   | Range Not Satisfiable         | 15.5.17 |
            +-------+-------------------------------+---------+
            | 417   | Expectation Failed            | 15.5.18 |
            +-------+-------------------------------+---------+
            | 418   | (Unused)                      | 15.5.19 |
            +-------+-------------------------------+---------+
            | 421   | Misdirected Request           | 15.5.20 |
            +-------+-------------------------------+---------+
            | 422   | Unprocessable Content         | 15.5.21 |
            +-------+-------------------------------+---------+
            | 426   | Upgrade Required              | 15.5.22 |
            +-------+-------------------------------+---------+
            | 500   | Internal Server Error         | 15.6.1  |
            +-------+-------------------------------+---------+
            | 501   | Not Implemented               | 15.6.2  |
            +-------+-------------------------------+---------+
            | 502   | Bad Gateway                   | 15.6.3  |
            +-------+-------------------------------+---------+
            | 503   | Service Unavailable           | 15.6.4  |
            +-------+-------------------------------+---------+
            | 504   | Gateway Timeout               | 15.6.5  |
            +-------+-------------------------------+---------+
            | 505   | HTTP Version Not Supported    | 15.6.6  |
            +-------+-------------------------------+---------+

                                  Table 8

18.4. Field Name Registration โœจ

okay bestie, so this section is basically the IANA paperwork for header field names ๐ŸŽ€ It says this spec updates the HTTP parts of the old registration rules from [RFC3864] ๐Ÿ’… Like, the old procedures for HTTP are retired, and HTTP field definitions get their own shiny new home ๐Ÿก

IANA made a new registry called "Hypertext Transfer Protocol (HTTP) Field Name Registry" as outlined in Section 16.3.1 ๐Ÿฆ‹

IANA moved every entry with the protocol 'http' out of the "Permanent Message Header Field Names" and "Provisional Message Header Field Names" registries (see <https://www.iana.org/assignments/message-headers/>) and into the new one, with these changes ๐ŸŒธ

  1. The 'Applicable Protocol' field got omitted. Bye bye ๐Ÿ‘‹
  2. Entries that were 'standard', 'experimental', 'reserved', or 'informational' became 'permanent' ๐Ÿ’–
  3. Provisional entries with no status became 'provisional' โœจ
  4. Permanent entries with no status (after confirming the registration document didn't define one) became 'provisional' ๐Ÿ™ˆ The expert(s) can change the status if there's evidence another one fits better ๐Ÿงš

IANA added a note to the old "Permanent Message Header Field Names" and "Provisional Message Header Field Names" registries saying HTTP field name registrations have moved ๐Ÿ“Œ

Note HTTP field name registrations have been moved to [https://www.iana.org/assignments/http-fields] per [RFC9110].

IANA also updated the new "Hypertext Transfer Protocol (HTTP) Field Name Registry" with the field names in the table below ๐Ÿ“

+===========================+============+=========+============+
| Field Name                | Status     | Section | Comments   |
+===========================+============+=========+============+
| Accept                    | permanent  | 12.5.1  |            |
+---------------------------+------------+---------+------------+
| Accept-Charset            | deprecated | 12.5.2  |            |
+---------------------------+------------+---------+------------+
| Accept-Encoding           | permanent  | 12.5.3  |            |
+---------------------------+------------+---------+------------+
| Accept-Language           | permanent  | 12.5.4  |            |
+---------------------------+------------+---------+------------+
| Accept-Ranges             | permanent  | 14.3    |            |
+---------------------------+------------+---------+------------+
| Allow                     | permanent  | 10.2.1  |            |
+---------------------------+------------+---------+------------+
| Authentication-Info       | permanent  | 11.6.3  |            |
+---------------------------+------------+---------+------------+
| Authorization             | permanent  | 11.6.2  |            |
+---------------------------+------------+---------+------------+
| Connection                | permanent  | 7.6.1   |            |
+---------------------------+------------+---------+------------+
| Content-Encoding          | permanent  | 8.4     |            |
+---------------------------+------------+---------+------------+
| Content-Language          | permanent  | 8.5     |            |
+---------------------------+------------+---------+------------+
| Content-Length            | permanent  | 8.6     |            |
+---------------------------+------------+---------+------------+
| Content-Location          | permanent  | 8.7     |            |
+---------------------------+------------+---------+------------+
| Content-Range             | permanent  | 14.4    |            |
+---------------------------+------------+---------+------------+
| Content-Type              | permanent  | 8.3     |            |
+---------------------------+------------+---------+------------+
| Date                      | permanent  | 6.6.1   |            |
+---------------------------+------------+---------+------------+
| ETag                      | permanent  | 8.8.3   |            |
+---------------------------+------------+---------+------------+
| Expect                    | permanent  | 10.1.1  |            |
+---------------------------+------------+---------+------------+
| From                      | permanent  | 10.1.2  |            |
+---------------------------+------------+---------+------------+
| Host                      | permanent  | 7.2     |            |
+---------------------------+------------+---------+------------+
| If-Match                  | permanent  | 13.1.1  |            |
+---------------------------+------------+---------+------------+
| If-Modified-Since         | permanent  | 13.1.3  |            |
+---------------------------+------------+---------+------------+
| If-None-Match             | permanent  | 13.1.2  |            |
+---------------------------+------------+---------+------------+
| If-Range                  | permanent  | 13.1.5  |            |
+---------------------------+------------+---------+------------+
| If-Unmodified-Since       | permanent  | 13.1.4  |            |
+---------------------------+------------+---------+------------+
| Last-Modified             | permanent  | 8.8.2   |            |
+---------------------------+------------+---------+------------+
| Location                  | permanent  | 10.2.2  |            |
+---------------------------+------------+---------+------------+
| Max-Forwards              | permanent  | 7.6.2   |            |
+---------------------------+------------+---------+------------+
| Proxy-Authenticate        | permanent  | 11.7.1  |            |
+---------------------------+------------+---------+------------+
| Proxy-Authentication-Info | permanent  | 11.7.3  |            |
+---------------------------+------------+---------+------------+
| Proxy-Authorization       | permanent  | 11.7.2  |            |
+---------------------------+------------+---------+------------+
| Range                     | permanent  | 14.2    |            |
+---------------------------+------------+---------+------------+
| Referer                   | permanent  | 10.1.3  |            |
+---------------------------+------------+---------+------------+
| Retry-After               | permanent  | 10.2.3  |            |
+---------------------------+------------+---------+------------+
| Server                    | permanent  | 10.2.4  |            |
+---------------------------+------------+---------+------------+
| TE                        | permanent  | 10.1.4  |            |
+---------------------------+------------+---------+------------+
| Trailer                   | permanent  | 6.6.2   |            |
+---------------------------+------------+---------+------------+
| Upgrade                   | permanent  | 7.8     |            |
+---------------------------+------------+---------+------------+
| User-Agent                | permanent  | 10.1.5  |            |
+---------------------------+------------+---------+------------+
| Vary                      | permanent  | 12.5.5  |            |
+---------------------------+------------+---------+------------+
| Via                       | permanent  | 7.6.3   |            |
+---------------------------+------------+---------+------------+
| WWW-Authenticate          | permanent  | 11.6.1  |            |
+---------------------------+------------+---------+------------+
| *                         | permanent  | 12.5.5  | (reserved) |
+---------------------------+------------+---------+------------+

Table 9 ๐Ÿฉต

The field name "*" is reserved because using that name as an HTTP header field might clash with its special meaning in the Vary header field (Section 12.5.5) ๐Ÿ™ˆ

IANA also updated the "Content-MD5" entry in the new registry to have a status of 'obsoleted' ๐Ÿฅ€ It points to Section 14.15 of [RFC2616] (for the definition of the header field) and Appendix B of [RFC7231] (which removed the field definition from the updated spec) ๐Ÿ“š

18.5. Authentication Scheme Registration ๐Ÿ”

IANA updated the "Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry" at <https://www.iana.org/assignments/http-authschemes> with the registration procedure of Section 16.4.1 ๐Ÿ’œ No authentication schemes are defined in this document, so this one is just a quick stop ๐Ÿฆ‹

18.6. Content Coding Registration ๐Ÿ—œ๏ธ

IANA updated the "HTTP Content Coding Registry" at <https://www.iana.org/assignments/http-parameters/> with the registration procedure of Section 16.6.1 and the content coding names in the table below ๐ŸŒˆ

+============+===========================================+=========+
| Name       | Description                               | Section |
+============+===========================================+=========+
| compress   | UNIX "compress" data format [Welch]       | 8.4.1.1 |
+------------+-------------------------------------------+---------+
| deflate    | "deflate" compressed data ([RFC1951])     | 8.4.1.2 |
|            | inside the "zlib" data format ([RFC1950]) |         |
+------------+-------------------------------------------+---------+
| gzip       | GZIP file format [RFC1952]                | 8.4.1.3 |
+------------+-------------------------------------------+---------+
| identity   | Reserved                                  | 12.5.3  |
+------------+-------------------------------------------+---------+
| x-compress | Deprecated (alias for compress)           | 8.4.1.1 |
+------------+-------------------------------------------+---------+
| x-gzip     | Deprecated (alias for gzip)               | 8.4.1.3 |
+------------+-------------------------------------------+---------+

Table 10 ๐ŸŽ€

18.7. Range Unit Registration ๐Ÿ“

IANA updated the "HTTP Range Unit Registry" at <https://www.iana.org/assignments/http-parameters/> with the registration procedure of Section 16.5.1 and the range unit names in the table below ๐Ÿ’–

+=================+==================================+=========+
| Range Unit Name | Description                      | Section |
+=================+==================================+=========+
| bytes           | a range of octets                | 14.1.2  |
+-----------------+----------------------------------+---------+
| none            | reserved as keyword to indicate  | 14.3    |
|                 | range requests are not supported |         |
+-----------------+----------------------------------+---------+

Table 11 โœจ

18.8. Media Type Registration ๐ŸŽž๏ธ

IANA updated the "Media Types" registry at <https://www.iana.org/assignments/media-types> with the registration information in Section 14.6 for the media type "multipart/byteranges" ๐Ÿ“

IANA also updated the registry note about "q" parameters with a link to Section 12.5.1 of this document ๐Ÿ”—

18.9. Port Registration ๐Ÿ”Œ

IANA updated the "Service Name and Transport Protocol Port Number Registry" at <https://www.iana.org/assignments/service-names-port-numbers/> for the services on ports 80 and 443 that use UDP or TCP ๐Ÿงš They did two things:

  1. use this document as "Reference", and
  2. when currently unspecified, set "Assignee" to "IESG" and "Contact" to "IETF_Chair" ๐Ÿ‘‘

That's the field name, auth scheme, content coding, range unit, media type, and port registrations all wrapped up, bestie ๐ŸŒˆ๐Ÿ’– More parts coming, so stay tuned ๐Ÿซถ

18.10. Upgrade Token Registration ๐ŸŽ€

okay bestie, last registry in the IANA section ๐Ÿ’… IANA updated the Hypertext Transfer Protocol (HTTP) Upgrade Token Registry at <https://www.iana.org/assignments/http-upgrade-tokens> using the registration procedure from Section 16.7. The upgrade token names are summarized in the table below โœจ

+======+===================+=========================+=========+
| Name | Description       | Expected Version Tokens | Section |
+======+===================+=========================+=========+
| HTTP | Hypertext         | any DIGIT.DIGIT (e.g.,  | 2.5     |
|      | Transfer Protocol | "2.0")                  |         |
+------+-------------------+-------------------------+---------+

Table 12 ๐Ÿฆ‹

19. References ๐Ÿ“š๐Ÿซถ

19.1. Normative References

19.2. Informative References

[RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, DOI 10.17487/RFC2617, June 1999, <https://www.rfc-editor.org/info/rfc2617>.

[RFC2774] Nielsen, H., Leach, P., and S. Lawrence, "An HTTP Extension Framework", RFC 2774, DOI 10.17487/RFC2774, February 2000, <https://www.rfc-editor.org/info/rfc2774>.

[RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, DOI 10.17487/RFC2818, May 2000, <https://www.rfc-editor.org/info/rfc2818>.

[RFC2978] Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19, RFC 2978, DOI 10.17487/RFC2978, October 2000, <https://www.rfc-editor.org/info/rfc2978>.

[RFC3040] Cooper, I., Melve, I., and G. Tomlinson, "Internet Web Replication and Caching Taxonomy", RFC 3040, DOI 10.17487/RFC3040, January 2001, <https://www.rfc-editor.org/info/rfc3040>.

[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, DOI 10.17487/RFC3864, September 2004, <https://www.rfc-editor.org/info/rfc3864>.

[RFC3875] Robinson, D. and K. Coar, "The Common Gateway Interface (CGI) Version 1.1", RFC 3875, DOI 10.17487/RFC3875, October 2004, <https://www.rfc-editor.org/info/rfc3875>.

[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, DOI 10.17487/RFC4033, March 2005, <https://www.rfc-editor.org/info/rfc4033>.

[RFC4559] Jaganathan, K., Zhu, L., and J. Brezak, "SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows", RFC 4559, DOI 10.17487/RFC4559, June 2006, <https://www.rfc-editor.org/info/rfc4559>.

[RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", RFC 5789, DOI 10.17487/RFC5789, March 2010, <https://www.rfc-editor.org/info/rfc5789>.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, "Network Time Protocol Version 4: Protocol and Algorithms Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010, <https://www.rfc-editor.org/info/rfc5905>.

[RFC6454] Barth, A., "The Web Origin Concept", RFC 6454, DOI 10.17487/RFC6454, December 2011, <https://www.rfc-editor.org/info/rfc6454>.

[RFC6585] Nottingham, M. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, DOI 10.17487/RFC6585, April 2012, <https://www.rfc-editor.org/info/rfc6585>.

[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, DOI 10.17487/RFC7230, June 2014, <https://www.rfc-editor.org/info/rfc7230>.

[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, DOI 10.17487/RFC7231, June 2014, <https://www.rfc-editor.org/info/rfc7231>.

[RFC7232] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests", RFC 7232, DOI 10.17487/RFC7232, June 2014, <https://www.rfc-editor.org/info/rfc7232>.

[RFC7233] Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Range Requests", RFC 7233, DOI 10.17487/RFC7233, June 2014, <https://www.rfc-editor.org/info/rfc7233>.

[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", RFC 7234, DOI 10.17487/RFC7234, June 2014, <https://www.rfc-editor.org/info/rfc7234>.

[RFC7235] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer Protocol (HTTP/1.1): Authentication", RFC 7235, DOI 10.17487/RFC7235, June 2014, <https://www.rfc-editor.org/info/rfc7235>.

[RFC7538] Reschke, J., "The Hypertext Transfer Protocol Status Code 308 (Permanent Redirect)", RFC 7538, DOI 10.17487/RFC7538, April 2015, <https://www.rfc-editor.org/info/rfc7538>.

[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext Transfer Protocol Version 2 (HTTP/2)", RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.

[RFC7578] Masinter, L., "Returning Values from Forms: multipart/ form-data", RFC 7578, DOI 10.17487/RFC7578, July 2015, <https://www.rfc-editor.org/info/rfc7578>.

[RFC7615] Reschke, J., "HTTP Authentication-Info and Proxy- Authentication-Info Response Header Fields", RFC 7615, DOI 10.17487/RFC7615, September 2015, <https://www.rfc-editor.org/info/rfc7615>.

[RFC7616] Shekh-Yusef, R., Ed., Ahrens, D., and S. Bremer, "HTTP Digest Access Authentication", RFC 7616, DOI 10.17487/RFC7616, September 2015, <https://www.rfc-editor.org/info/rfc7616>.

[RFC7617] Reschke, J., "The 'Basic' HTTP Authentication Scheme", RFC 7617, DOI 10.17487/RFC7617, September 2015, <https://www.rfc-editor.org/info/rfc7617>.

[RFC7694] Reschke, J., "Hypertext Transfer Protocol (HTTP) Client- Initiated Content-Encoding", RFC 7694, DOI 10.17487/RFC7694, November 2015, <https://www.rfc-editor.org/info/rfc7694>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8187] Reschke, J., "Indicating Character Encoding and Language for HTTP Header Field Parameters", RFC 8187, DOI 10.17487/RFC8187, September 2017, <https://www.rfc-editor.org/info/rfc8187>.

[RFC8246] McManus, P., "HTTP Immutable Responses", RFC 8246, DOI 10.17487/RFC8246, September 2017, <https://www.rfc-editor.org/info/rfc8246>.

[RFC8288] Nottingham, M., "Web Linking", RFC 8288, DOI 10.17487/RFC8288, October 2017, <https://www.rfc-editor.org/info/rfc8288>.

[RFC8336] Nottingham, M. and E. Nygren, "The ORIGIN HTTP/2 Frame", RFC 8336, DOI 10.17487/RFC8336, March 2018, <https://www.rfc-editor.org/info/rfc8336>.

[RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019, <https://www.rfc-editor.org/info/rfc8615>.

[RFC8941] Nottingham, M. and P-H. Kamp, "Structured Field Values for HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021, <https://www.rfc-editor.org/info/rfc8941>.

[Sniffing] WHATWG, "MIME Sniffing", <https://mimesniff.spec.whatwg.org>.

[WEBDAV] Dusseault, L., Ed., "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)", RFC 4918, DOI 10.17487/RFC4918, June 2007, <https://www.rfc-editor.org/info/rfc4918>.

Appendix A. Collected ABNF ๐ŸŽ€

okay bestie, this is the ABNF buffet ๐Ÿ“ all the grammar rules gathered in one place so you don't have to hunt for them. the list rules are expanded the way Section 5.6.1 says, so the little comma-separated bits are already spelled out for you ๐Ÿ’…

   Accept = [ ( media-range [ weight ] ) *( OWS "," OWS ( media-range [
    weight ] ) ) ]
   Accept-Charset = [ ( ( token / "*" ) [ weight ] ) *( OWS "," OWS ( (
    token / "*" ) [ weight ] ) ) ]
   Accept-Encoding = [ ( codings [ weight ] ) *( OWS "," OWS ( codings [
    weight ] ) ) ]
   Accept-Language = [ ( language-range [ weight ] ) *( OWS "," OWS (
    language-range [ weight ] ) ) ]
   Accept-Ranges = acceptable-ranges
   Allow = [ method *( OWS "," OWS method ) ]
   Authentication-Info = [ auth-param *( OWS "," OWS auth-param ) ]
   Authorization = credentials

   BWS = OWS

   Connection = [ connection-option *( OWS "," OWS connection-option )
    ]
   Content-Encoding = [ content-coding *( OWS "," OWS content-coding )
    ]
   Content-Language = [ language-tag *( OWS "," OWS language-tag ) ]
   Content-Length = 1*DIGIT
   Content-Location = absolute-URI / partial-URI
   Content-Range = range-unit SP ( range-resp / unsatisfied-range )
   Content-Type = media-type

   Date = HTTP-date

   ETag = entity-tag
   Expect = [ expectation *( OWS "," OWS expectation ) ]

   From = mailbox

   GMT = %x47.4D.54 ; GMT

   HTTP-date = IMF-fixdate / obs-date
   Host = uri-host [ ":" port ]

   IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
   If-Match = "*" / [ entity-tag *( OWS "," OWS entity-tag ) ]
   If-Modified-Since = HTTP-date
   If-None-Match = "*" / [ entity-tag *( OWS "," OWS entity-tag ) ]
   If-Range = entity-tag / HTTP-date
   If-Unmodified-Since = HTTP-date

   Last-Modified = HTTP-date
   Location = URI-reference

   Max-Forwards = 1*DIGIT

   OWS = *( SP / HTAB )

   Proxy-Authenticate = [ challenge *( OWS "," OWS challenge ) ]
   Proxy-Authentication-Info = [ auth-param *( OWS "," OWS auth-param )
    ]
   Proxy-Authorization = credentials

   RWS = 1*( SP / HTAB )
   Range = ranges-specifier
   Referer = absolute-URI / partial-URI
   Retry-After = HTTP-date / delay-seconds

   Server = product *( RWS ( product / comment ) )

   TE = [ t-codings *( OWS "," OWS t-codings ) ]
   Trailer = [ field-name *( OWS "," OWS field-name ) ]

   URI-reference = <URI-reference, see [URI], Section 4.1>
   Upgrade = [ protocol *( OWS "," OWS protocol ) ]
   User-Agent = product *( RWS ( product / comment ) )

   Vary = [ ( "*" / field-name ) *( OWS "," OWS ( "*" / field-name ) )
    ]
   Via = [ ( received-protocol RWS received-by [ RWS comment ] ) *( OWS
    "," OWS ( received-protocol RWS received-by [ RWS comment ] ) ) ]

   WWW-Authenticate = [ challenge *( OWS "," OWS challenge ) ]

   absolute-URI = <absolute-URI, see [URI], Section 4.3>
   absolute-path = 1*( "/" segment )
   acceptable-ranges = range-unit *( OWS "," OWS range-unit )
   asctime-date = day-name SP date3 SP time-of-day SP year
   auth-param = token BWS "=" BWS ( token / quoted-string )
   auth-scheme = token
   authority = <authority, see [URI], Section 3.2>

   challenge = auth-scheme [ 1*SP ( token68 / [ auth-param *( OWS ","
    OWS auth-param ) ] ) ]
   codings = content-coding / "identity" / "*"
   comment = "(" *( ctext / quoted-pair / comment ) ")"
   complete-length = 1*DIGIT
   connection-option = token
   content-coding = token
   credentials = auth-scheme [ 1*SP ( token68 / [ auth-param *( OWS ","
    OWS auth-param ) ] ) ]
   ctext = HTAB / SP / %x21-27 ; '!'-'''
    / %x2A-5B ; '*'-'['
    / %x5D-7E ; ']'-'~'
    / obs-text

   date1 = day SP month SP year
   date2 = day "-" month "-" 2DIGIT
   date3 = month SP ( 2DIGIT / ( SP DIGIT ) )
   day = 2DIGIT
   day-name = %x4D.6F.6E ; Mon
    / %x54.75.65 ; Tue
    / %x57.65.64 ; Wed
    / %x54.68.75 ; Thu
    / %x46.72.69 ; Fri
    / %x53.61.74 ; Sat
    / %x53.75.6E ; Sun
   day-name-l = %x4D.6F.6E.64.61.79 ; Monday
    / %x54.75.65.73.64.61.79 ; Tuesday
    / %x57.65.64.6E.65.73.64.61.79 ; Wednesday
    / %x54.68.75.72.73.64.61.79 ; Thursday
    / %x46.72.69.64.61.79 ; Friday
    / %x53.61.74.75.72.64.61.79 ; Saturday
    / %x53.75.6E.64.61.79 ; Sunday
   delay-seconds = 1*DIGIT

   entity-tag = [ weak ] opaque-tag
   etagc = "!" / %x23-7E ; '#'-'~'
    / obs-text
   expectation = token [ "=" ( token / quoted-string ) parameters ]

   field-content = field-vchar [ 1*( SP / HTAB / field-vchar )
    field-vchar ]
   field-name = token
   field-value = *field-content
   field-vchar = VCHAR / obs-text
   first-pos = 1*DIGIT

   hour = 2DIGIT
   http-URI = "http://" authority path-abempty [ "?" query ]
   https-URI = "https://" authority path-abempty [ "?" query ]

   incl-range = first-pos "-" last-pos
   int-range = first-pos "-" [ last-pos ]

   language-range = <language-range, see [RFC4647], Section 2.1>
   language-tag = <Language-Tag, see [RFC5646], Section 2.1>
   last-pos = 1*DIGIT

   mailbox = <mailbox, see [RFC5322], Section 3.4>
   media-range = ( "*/*" / ( type "/*" ) / ( type "/" subtype ) )
    parameters
   media-type = type "/" subtype parameters
   method = token
   minute = 2DIGIT
   month = %x4A.61.6E ; Jan
    / %x46.65.62 ; Feb
    / %x4D.61.72 ; Mar
    / %x41.70.72 ; Apr
    / %x4D.61.79 ; May
    / %x4A.75.6E ; Jun
    / %x4A.75.6C ; Jul
    / %x41.75.67 ; Aug
    / %x53.65.70 ; Sep
    / %x4F.63.74 ; Oct
    / %x4E.6F.76 ; Nov
    / %x44.65.63 ; Dec

   obs-date = rfc850-date / asctime-date
   obs-text = %x80-FF
   opaque-tag = DQUOTE *etagc DQUOTE
   other-range = 1*( %x21-2B ; '!'-'+'
    / %x2D-7E ; '-'-'~'
    )

   parameter = parameter-name "=" parameter-value
   parameter-name = token
   parameter-value = ( token / quoted-string )
   parameters = *( OWS ";" OWS [ parameter ] )
   partial-URI = relative-part [ "?" query ]
   path-abempty = <path-abempty, see [URI], Section 3.3>
   port = <port, see [URI], Section 3.2.3>
   product = token [ "/" product-version ]
   product-version = token
   protocol = protocol-name [ "/" protocol-version ]
   protocol-name = token
   protocol-version = token
   pseudonym = token

   qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'['
    / %x5D-7E ; ']'-'~'
    / obs-text
   query = <query, see [URI], Section 3.4>
   quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
   quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
   qvalue = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )

   range-resp = incl-range "/" ( complete-length / "*" )
   range-set = range-spec *( OWS "," OWS range-spec )
   range-spec = int-range / suffix-range / other-range
   range-unit = token
   ranges-specifier = range-unit "=" range-set
   received-by = pseudonym [ ":" port ]
   received-protocol = [ protocol-name "/" ] protocol-version
   relative-part = <relative-part, see [URI], Section 4.2>
   rfc850-date = day-name-l "," SP date2 SP time-of-day SP GMT

   second = 2DIGIT
   segment = <segment, see [URI], Section 3.3>
   subtype = token
   suffix-length = 1*DIGIT
   suffix-range = "-" suffix-length

   t-codings = "trailers" / ( transfer-coding [ weight ] )
   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
    "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
   time-of-day = hour ":" minute ":" second
   token = 1*tchar
   token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" )
    *"="
   transfer-coding = token *( OWS ";" OWS transfer-parameter )
   transfer-parameter = token BWS "=" BWS ( token / quoted-string )
   type = token

   unsatisfied-range = "*/" complete-length
   uri-host = <host, see [URI], Section 3.2.2>

   weak = %x57.2F ; W/
   weight = OWS ";" OWS "q=" qvalue

   year = 4DIGIT

Appendix B. Changes from Previous RFCs ๐Ÿฆ‹

ok this part is the glow-up history ๐ŸŒธ what changed from the older RFCs, so you can see what's new and what's been moved around โœจ

B.1. Changes from RFC 2818

Nothing changed here! ๐Ÿซถ the list is just "None." ๐Ÿ™ˆ

B.2. Changes from RFC 7230

bestie, this is the big one ๐Ÿ’œ here's everything that shifted from RFC 7230:

The sections about HTTP's design goals, history, architecture, conformance criteria, protocol versioning, URIs, message routing, and header fields got moved into this document ๐Ÿ“ฆโœจ

The semantic conformance requirement got swapped out for permission to ignore or work around implementation-specific failures ๐Ÿ™ˆ (Section 2.2)

The description of an origin and authoritative access to origin servers got extended for both "http" and "https" URIs, so it can account for alternative services and secured connections that aren't necessarily based on TCP ๐ŸŒˆ (Sections 4.2.1, 4.2.2, 4.3.1, and 7.3.3)

Explicit requirements got added to check the target URI scheme's semantics and to reject requests that don't meet any associated requirements ๐Ÿ”ฅ (Section 7.4)

Parameters in media type, media range, and expectation can now be empty via one or more trailing semicolons ๐Ÿ’… (Section 5.6.6)

"Field value" now refers to the value after multiple field lines are combined with commas, which is by far the most common use ๐Ÿ‘‘ If you want to refer to a single header line's value, use "field line value" instead. (Section 6.3)

Trailer field semantics now go beyond chunked transfer coding specifics ๐Ÿฆ‹ The use of trailer fields got further limited: a sender may generate one as a trailer field only when it knows the field defines that usage, and a recipient may merge it into the header section only if it knows the corresponding field definition permits and defines how to merge. In all other cases, implementations are encouraged either to store the trailer fields separately or to discard them instead of merging. (Section 6.5.1)

The priority of the absolute form of the request URI over the Host header field by origin servers got made explicit, so it lines up with proxy handling ๐ŸŽ€ (Section 7.2)

The grammar for the Via field's "received-by" got expanded in RFC 7230 because of changes to the URI grammar for host [URI] that aren't desirable for Via. For simplicity, uri-host got removed from the received-by production, since it can be covered by the existing grammar for pseudonym. This change also removed comma from the allowed set of characters for a host name in received-by. (Section 7.6.3)

B.3. Changes from RFC 7231 ๐Ÿ’…โœจ

Okay so the big one first: minimum URI lengths that implementations should support are now RECOMMENDED ๐ŸŽ€ (Section 4.1). Wait, let me say that properly: the original says they are now recommended, so the capitalised phrase goes here as RECOMMENDED. ๐ŸŒธ

The following have been clarified, bestie ๐Ÿซถ: CR and NUL in field values are to be rejected or mapped to SP, and leading and trailing whitespace needs to be stripped from field values before they are consumed. (Section 5.5) ๐Ÿ˜ญ

Parameters in media type, media range, and expectation can be empty via one or more trailing semicolons. (Section 5.6.6) ๐Ÿฆ‹

An abstract data type for HTTP messages has been introduced ๐Ÿงš to define the components of a message and their semantics as an abstraction across multiple HTTP versions, rather than in terms of the specific syntax form of HTTP/1.1 in [HTTP/1.1], and reflect the contents after the message is parsed. This makes it easier to distinguish between requirements on the content (what is conveyed) versus requirements on the messaging syntax (how it is conveyed) and avoids baking limitations of early protocol versions into the future of HTTP. (Section 6) ๐Ÿ‘‘

The terms "payload" and "payload body" have been replaced with "content", to better align with its usage elsewhere (e.g., in field names) and to avoid confusion with frame payloads in HTTP/2 and HTTP/3. (Section 6.4) ๐Ÿ’œ

The term "effective request URI" has been replaced with "target URI". (Section 7.1) ๐Ÿ“

Restrictions on client retries have been loosened to reflect implementation behavior. (Section 9.2.2) ๐ŸŒˆ

The fact that request bodies on GET, HEAD, and DELETE are not interoperable has been clarified. (Sections 9.3.1, 9.3.2, and 9.3.5) ๐Ÿ™ˆ

The use of the Content-Range header field (Section 14.4) as a request modifier on PUT is allowed. (Section 9.3.4) โœจ

A superfluous requirement about setting Content-Length has been removed from the description of the OPTIONS method. (Section 9.3.7) ๐Ÿ’€

The normative requirement to use the "message/http" media type in TRACE responses has been removed. (Section 9.3.8) ๐Ÿ”ฅ

List-based grammar for Expect has been restored for compatibility with RFC 2616. (Section 10.1.1) ๐ŸŽ€

Accept and Accept-Encoding are allowed in response messages; the latter was introduced by [RFC7694]. (Section 12.3) ๐Ÿ’–

"Accept Parameters" (accept-params and accept-ext ABNF production) have been removed from the definition of the Accept field. (Section 12.5.1) ๐Ÿฆ‹

The Accept-Charset field is now deprecated. (Section 12.5.2) ๐ŸŒธ

The semantics of "*" in the Vary header field when other values are present was clarified. (Section 12.5.5) โญ

Range units are compared in a case-insensitive fashion. (Section 14.1) ๐Ÿ’…

The use of the Accept-Ranges field is not restricted to origin servers. (Section 14.3) ๐Ÿซถ

The process of creating a redirected request has been clarified. (Section 15.4) ๐Ÿงš

Status code 308 (previously defined in [RFC7538]) has been added so that it's defined closer to status codes 301, 302, and 307. (Section 15.4.9) ๐Ÿ‘‘

Status code 421 (previously defined in Section 9.1.2 of [RFC7540]) has been added because of its general applicability. 421 is no longer defined as heuristically cacheable since the response is specific to the connection (not the target resource). (Section 15.5.20) ๐ŸŒˆ

Status code 422 (previously defined in Section 11.2 of [WEBDAV]) has been added because of its general applicability. (Section 15.5.21) ๐Ÿ’–

B.4. Changes from RFC 7232 ๐ŸŒธ

Previous revisions of HTTP imposed an arbitrary 60-second limit on the determination of whether Last-Modified was a strong validator, to guard 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. This specification has relaxed that to allow reasonable discretion. (Section 8.8.2.2) โญ

An edge-case requirement on If-Match and If-Unmodified-Since has been removed, which required a validator not to be sent in a 2xx response if validation fails because the change request has already been applied. (Sections 13.1.1 and 13.1.4) ๐Ÿ™ˆ

The fact that If-Unmodified-Since does not apply to a resource without a concept of modification time has been clarified. (Section 13.1.4) ๐Ÿ’…

Preconditions can now be evaluated before the request content is processed, rather than waiting until the response would otherwise be successful. (Section 13.2) ๐Ÿฆ‹

B.5. Changes from RFC 7233 ๐Ÿงš

Refactored the range-unit and ranges-specifier grammars to simplify and reduce artificial distinctions between bytes and other (extension) range units, removing the overlapping grammar of other-range-unit by defining range units generically as a token and placing extensions within the scope of a range-spec (other-range). This disambiguates the role of list syntax (commas) in all range sets, including extension range units, for indicating a range-set of more than one range. Moving the extension grammar into range specifiers also allows protocol specific to byte ranges to be specified separately. ๐Ÿ‘‘

It is now possible to define Range handling on extension methods. (Section 14.2) ๐Ÿ“

Described use of the Content-Range header field (Section 14.4) as a request modifier to perform a partial PUT. (Section 14.5) ๐ŸŒˆ

B.6. Changes from RFC 7235 ๐Ÿ’œ

None. ๐ŸŒธ

B.7. Changes from RFC 7538 ๐ŸŽ€

None. ๐Ÿ’–

B.8. Changes from RFC 7615 ๐Ÿฆ‹

None. โœจ

B.9. Changes from RFC 7694 ๐Ÿซถ

This specification includes the extension defined in [RFC7694] but leaves out examples and deployment considerations. ๐Ÿ”ฅ


Acknowledgements ๐ŸŒท

Aside from the current editors, the following individuals deserve special recognition for their contributions to early aspects of HTTP and its core specifications: Marc Andreessen, Tim Berners-Lee, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jim Gettys, Jean-Franรงois Groff, Phillip M. Hallam-Baker, Koen Holtman, Jeffery L. Hostetler, Shel Kaphan, Dave Kristol, Yves Lafon, Scott D. Lawrence, Paul J. Leach, Hรฅkon W. Lie, Ari Luotonen, Larry Masinter, Rob McCool, Jeffrey C. Mogul, Lou Montulli, David Morris, Henrik Frystyk Nielsen, Dave Raggett, Eric Rescorla, Tony Sanders, Lawrence C. Stewart, Marc VanHeyningen, and Steve Zilles. ๐Ÿ‘‘

This document builds on the many contributions that went into past specifications of HTTP, including [HTTP/1.0], [RFC2068], [RFC2145], [RFC2616], [RFC2617], [RFC2818], [RFC7230], [RFC7231], [RFC7232], [RFC7233], [RFC7234], and [RFC7235]. The acknowledgements within those documents still apply. ๐Ÿ’–

Since 2014, the following contributors have helped improve this specification by reporting bugs, asking smart questions, drafting or reviewing text, and evaluating issues: Alan Egerton, Alex Rousskov, Amichai Rothman, Amos Jeffries, Anders Kaseorg, Andreas Gebhardt, Anne van Kesteren, Armin Abfalterer, Aron Duby, Asanka Herath, Asbjรธrn Ulsberg, Asta Olofsson, Attila Gulyas, Austin Wright, Barry Pollard, Ben Burkert, Benjamin Kaduk, Bjรถrn Hรถhrmann, Brad Fitzpatrick, Chris Pacejo, Colin Bendell, Cory Benfield, Cory Nelson, Daisuke Miyakawa, Dale Worley, Daniel Stenberg, Danil Suits, David Benjamin, David Matson, David Schinazi, ะ”ะธะปัะฝ ะŸะฐะปะฐัƒะทะพะฒ (Dilyan Palauzov), Eric Anderson, Eric Rescorla, ร‰ric Vyncke, Erik Kline, Erwin Pe, Etan Kissling, Evert Pot, Evgeny Vrublevsky, Florian Best, Francesca Palombini, Igor Lubashev, James Callahan, James Peach, Jeffrey Yasskin, Kalin Gyokov, Kannan Goundan, ๅฅฅ ไธ€็ฉ‚ (Kazuho Oku), Ken Murchison, Krzysztof Maczyล„ski, Lars Eggert, Lucas Pardue, Martin Duke, Martin Dรผrst, Martin Thomson, Martynas Juseviฤius, Matt Menke, Matthias Pigulla, Mattias Grenfeldt, Michael Osipov, Mike Bishop, Mike Pennisi, Mike Taylor, Mike West, Mohit Sethi, Murray Kucherawy, Nathaniel J. Smith, Nicholas Hurley, Nikita Prokhorov, Patrick McManus, Piotr Sikora, Poul-Henning Kamp, Rick van Rein, Robert Wilton, Roberto Polli, Roman Danyliw, Samuel Williams, Semyon Kholodnov, Simon Pieters, Simon Schรผppel, Stefan Eissing, Taylor Hunt, Todd Greer, Tommy Pauly, Vasiliy Faronov, Vladimir Lashchev, Wenbo Zhu, William A. Rowe Jr., Willy Tarreau, Xingwei Liu, Yishuai Li, and Zaheduzzaman Sarker. ๐ŸŒˆ

Index ๐Ÿ“š

1 2 3 4 5 A B C D E F G H I L M N O P R S T U V W X

1

100 Continue (status code) _Section 15.2.1_ 100-continue (expect value) _Section 10.1.1_ 101 Switching Protocols (status code) _Section 15.2.2_ 1xx Informational (status code class) _Section 15.2_

2

200 OK (status code) _Section 15.3.1_ 201 Created (status code) _Section 15.3.2_ 202 Accepted (status code) _Section 15.3.3_ 203 Non-Authoritative Information (status code) _Section 15.3.4_ 204 No Content (status code) _Section 15.3.5_ 205 Reset Content (status code) _Section 15.3.6_ 206 Partial Content (status code) _Section 15.3.7_ 2xx Successful (status code class) _Section 15.3_

3

300 Multiple Choices (status code) _Section 15.4.1_ 301 Moved Permanently (status code) _Section 15.4.2_ 302 Found (status code) _Section 15.4.3_ 303 See Other (status code) _Section 15.4.4_ 304 Not Modified (status code) _Section 15.4.5_ 305 Use Proxy (status code) _Section 15.4.6_ 306 (Unused) (status code) _Section 15.4.7_ 307 Temporary Redirect (status code) _Section 15.4.8_ 308 Permanent Redirect (status code) _Section 15.4.9_ 3xx Redirection (status code class) _Section 15.4_

4

400 Bad Request (status code) _Section 15.5.1_ 401 Unauthorized (status code) _Section 15.5.2_ 402 Payment Required (status code) _Section 15.5.3_ 403 Forbidden (status code) _Section 15.5.4_ 404 Not Found (status code) _Section 15.5.5_ 405 Method Not Allowed (status code) _Section 15.5.6_ 406 Not Acceptable (status code) _Section 15.5.7_ 407 Proxy Authentication Required (status code) _Section 15.5.8_ 408 Request Timeout (status code) _Section 15.5.9_ 409 Conflict (status code) _Section 15.5.10_ 410 Gone (status code) _Section 15.5.11_ 411 Length Required (status code) _Section 15.5.12_ 412 Precondition Failed (status code) _Section 15.5.13_ 413 Content Too Large (status code) _Section 15.5.14_ 414 URI Too Long (status code) _Section 15.5.15_ 415 Unsupported Media Type (status code) _Section 15.5.16_ 416 Range Not Satisfiable (status code) _Section 15.5.17_ 417 Expectation Failed (status code) _Section 15.5.18_ 418 (Unused) (status code) _Section 15.5.19_ 421 Misdirected Request (status code) _Section 15.5.20_ 422 Unprocessable Content (status code) _Section 15.5.21_ 426 Upgrade Required (status code) _Section 15.5.22_ 4xx Client Error (status code class) _Section 15.5_

5

500 Internal Server Error (status code) _Section 15.6.1_ 501 Not Implemented (status code) _Section 15.6.2_ 502 Bad Gateway (status code) _Section 15.6.3_ 503 Service Unavailable (status code) _Section 15.6.4_ 504 Gateway Timeout (status code) _Section 15.6.5_ 505 HTTP Version Not Supported (status code) _Section 15.6.6_ 5xx Server Error (status code class) _Section 15.6_

A

okay bestie, the index is a whole vibe ๐Ÿ’… here are the entries from the accelerator line through the H heading โœจ

         accelerator  *_Section 3.7, Paragraph 6_*
         Accept header field  *_Section 12.5.1_*
         Accept-Charset header field  *_Section 12.5.2_*
         Accept-Encoding header field  *_Section 12.5.3_*
         Accept-Language header field  *_Section 12.5.4_*
         Accept-Ranges header field  *_Section 14.3_*
         Allow header field  *_Section 10.2.1_*
         Authentication-Info header field  *_Section 11.6.3_*
         authoritative response  *_Section 17.1_*
         Authorization header field  *_Section 11.6.2_*

      B

         browser  *_Section 3.5_*

      C

         cache  *_Section 3.8_*
         cacheable  *_Section 3.8, Paragraph 4_*
         client  *_Section 3.3_*
         clock  *_Section 5.6.7_*
         complete  *_Section 6.1_*
         compress (Coding Format)  Section 8.4.1.1
         compress (content coding)  *_Section 8.4.1_*
         conditional request  *_Section 13_*
         CONNECT method  *_Section 9.3.6_*
         connection  *_Section 3.3_*
         Connection header field  *_Section 7.6.1_*
         content  Section 6.4
         content coding  *_Section 8.4.1_*
         content negotiation  Section 1.3, Paragraph 4
         Content-Encoding header field  *_Section 8.4_*
         Content-Language header field  *_Section 8.5_*
         Content-Length header field  *_Section 8.6_*
         Content-Location header field  *_Section 8.7_*
         Content-MD5 header field  *_Section 18.4, Paragraph 10_*
         Content-Range header field  *_Section 14.4_*; Section 14.5
         Content-Type header field  *_Section 8.3_*
         control data  *_Section 6.2_*

      D

         Date header field  *_Section 6.6.1_*
         deflate (Coding Format)  Section 8.4.1.2
         deflate (content coding)  *_Section 8.4.1_*
         DELETE method  *_Section 9.3.5_*
         Delimiters  Section 5.6.2, Paragraph 3
         downstream  *_Section 3.7, Paragraph 4_*

      E

         effective request URI  *_Section 7.1, Paragraph 8.1_*
         ETag field  *_Section 8.8.3_*
         Expect header field  *_Section 10.1.1_*

      F

         field  *_Section 5_*; Section 6.3
         field line  Section 5.2, Paragraph 1
         field line value  Section 5.2, Paragraph 1
         field name  Section 5.2, Paragraph 1
         field value  Section 5.2, Paragraph 2
         Fields
            *  *_Section 18.4, Paragraph 9_*
            Accept  *_Section 12.5.1_*
            Accept-Charset  *_Section 12.5.2_*
            Accept-Encoding  *_Section 12.5.3_*
            Accept-Language  *_Section 12.5.4_*
            Accept-Ranges  *_Section 14.3_*
            Allow  *_Section 10.2.1_*
            Authentication-Info  *_Section 11.6.3_*
            Authorization  *_Section 11.6.2_*
            Connection  *_Section 7.6.1_*
            Content-Encoding  *_Section 8.4_*
            Content-Language  *_Section 8.5_*
            Content-Length  *_Section 8.6_*
            Content-Location  *_Section 8.7_*
            Content-MD5  *_Section 18.4, Paragraph 10_*
            Content-Range  *_Section 14.4_*; Section 14.5
            Content-Type  *_Section 8.3_*
            Date  *_Section 6.6.1_*
            ETag  *_Section 8.8.3_*
            Expect  *_Section 10.1.1_*
            From  *_Section 10.1.2_*
            Host  *_Section 7.2_*
            If-Match  *_Section 13.1.1_*
            If-Modified-Since  *_Section 13.1.3_*
            If-None-Match  *_Section 13.1.2_*
            If-Range  *_Section 13.1.5_*
            If-Unmodified-Since  *_Section 13.1.4_*
            Last-Modified  *_Section 8.8.2_*
            Location  *_Section 10.2.2_*
            Max-Forwards  *_Section 7.6.2_*
            Proxy-Authenticate  *_Section 11.7.1_*
            Proxy-Authentication-Info  *_Section 11.7.3_*
            Proxy-Authorization  *_Section 11.7.2_*
            Range  *_Section 14.2_*
            Referer  *_Section 10.1.3_*
            Retry-After  *_Section 10.2.3_*
            Server  *_Section 10.2.4_*
            TE  *_Section 10.1.4_*
            Trailer  *_Section 6.6.2_*
            Upgrade  *_Section 7.8_*
            User-Agent  *_Section 10.1.5_*
            Vary  *_Section 12.5.5_*
            Via  *_Section 7.6.3_*
            WWW-Authenticate  *_Section 11.6.1_*
         Fragment Identifiers  Section 4.2.5
         From header field  *_Section 10.1.2_*

      G

         gateway  *_Section 3.7, Paragraph 6_*
         GET method  *_Section 9.3.1_*
         Grammar
            ALPHA  *_Section 2.1_*
            Accept  *_Section 12.5.1_*
            Accept-Charset  *_Section 12.5.2_*
            Accept-Encoding  *_Section 12.5.3_*
            Accept-Language  *_Section 12.5.4_*
            Accept-Ranges  *_Section 14.3_*
            Allow  *_Section 10.2.1_*
            Authentication-Info  *_Section 11.6.3_*
            Authorization  *_Section 11.6.2_*
            BWS  *_Section 5.6.3_*
            CR  *_Section 2.1_*
            CRLF  *_Section 2.1_*
            CTL  *_Section 2.1_*
            Connection  *_Section 7.6.1_*
            Content-Encoding  *_Section 8.4_*
            Content-Language  *_Section 8.5_*
            Content-Length  *_Section 8.6_*
            Content-Location  *_Section 8.7_*
            Content-Range  *_Section 14.4_*
            Content-Type  *_Section 8.3_*
            DIGIT  *_Section 2.1_*
            DQUOTE  *_Section 2.1_*
            Date  *_Section 6.6.1_*
            ETag  *_Section 8.8.3_*
            Expect  *_Section 10.1.1_*
            From  *_Section 10.1.2_*
            GMT  *_Section 5.6.7_*
            HEXDIG  *_Section 2.1_*
            HTAB  *_Section 2.1_*
            HTTP-date  *_Section 5.6.7_*
            Host  *_Section 7.2_*
            IMF-fixdate  *_Section 5.6.7_*
            If-Match  *_Section 13.1.1_*
            If-Modified-Since  *_Section 13.1.3_*
            If-None-Match  *_Section 13.1.2_*
            If-Range  *_Section 13.1.5_*
            If-Unmodified-Since  *_Section 13.1.4_*
            LF  *_Section 2.1_*
            Last-Modified  *_Section 8.8.2_*
            Location  *_Section 10.2.2_*
            Max-Forwards  *_Section 7.6.2_*
            OCTET  *_Section 2.1_*
            OWS  *_Section 5.6.3_*
            Proxy-Authenticate  *_Section 11.7.1_*
            Proxy-Authentication-Info  *_Section 11.7.3_*
            Proxy-Authorization  *_Section 11.7.2_*
            RWS  *_Section 5.6.3_*
            Range  *_Section 14.2_*
            Referer  *_Section 10.1.3_*
            Retry-After  *_Section 10.2.3_*
            SP  *_Section 2.1_*
            Server  *_Section 10.2.4_*
            TE  *_Section 10.1.4_*
            Trailer  *_Section 6.6.2_*
            URI-reference  *_Section 4.1_*
            Upgrade  *_Section 7.8_*
            User-Agent  *_Section 10.1.5_*
            VCHAR  *_Section 2.1_*
            Vary  *_Section 12.5.5_*
            Via  *_Section 7.6.3_*
            WWW-Authenticate  *_Section 11.6.1_*
            absolute-URI  *_Section 4.1_*
            absolute-path  *_Section 4.1_*
            acceptable-ranges  *_Section 14.3_*
            asctime-date  *_Section 5.6.7_*
            auth-param  *_Section 11.2_*
            auth-scheme  *_Section 11.1_*
            authority  *_Section 4.1_*
            challenge  *_Section 11.3_*
            codings  *_Section 12.5.3_*
            comment  *_Section 5.6.5_*
            complete-length  *_Section 14.4_*
            connection-option  *_Section 7.6.1_*
            content-coding  *_Section 8.4.1_*
            credentials  *_Section 11.4_*
            ctext  *_Section 5.6.5_*
            date1  *_Section 5.6.7_*
            day  *_Section 5.6.7_*
            day-name  *_Section 5.6.7_*
            day-name-l  *_Section 5.6.7_*
            delay-seconds  *_Section 10.2.3_*
            entity-tag  *_Section 8.8.3_*
            etagc  *_Section 8.8.3_*
            field-content  *_Section 5.5_*
            field-name  *_Section 5.1_*; Section 6.6.2
            field-value  *_Section 5.5_*
            field-vchar  *_Section 5.5_*
            first-pos  *_Section 14.1.1_*; Section 14.4
            hour  *_Section 5.6.7_*
            http-URI  *_Section 4.2.1_*
            https-URI  *_Section 4.2.2_*
            incl-range  *_Section 14.4_*
            int-range  *_Section 14.1.1_*
            language-range  *_Section 12.5.4_*
            language-tag  *_Section 8.5.1_*
            last-pos  *_Section 14.1.1_*; Section 14.4
            media-range  *_Section 12.5.1_*
            media-type  *_Section 8.3.1_*
            method  *_Section 9.1_*
            minute  *_Section 5.6.7_*
            month  *_Section 5.6.7_*
            obs-date  *_Section 5.6.7_*
            obs-text  *_Section 5.5_*
            opaque-tag  *_Section 8.8.3_*
            other-range  *_Section 14.1.1_*
            parameter  *_Section 5.6.6_*
            parameter-name  *_Section 5.6.6_*
            parameter-value  *_Section 5.6.6_*
            parameters  *_Section 5.6.6_*
            partial-URI  *_Section 4.1_*
            port  *_Section 4.1_*
            product  *_Section 10.1.5_*
            product-version  *_Section 10.1.5_*
            protocol-name  *_Section 7.6.3_*
            protocol-version  *_Section 7.6.3_*
            pseudonym  *_Section 7.6.3_*
            qdtext  *_Section 5.6.4_*
            query  *_Section 4.1_*
            quoted-pair  *_Section 5.6.4_*
            quoted-string  *_Section 5.6.4_*
            qvalue  *_Section 12.4.2_*
            range-resp  *_Section 14.4_*
            range-set  *_Section 14.1.1_*
            range-spec  *_Section 14.1.1_*
            range-unit  *_Section 14.1_*
            ranges-specifier  *_Section 14.1.1_*
            received-by  *_Section 7.6.3_*
            received-protocol  *_Section 7.6.3_*
            rfc850-date  *_Section 5.6.7_*
            second  *_Section 5.6.7_*
            segment  *_Section 4.1_*
            subtype  *_Section 8.3.1_*
            suffix-length  *_Section 14.1.1_*
            suffix-range  *_Section 14.1.1_*
            t-codings  *_Section 10.1.4_*
            tchar  *_Section 5.6.2_*
            time-of-day  *_Section 5.6.7_*
            token  *_Section 5.6.2_*
            token68  *_Section 11.2_*
            transfer-coding  *_Section 10.1.4_*
            transfer-parameter  *_Section 10.1.4_*
            type  *_Section 8.3.1_*
            unsatisfied-range  *_Section 14.4_*
            uri-host  *_Section 4.1_*
            weak  *_Section 8.8.3_*
            weight  *_Section 12.4.2_*
            year  *_Section 5.6.7_*
         gzip (Coding Format)  Section 8.4.1.3
         gzip (content coding)  *_Section 8.4.1_*

      H

Okay bestie, this is the index, the big cheat sheet where you can find every header field, method, status code and term in the whole spec. ๐Ÿ’– Each entry points to the section it lives in, so if you're ever lost, just look it up ๐Ÿงš

         HEAD method  *_Section 9.3.2_*
         Header Fields
            Accept  *_Section 12.5.1_*
            Accept-Charset  *_Section 12.5.2_*
            Accept-Encoding  *_Section 12.5.3_*
            Accept-Language  *_Section 12.5.4_*
            Accept-Ranges  *_Section 14.3_*
            Allow  *_Section 10.2.1_*
            Authentication-Info  *_Section 11.6.3_*
            Authorization  *_Section 11.6.2_*
            Connection  *_Section 7.6.1_*
            Content-Encoding  *_Section 8.4_*
            Content-Language  *_Section 8.5_*
            Content-Length  *_Section 8.6_*
            Content-Location  *_Section 8.7_*
            Content-MD5  *_Section 18.4, Paragraph 10_*
            Content-Range  *_Section 14.4_*; Section 14.5
            Content-Type  *_Section 8.3_*
            Date  *_Section 6.6.1_*
            ETag  *_Section 8.8.3_*
            Expect  *_Section 10.1.1_*
            From  *_Section 10.1.2_*
            Host  *_Section 7.2_*
            If-Match  *_Section 13.1.1_*
            If-Modified-Since  *_Section 13.1.3_*
            If-None-Match  *_Section 13.1.2_*
            If-Range  *_Section 13.1.5_*
            If-Unmodified-Since  *_Section 13.1.4_*
            Last-Modified  *_Section 8.8.2_*
            Location  *_Section 10.2.2_*
            Max-Forwards  *_Section 7.6.2_*
            Proxy-Authenticate  *_Section 11.7.1_*
            Proxy-Authentication-Info  *_Section 11.7.3_*
            Proxy-Authorization  *_Section 11.7.2_*
            Range  *_Section 14.2_*
            Referer  *_Section 10.1.3_*
            Retry-After  *_Section 10.2.3_*
            Server  *_Section 10.2.4_*
            TE  *_Section 10.1.4_*
            Trailer  *_Section 6.6.2_*
            Upgrade  *_Section 7.8_*
            User-Agent  *_Section 10.1.5_*
            Vary  *_Section 12.5.5_*
            Via  *_Section 7.6.3_*
            WWW-Authenticate  *_Section 11.6.1_*
         header section  *_Section 6.3_*
         Host header field  *_Section 7.2_*
         http URI scheme  *_Section 4.2.1_*
         https URI scheme  *_Section 4.2.2_*

      I

         idempotent  *_Section 9.2.2_*
         If-Match header field  *_Section 13.1.1_*
         If-Modified-Since header field  *_Section 13.1.3_*
         If-None-Match header field  *_Section 13.1.2_*
         If-Range header field  *_Section 13.1.5_*
         If-Unmodified-Since header field  *_Section 13.1.4_*
         inbound  *_Section 3.7, Paragraph 4_*
         incomplete  *_Section 6.1_*
         interception proxy  *_Section 3.7, Paragraph 10_*
         intermediary  *_Section 3.7_*

      L

         Last-Modified header field  *_Section 8.8.2_*
         list-based field  Section 5.5, Paragraph 7
         Location header field  *_Section 10.2.2_*

      M

         Max-Forwards header field  *_Section 7.6.2_*
         Media Type
            multipart/byteranges  *_Section 14.6_*
            multipart/x-byteranges  Section 14.6, Paragraph 4, Item 3
         message  Section 3.4; *_Section 6_*
         message abstraction  *_Section 6_*
         messages  *_Section 3.4_*
         metadata  *_Section 8.8_*
         Method
            *  *_Section 18.2, Paragraph 3_*
            CONNECT  *_Section 9.3.6_*
            DELETE  *_Section 9.3.5_*
            GET  *_Section 9.3.1_*
            HEAD  *_Section 9.3.2_*
            OPTIONS  *_Section 9.3.7_*
            POST  *_Section 9.3.3_*
            PUT  *_Section 9.3.4_*
            TRACE  *_Section 9.3.8_*
         multipart/byteranges Media Type  *_Section 14.6_*
         multipart/x-byteranges Media Type  Section 14.6, Paragraph 4,
            Item 3

      N

         non-transforming proxy  *_Section 7.7_*

      O

         OPTIONS method  *_Section 9.3.7_*
         origin  *_Section 4.3.1_*; Section 11.5
         origin server  *_Section 3.6_*
         outbound  *_Section 3.7, Paragraph 4_*

      P

         phishing  *_Section 17.1_*
         POST method  *_Section 9.3.3_*
         Protection Space  Section 11.5
         proxy  *_Section 3.7, Paragraph 5_*
         Proxy-Authenticate header field  *_Section 11.7.1_*
         Proxy-Authentication-Info header field  *_Section 11.7.3_*
         Proxy-Authorization header field  *_Section 11.7.2_*
         PUT method  *_Section 9.3.4_*

      R

         Range header field  *_Section 14.2_*
         Realm  Section 11.5
         recipient  *_Section 3.4_*
         Referer header field  *_Section 10.1.3_*
         representation  *_Section 3.2_*
         request  *_Section 3.4_*
         request target  *_Section 7.1_*
         resource  *_Section 3.1_*; Section 4
         response  *_Section 3.4_*
         Retry-After header field  *_Section 10.2.3_*
         reverse proxy  *_Section 3.7, Paragraph 6_*

      S

         safe  *_Section 9.2.1_*
         satisfiable range  *_Section 14.1.1_*
         secured  *_Section 4.2.2_*
         selected representation  *_Section 3.2, Paragraph 4_*;
            Section 8.8; Section 13.1
         self-descriptive  *_Section 6_*
         sender  *_Section 3.4_*
         server  *_Section 3.3_*
         Server header field  *_Section 10.2.4_*
         singleton field  Section 5.5, Paragraph 6
         spider  *_Section 3.5_*
         Status Code  Section 15
         Status Codes
            Final  Section 15, Paragraph 7
            Informational  Section 15, Paragraph 7
            Interim  Section 15, Paragraph 7
         Status Codes Classes
            1xx Informational  *_Section 15.2_*
            2xx Successful  *_Section 15.3_*
            3xx Redirection  *_Section 15.4_*
            4xx Client Error  *_Section 15.5_*
            5xx Server Error  *_Section 15.6_*

      T

         target resource  *_Section 7.1_*
         target URI  *_Section 7.1_*
         TE header field  *_Section 10.1.4_*
         TRACE method  *_Section 9.3.8_*
         Trailer Fields  *_Section 6.5_*
            ETag  *_Section 8.8.3_*
         Trailer header field  *_Section 6.6.2_*
         trailer section  *_Section 6.5_*
         trailers  *_Section 6.5_*
         transforming proxy  *_Section 7.7_*
         transparent proxy  *_Section 3.7, Paragraph 10_*
         tunnel  *_Section 3.7, Paragraph 8_*

      U

         unsatisfiable range  *_Section 14.1.1_*
         Upgrade header field  *_Section 7.8_*
         upstream  *_Section 3.7, Paragraph 4_*
         URI  *_Section 4_*
            origin  *_Section 4.3.1_*
         URI reference  *_Section 4.1_*
         URI scheme
            http  *_Section 4.2.1_*
            https  *_Section 4.2.2_*
         user agent  *_Section 3.5_*
         User-Agent header field  *_Section 10.1.5_*

      V

         validator  *_Section 8.8_*
            strong  *_Section 8.8.1_*
            weak  *_Section 8.8.1_*
         Vary header field  *_Section 12.5.5_*
         Via header field  *_Section 7.6.3_*

      W

         WWW-Authenticate header field  *_Section 11.6.1_*

      X

         x-compress (content coding)  *_Section 8.4.1_*
         x-gzip (content coding)  *_Section 8.4.1_*

Authors' Addresses โœจ

Meet the crew who wrote this ๐ŸŽ€ Roy, Mark and Julian, the editors who kept the whole thing together ๐Ÿซถ

   Roy T. Fielding (editor)
   Adobe
   345 Park Ave
   San Jose, CA 95110
   United States of America
   Email: fielding@gbiv.com
   URI:   https://roy.gbiv.com/


   Mark Nottingham (editor)
   Fastly
   Prahran
   Australia
   Email: mnot@mnot.net
   URI:   https://www.mnot.net/


   Julian Reschke (editor)
   greenbytes GmbH
   Hafenweg 16
   48155 Mรผnster
   Germany
   Email: julian.reschke@greenbytes.de
   URI:   https://greenbytes.de/tech/webdav/
๐Ÿ“ฆ where this page comes from