Specifications should use [HTTP] as the primary reference for HTTP; it is not necessary to reference all of the specifications in the HTTP suite unless there are specific reasons to do so (e.g., a particular feature is called out).
Because HTTP is a hop-by-hop protocol, a connection can be handled by implementations that are not controlled by the application; for example, proxies, CDNs, firewalls, and so on. Requiring a particular version of HTTP makes it difficult to use in these situations and harms interoperability. Therefore, it is NOT RECOMMENDED that applications using HTTP specify a minimum version of HTTP to be used.
However, if an application's deployment benefits from the use of a particular version of HTTP (for example, HTTP/2's multiplexing), this ought be noted.
Applications using HTTP MUST NOT specify a maximum version, to preserve the protocol's ability to evolve.
When specifying examples of protocol interactions, applications should document both the request and response messages with complete header sections, preferably in HTTP/1.1 format [HTTP/1.1]. For example:
GET /thing HTTP/1.1
HTTP/1.1 200 OK
An application's expectations for client behaviour ought to be closely aligned with those of Web browsers to avoid interoperability issues when they are used.
One way to do this is to define it in terms of [FETCH] since that is the abstraction that browsers use for HTTP.
Some client behaviours (e.g., automatic redirect handling) and extensions (e.g., cookies) are not required by HTTP but nevertheless have become very common. If their use is not explicitly specified by applications using HTTP, there may be confusion and interoperability problems. In particular:
- Redirect handling:
- Applications need to specify how redirects are expected to be handled; see Section 4.6.1.
- Applications using HTTP should explicitly reference the Cookie specification [COOKIES] if they are required.
- Applications using HTTP should specify that TLS certificates are to be checked according to Section 4.3.4 of [HTTP] when HTTPS is used.
Applications using HTTP should not require that clients statically support HTTP features that are usually negotiated. For example, requiring that clients support responses with a certain content coding ([HTTP], Section 8.4.1) instead of negotiating for it ([HTTP], Section 12.5.3) means that otherwise conformant clients cannot interoperate with the application. Applications can encourage the implementation of such features, though.
Applications that use HTTP MUST confine themselves to using registered HTTP methods such as GET, POST, PUT, DELETE, and PATCH.
New HTTP methods are rare; they are required to be registered in the "HTTP Method Registry" with IETF Review (see [HTTP]) and are also required to be generic. That means that they need to be potentially applicable to all resources, not just those of one application.
While historically some applications (e.g., [RFC4791]) have defined application-specific methods, [HTTP] now forbids this.
When authors believe that a new method is required, they are encouraged to engage with the HTTP community early (e.g., on the <mailto:firstname.lastname@example.org> mailing list) and document their proposal as a separate HTTP extension rather than as part of an application's specification.
GET is the most common and useful HTTP method; its retrieval semantics allow caching and side-effect free linking and underlie many of the benefits of using HTTP.
Queries can be performed with GET, often using the query component of the URL; this is a familiar pattern from Web browsing, and the results can be cached, improving the efficiency of an often expensive process. In some cases, however, GET might be unwieldy for expressing queries because of the limited syntax of the URI; in particular, if binary data forms part of the query terms, it needs to be encoded to conform to the URI syntax.
While this is not an issue for short queries, it can become one for larger query terms or those that need to sustain a high rate of requests. Additionally, some HTTP implementations limit the size of URLs they support, although modern HTTP software has much more generous limits than previously (typically, considerably more than 8000 octets, as required by [HTTP]).
In these cases, an application using HTTP might consider using POST to express queries in the request's content; doing so avoids encoding overhead and URL length limits in implementations. However, in doing so, it should be noted that the benefits of GET such as caching and linking to query results are lost. Therefore, applications using HTTP that require support for POST queries ought to consider allowing both methods.
Processing of GET requests should not change the application's state or have other side effects that might be significant to the client since implementations can and do retry HTTP GET requests that fail. Furthermore, some GET requests protected by TLS early data might be vulnerable to replay attacks (see [RFC8470]). Note that this does not include logging and similar functions; see [HTTP], Section 9.2.1.
Finally, note that while the generic HTTP syntax allows a GET request message to contain content, the purpose is to allow message parsers to be generic; per [HTTP], Section 9.3.1, content in a GET is not recommended, has no meaning, and will be either ignored or rejected by generic HTTP software (such as intermediaries, caches, servers, and client libraries).
The OPTIONS method was defined for metadata retrieval and is used both by Web Distributed Authoring and Versioning (WebDAV) [RFC4918] and CORS [FETCH]. Because HTTP-based APIs often need to retrieve metadata about resources, it is often considered for their use.
However, OPTIONS does have significant limitations:
- It isn't possible to link to the metadata with a simple URL because OPTIONS is not the default method.
- OPTIONS responses are not cacheable because HTTP caches operate on representations of the resource (i.e., GET and HEAD). If OPTIONS responses are cached separately, their interactions with the HTTP cache expiry, secondary keys, and other mechanisms need to be considered.
- OPTIONS is "chatty" -- requesting metadata separately increases the number of requests needed to interact with the application.
- Implementation support for OPTIONS is not universal; some servers do not expose the ability to respond to OPTIONS requests without significant effort.
Instead of OPTIONS, one of these alternative approaches might be more appropriate:
- For server-wide metadata, create a well-known URI [WELL-KNOWN-URI] or use an already existing one if appropriate (e.g., host-meta [RFC6415]).
- For metadata about a specific resource, create a separate resource and link to it using a Link response header field or a link serialised into the response's content. See [WEB-LINKING]. Note that the Link header field is available on HEAD responses, which is useful if the client wants to discover a resource's capabilities before they interact with it.
HTTP status codes convey semantics both for the benefit of generic HTTP components -- such as caches, intermediaries, and clients -- and applications themselves. However, applications can encounter a number of pitfalls in their use.
First, status codes are often generated by components other than the application itself. This can happen, for example, when network errors are encountered; when a captive portal, proxy, or content delivery network is present; or when a server is overloaded or thinks it is under attack. They can even be generated by generic client software when certain error conditions are encountered. As a result, if an application assigns specific semantics to one of these status codes, a client can be misled about its state because the status code was generated by a generic component, not the application itself.
Furthermore, mapping application errors to individual HTTP status codes one-to-one often leads to a situation where the finite space of applicable HTTP status codes is exhausted. This, in turn, leads to a number of bad practices -- including minting new, application-specific status codes or using existing status codes even though the link between their semantics and the application's is tenuous at best.
Instead, applications using HTTP should define their errors to use the most applicable status code, making generous use of the general status codes (200, 400, and 500) when in doubt. Importantly, they should not specify a one-to-one relationship between status codes and application errors, thereby avoiding the exhaustion issue outlined above.
To distinguish between multiple error conditions that are mapped to the same status code and to avoid the misattribution issue outlined above, applications using HTTP should convey finer-grained error information in the response's message content and/or header fields. [PROBLEM-DETAILS] provides one way to do so.
Because the set of registered HTTP status codes can expand, applications using HTTP should explicitly point out that clients ought to be able to handle all applicable status codes gracefully (i.e., falling back to the generic n00 semantics of a given status code; e.g., 499 can be safely handled as 400 (Bad Request) by clients that don't recognise it). This is preferable to creating a "laundry list" of potential status codes since such a list won't be complete in the foreseeable future.
Applications using HTTP MUST NOT re-specify the semantics of HTTP status codes, even if it is only by copying their definition. It is NOT RECOMMENDED they require specific reason phrases to be used; the reason phrase has no function in HTTP, is not guaranteed to be preserved by implementations, and is not carried at all in the HTTP/2 [HTTP/2] message format.
Applications MUST only use registered HTTP status codes. As with methods, new HTTP status codes are rare and required (by [HTTP]) to be registered with IETF Review. Similarly, HTTP status codes are generic; they are required (by [HTTP]) to be potentially applicable to all resources, not just to those of one application.
When authors believe that a new status code is required, they are encouraged to engage with the HTTP community early (e.g., on the <mailto:email@example.com> mailing list) and document their proposal as a separate HTTP extension, rather than as part of an application's specification.
The 3xx series of status codes specified in Section 15.4 of [HTTP] directs the user agent to another resource to satisfy the request. The most common of these are 301, 302, 307, and 308, all of which use the Location response header field to indicate where the client should resend the request.
There are two ways that the members of this group of status codes differ:
- Whether they are permanent or temporary. Permanent redirects can be used to update links stored in the client (e.g., bookmarks), whereas temporary ones cannot. Note that this has no effect on HTTP caching; it is completely separate.
- Whether they allow the redirected request to change the request method from POST to GET. Web browsers generally do change POST to GET for 301 and 302; therefore, 308 and 307 were created to allow redirection without changing the method.
This table summarises their relationships:
|Allows change of the request method from POST to GET||301||302|
|Does not allow change of the request method||308||307|
The 303 (See Other) status code can be used to inform the client that the result of an operation is available at a different location using GET.
As noted in [HTTP], a user agent is allowed to automatically follow a 3xx redirect that has a Location response header field, even if they don't understand the semantics of the specific status code. However, they aren't required to do so; therefore, if an application using HTTP desires redirects to be automatically followed, it needs to explicitly specify the circumstances when this is required.
Redirects can be cached (when appropriate cache directives are present), but beyond that, they are not "sticky" -- i.e., redirection of a URI will not result in the client assuming that similar URIs (e.g., with different query parameters) will also be redirected.
Applications using HTTP are encouraged to specify that 301 and 302 responses change the subsequent request method from POST (but no other method) to GET to be compatible with browsers. Generally, when a redirected request is made, its header fields are copied from the original request. However, they can be modified by various mechanisms; e.g., sent Authorization ([HTTP], Section 11) and Cookie ([COOKIES]) header fields will change if the origin (and sometimes path) of the request changes. An application using HTTP should specify if any request header fields that it defines need to be modified or removed upon a redirect; however, this behaviour cannot be relied upon since a generic client (like a browser) will be unaware of such requirements.
Common syntactic conventions for message contents include JSON [JSON], XML [XML], and Concise Binary Object Representation (CBOR) [RFC8949]. Best practices for their use are out of scope for this document.
Applications should register distinct media types for each format they define; this makes it possible to identify them unambiguously and negotiate for their use. See [RFC6838] for more information.
Clients often need to send multiple requests to perform a task.
In HTTP/1 [HTTP/1.1], parallel requests are most often supported by opening multiple connections. Application performance can be impacted when too many simultaneous connections are used because connections' congestion control will not be coordinated. Furthermore, it can be difficult for applications to decide when to issue and which connection to use for a given request, further impacting performance.
HTTP/2 [HTTP/2] and HTTP/3 [HTTP/3] offer multiplexing to applications, removing the need to use multiple connections. However, application performance can still be significantly affected by how the server chooses to prioritize responses. Depending on the application, it might be best for the server to determine the priority of responses or for the client to hint its priorities to the server (see, e.g., [HTTP-PRIORITY]).
In all versions of HTTP, requests are made independently -- you can't rely on the relative order of two requests to guarantee their processing order. This is because they might be sent over a multiplexed protocol by an intermediary or sent to different origin servers, or the server might even perform processing in a different order. If two requests need strict ordering, the only reliable way to ensure the outcome is to issue the second request when the final response to the first has begun.
Applications MUST NOT make assumptions about the relationship between separate requests on a single transport connection; doing so breaks many of the assumptions of HTTP as a stateless protocol and will cause problems in interoperability, security, operability, and evolution.
Applications can use HTTP authentication (Section 11 of [HTTP]) to identify clients. Per [RFC7617], the Basic authentication scheme is not suitable for protecting sensitive or valuable information unless the channel is secure (e.g., using the "https" URI scheme). Likewise, [RFC7616] requires the Digest authentication scheme to be used over a secure channel.
With HTTPS, clients might also be authenticated using certificates [RFC8446], but note that such authentication is intrinsically scoped to the underlying transport connection. As a result, a client has no way of knowing whether the authenticated status was used in preparing the response (though Vary: * and/or the private cache directive can provide a partial indication), and the only way to obtain a specifically unauthenticated response is to open a new connection.
When used, it is important to carefully specify the scoping and use of authentication; if the application exposes sensitive data or capabilities (e.g., by acting as an ambient authority; see Section 8.3 of [RFC6454]), exploits are possible. Mitigations include using a request-specific token to ensure the intent of the client.
Even if there is not an intent for an application to be used with a Web browser, its resources will remain available to browsers and other HTTP clients. This means that all such applications that use HTTP need to consider how browsers will interact with them, particularly regarding security.
For example, if an application's state can be changed using a POST request, a Web browser can easily be coaxed into cross-site request forgery (CSRF) from arbitrary Web sites.
Or, if an attacker gains control of content returned from the application's resources (for example, part of the request is reflected in the response, or the response contains external information that the attacker can change), they can inject code into the browser and access data and capabilities as if they were the origin -- a technique known as a cross-site scripting (XSS) attack.
This is only a small sample of the kinds of issues that applications using HTTP must consider. Generally, the best approach is to actually consider the application as a Web application, and to follow best practices for their secure development.
A complete enumeration of such practices is out of scope for this document, but some considerations include:
- Using an application-specific media type in the Content-Type header field, and requiring clients to fail if it is not used.
- Using X-Content-Type-Options: nosniff [FETCH] to ensure that content under attacker control can't be coaxed into a form that is interpreted as active content by a Web browser.
- Using Content-Security-Policy [CSP] to constrain the capabilities of active content (i.e., that which can execute scripts, such as HTML [HTML] and PDF), thereby mitigating XSS attacks.
- Using Referrer-Policy [REFERRER-POLICY] to prevent sensitive data in URLs from being leaked in the Referer request header field.
- Using the 'HttpOnly' flag on Cookies to ensure that cookies are not exposed to browser scripting languages [COOKIES].
- Avoiding use of compression on any sensitive information (e.g., authentication tokens, passwords), as the scripting environment offered by Web browsers allows an attacker to repeatedly probe the compression space; if the attacker has access to the network path of the communication, they can use this capability to recover that information.
Depending on how they are intended to be deployed, specifications for applications using HTTP might require the use of these mechanisms in specific ways or might merely point them out in Security Considerations.
An example of an HTTP response from an application that does not intend for its content to be treated as active by browsers might look like this:
HTTP/1.1 200 OK
Content-Security-Policy: default-src 'none'
If an application has browser compatibility as a goal, client interaction ought to be defined in terms of [FETCH] since that is the abstraction that browsers use for HTTP; it enforces many of these best practices.
Because many HTTP capabilities are scoped to the origin [RFC6454], applications also need to consider how deployments might interact with other applications (including Web browsing) that use the same origin server.
For example, if cookies [COOKIES] are used to carry application state, they will be sent with all requests to the origin by default (unless scoped by path), and the application might receive cookies from other applications on the origin server. This can lead to security issues as well as collision in cookie names.
One solution to these issues is to require a dedicated hostname for the application so that it has a unique origin. However, it is often desirable to allow multiple applications to be deployed on a single hostname; doing so provides the most deployment flexibility and enables them to be "mixed" together (see [BCP190] for details).
Modern Web browsers constrain the ability of content from one origin to access resources from another to avoid leaking private information. As a result, applications that wish to expose cross-origin data to browsers will need to implement the CORS protocol; see [FETCH].