Content Security Policy (CSP) - HTTP

Content Security Policy (CSP)
=============================

**Content Security Policy** (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks,
 including Cross-Site Scripting (XSS) and data injection attacks.
 These attacks are used for everything from data theft, to site defacement, to malware distribution.

 CSP is designed to be fully backward compatible (except CSP version 2 where there are some explicitly-mentioned inconsistencies in backward compatibility; more details here section 1.1).
 Browsers that don't support it still work with servers that implement it, and vice versa: browsers that don't support CSP ignore it, functioning as usual, defaulting to the standard same-origin policy for web content.
 If the site doesn't offer the CSP header, browsers likewise use the standard same-origin policy.

 To enable CSP, you need to configure your web server to return the `Content-Security-Policy` HTTP header.
 (Sometimes you may see mentions of the `X-Content-Security-Policy` header, but that's an older version and you don't need to specify it anymore.)

Alternatively, the `<meta>` element can be used to configure a policy, for example:

```html
<meta
 http-equiv="Content-Security-Policy"
 content="default-src 'self'; img-src https://\*; child-src 'none';" />
```

**Note:** Some features, such as sending CSP violation reports, are only available when using the HTTP headers.

Threats
-------

### Mitigating cross-site scripting

 A primary goal of CSP is to mitigate and report XSS attacks. XSS attacks exploit the browser's trust in the content received from the server.
 Malicious scripts are executed by the victim's browser because the browser trusts the source of the content, even when it's not coming from where it seems to be coming from.

 CSP makes it possible for server administrators to reduce or eliminate the vectors by which XSS can occur by specifying the domains that the browser should consider to be valid sources of executable scripts.
 A CSP compatible browser will then only execute scripts loaded in source files received from those allowed domains, ignoring all other scripts (including inline scripts and event-handling HTML attributes).

 As an ultimate form of protection, sites that want to never allow scripts to be
 executed can opt to globally disallow script execution.

### Mitigating packet sniffing attacks

 In addition to restricting the domains from which content can be loaded, the server can specify which protocols are allowed to be used;
 for example (and ideally, from a security standpoint), a server can specify that all content must be loaded using HTTPS.
 A complete data transmission security strategy includes not only enforcing HTTPS for data transfer, but also marking all cookies with the `secure` attribute and providing automatic redirects from HTTP pages to their HTTPS counterparts.
 Sites may also use the `Strict-Transport-Security` HTTP header to ensure that browsers connect to them only over an encrypted channel.

Using CSP
---------

 Configuring Content Security Policy involves adding the `Content-Security-Policy` HTTP header to a web page and giving it values to control what resources the user agent is allowed to load for that page.
 For example, a page that uploads and displays images could allow images from anywhere, but restrict a form action to a specific endpoint.
 A properly designed Content Security Policy helps protect a page against a cross-site scripting attack.
 This article explains how to construct such headers properly, and provides examples.

### Specifying your policy

You can use the `Content-Security-Policy` HTTP header to specify your policy, like this:

```http
Content-Security-Policy: policy
```

The policy is a string containing the policy directives describing your Content Security Policy.

### Writing a policy

 A policy is described using a series of policy directives, each of which describes the policy for a certain resource type or policy area.
 Your policy should include a `default-src` policy directive, which is a fallback for other resource types when they don't have policies of their own (for a complete list, see the description of the `default-src` directive).
 A policy needs to include a `default-src` or `script-src` directive to prevent inline scripts from running, as well as blocking the use of `eval()`.
 A policy needs to include a `default-src` or `style-src` directive to restrict inline styles from being applied from a `<style>` element or a `style` attribute.
 There are specific directives for a wide variety of types of items, so that each type can have its own policy, including fonts, frames, images, audio and video media, scripts, and workers.

For a complete list of policy directives, see the reference page for the Content-Security-Policy header.

Examples: Common use cases
--------------------------

This section provides examples of some common security policy scenarios.

### Example 1

A website administrator wants all content to come from the site's own origin (this excludes subdomains.)

```http
Content-Security-Policy: default-src 'self'
```

### Example 2

A website administrator wants to allow content from a trusted domain and all its subdomains (it doesn't have to be the same domain that the CSP is set on.)

```http
Content-Security-Policy: default-src 'self' example.com \*.example.com
```

### Example 3

 A website administrator wants to allow users of a web application to include images from any origin in their own content,
 but to restrict audio or video media to trusted providers, and all scripts only to a specific server that hosts trusted code.

```http
Content-Security-Policy: default-src 'self'; img-src \*; media-src example.org example.net; script-src userscripts.example.com
```

Here, by default, content is only permitted from the document's origin, with the following exceptions:

* Images may load from anywhere (note the "\*" wildcard).
* Media is only allowed from example.org and example.net (and not from subdomains of those sites).
* Executable script is only allowed from userscripts.example.com.
### Example 4

A website administrator for an online banking site wants to ensure that all its content is loaded using TLS, in order to prevent attackers from eavesdropping on requests.

```http
Content-Security-Policy: default-src https://onlinebanking.example.com
```

The server permits access only to documents being loaded specifically over HTTPS through the single origin onlinebanking.example.com.

### Example 5

A website administrator of a web mail site wants to allow HTML in email, as well as images loaded from anywhere, but not JavaScript or other potentially dangerous content.

```http
Content-Security-Policy: default-src 'self' \*.example.com; img-src \*
```

 Note that this example doesn't specify a `script-src`; with the example CSP,
 this site uses the setting specified by the `default-src` directive, which means that scripts can be loaded only from the originating server.

Testing your policy
-------------------

 To ease deployment, CSP can be deployed in report-only mode.
 The policy is not enforced, but any violations are reported to a provided URI.
 Additionally, a report-only header can be used to test a future revision to a policy without actually deploying it.

You can use the `Content-Security-Policy-Report-Only` HTTP header to specify your policy, like this:

```http
Content-Security-Policy-Report-Only: policy
```

 If both a `Content-Security-Policy-Report-Only` header and a `Content-Security-Policy` header are present in the same response, both policies are honored.
 The policy specified in `Content-Security-Policy` headers is enforced while the `Content-Security-Policy-Report-Only` policy generates reports but is not enforced.

Enabling reporting
------------------

By default, violation reports aren't sent. To enable violation reporting, you need to specify the `report-to` policy directive, providing at least one URI to which to deliver the reports:

```http
Content-Security-Policy: default-src 'self'; report-to http://reportcollector.example.com/collector.cgi
```

Then you need to set up your server to receive the reports; it can store or process them in whatever manner you determine is appropriate.

Violation report syntax
-----------------------

The report JSON object is sent with an `application/csp-report` `Content-Type` and contains the following data:

`blocked-uri`

 The URI of the resource that was blocked from loading by the Content Security Policy.
 If the blocked URI is from a different origin than the `document-uri`, then the blocked URI is truncated to contain just the scheme, host, and port.

`disposition`

Either `"enforce"` or `"report"` depending on whether the `Content-Security-Policy-Report-Only` header or the `Content-Security-Policy` header is used.

`document-uri`

The URI of the document in which the violation occurred.

`effective-directive`

 The directive whose enforcement caused the violation.
 Some browsers may provide different values, such as Chrome providing `style-src-elem`/`style-src-attr`, even when the actually enforced directive was `style-src`.

`original-policy`

The original policy as specified by the `Content-Security-Policy` HTTP header.

`referrer`
Deprecated

Non-standard

The referrer of the document in which the violation occurred.

`script-sample`

 The first 40 characters of the inline script, event handler, or style that caused the violation.
 Only applicable to `script-src*` and `style-src*` violations, when they contain the `'report-sample'`

`status-code`

The HTTP status code of the resource on which the global object was instantiated.

`violated-directive`
Deprecated

The directive whose enforcement caused the violation. The `violated-directive` is a historic name for the `effective-directive` field and contains the same value.

Sample violation report
-----------------------

 Let's consider a page located at `http://example.com/signup.html`.
 It uses the following policy, disallowing everything but stylesheets from `cdn.example.com`.

```http
Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-to /\_/csp-reports
```

The HTML of `signup.html` looks like this:

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    Here be content.
  </body>
</html>
```

 Can you spot the mistake? Stylesheets are allowed to be loaded only from `cdn.example.com`, yet the website tries to load one from its own origin (`http://example.com`).
 A browser capable of enforcing CSP would send the following violation report as a POST request to `http://example.com/_/csp-reports`, when the document is visited:

```json
{
  "csp-report": {
    "blocked-uri": "http://example.com/css/style.css",
    "disposition": "report",
    "document-uri": "http://example.com/signup.html",
    "effective-directive": "style-src-elem",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-to /\_/csp-reports",
    "referrer": "",
    "status-code": 200,
    "violated-directive": "style-src-elem"
  }
}
```

 As you can see, the report includes the full path to the violating resource in `blocked-uri`.
 This is not always the case.
 For example, if the `signup.html` attempted to load CSS from `http://anothercdn.example.com/stylesheet.css`, the browser would *not* include the full path, but only the origin
 (`http://anothercdn.example.com`).
 The CSP specification gives an explanation of this odd behavior.
 In summary, this is done to prevent leaking sensitive information about cross-origin resources.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### Compatibility notes

 A specific incompatibility exists in some versions of the Safari web browser, whereby if a Content Security Policy header is set, but not a Same Origin header,
 the browser will block self-hosted content and off-site content, and incorrectly report that this is due to the Content Security Policy not allowing the content.

See also
--------

* `Content-Security-Policy` HTTP Header
* `Content-Security-Policy-Report-Only` HTTP Header
* Content Security in WebExtensions
* CSP in Web Workers
* Privacy, permissions, and information security
* CSP Evaluator - Evaluate your Content Security Policy


Cross-Origin Resource Policy (CORP) - HTTP

Cross-Origin Resource Policy (CORP)
===================================

**Cross-Origin Resource Policy** is a policy set by the `Cross-Origin-Resource-Policy` HTTP header that lets websites and applications opt in to protection against certain requests from other origins (such as those issued with elements like `<script>` and `<img>`), to mitigate speculative side-channel attacks, like Spectre, as well as Cross-Site Script Inclusion attacks.

CORP is an additional layer of protection beyond the default same-origin policy. Cross-Origin Resource Policy complements Cross-Origin Read Blocking (CORB), which is a mechanism to prevent some cross-origin reads by default.

**Note:** The policy is only effective for `no-cors` requests, which are issued by default for CORS-safelisted methods/headers.

As this policy is expressed via a *response header*, the actual request is not prevented—rather, the browser prevents the *result* from being leaked by stripping the response body.

Usage
-----

**Note:** Due to a bug in Chrome, setting Cross-Origin-Resource-Policy can break PDF rendering, preventing visitors from being able to read past the first page of some PDFs. Exercise caution using this header in a production environment.

Web applications set a Cross-Origin Resource Policy via the `Cross-Origin-Resource-Policy` HTTP response header, which accepts one of three values:

`same-site`

Only requests from the same *Site* can read the resource.

**Warning:** This is less secure than an origin. The algorithm for checking if two origins are same site is defined in the HTML standard and involves checking the *registrable domain*.

`same-origin`

Only requests from the same *origin* (i.e. scheme + host + port) can read the resource.

`cross-origin`

Requests from any *origin* (both same-site and cross-site) can read the resource. This is useful when COEP is used (see below).

```http
Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin
```

During a cross-origin resource policy check, if the header is set, the browser will deny `no-cors` requests issued from a different origin/site.

Relationship to cross-origin embedder policy (COEP)
---------------------------------------------------

The `Cross-Origin-Embedder-Policy` HTTP response header, when used upon a document, can be used to require subresources to either be same-origin with the document, or come with a `Cross-Origin-Resource-Policy` HTTP response header to indicate they are okay with being embedded. This is why the `cross-origin` value exists.

History
-------

The concept was originally proposed in 2012 (as `From-Origin`), but resurrected in Q2 of 2018 and implemented in Safari and Chromium.

In early 2018, two side-channel hardware vulnerabilities known as *Meltdown* and *Spectre* were disclosed. These vulnerabilities allowed sensitive data disclosure due to a race condition which arose as part of speculative execution functionality, designed to improve performance.

In response, Chromium shipped Cross-Origin Read Blocking, which automatically protects certain resources (of `Content-Type` HTML, JSON and XML) against cross-origin reads. If the application does not serve a `no-sniff` directive, Chromium will attempt to guess the `Content-Type` and apply the protection anyway.

`Cross-Origin-Resource-Policy` is an opt-in response header which can protect *any* resource; there is no need for browsers to sniff MIME types.

Specifications
--------------

| Specification |
| --- |
| Fetch Standard # cross-origin-resource-policy-header |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Cross-Origin-Resource-Policy` HTTP Header


Resources and URIs - HTTP

Resources and URIs
==================

HTTP allows a browser, or another user agent, to communicate with different *resources* on the Internet: to do this the browser needs both the *identity* and the *location* of the resources. These two bits of information are described by a URI.

Identifying resources on the Web

URIs and how to access resources on the Web.

Data URLs

A specific kind of URIs, data URLs, embed the resource itself inside the identifier.

Choosing between www and non-www URLs

Advice on using a www-prefixed domain or not, this article explains the consequences of the choice as well as how to make it.

MIME Types

MIME media types define what kind of document a specific resource is. This article presents both the syntax and the most useful MIME types for use on the Web.

Common MIME types

List of common MIME types useful for Web developers.


HTTP caching - HTTP

HTTP caching
============

Overview
--------

The HTTP cache stores a response associated with a request and reuses the stored response for subsequent requests.

There are several advantages to reusability. First, since there is no need to deliver the request to the origin server, then the closer the client and cache are, the faster the response will be. The most typical example is when the browser itself stores a cache for browser requests.

Also, when a response is reusable, the origin server does not need to process the request — so it does not need to parse and route the request, restore the session based on the cookie, query the DB for results, or render the template engine. That reduces the load on the server.

Proper operation of the cache is critical to the health of the system.

Types of caches
---------------

In the HTTP Caching spec, there are two main types of caches: **private caches** and **shared caches**.

### Private caches

A private cache is a cache tied to a specific client — typically a browser cache. Since the stored response is not shared with other clients, a private cache can store a personalized response for that user.

On the other hand, if personalized contents are stored in a cache other than a private cache, then other users may be able to retrieve those contents — which may cause unintentional information leakage.

If a response contains personalized content and you want to store the response only in the private cache, you must specify a `private` directive.

```http
Cache-Control: private
```

Personalized contents are usually controlled by cookies, but the presence of a cookie does not always indicate that it is private, and thus a cookie alone does not make the response private.

### Shared cache

The shared cache is located between the client and the server and can store responses that can be shared among users. And shared caches can be further sub-classified into **proxy caches** and **managed caches**.

#### Proxy caches

In addition to the function of access control, some proxies implement caching to reduce traffic out of the network. This is usually not managed by the service developer, so it must be controlled by appropriate HTTP headers and so on. However, in the past, outdated proxy-cache implementations — such as implementations that do not properly understand the HTTP Caching standard — have often caused problems for developers.

**Kitchen-sink headers** like the following are used to try to work around "old and not updated proxy cache" implementations that do not understand current HTTP Caching spec directives like `no-store`.

```http
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
```

However, in recent years, as HTTPS has become more common and client/server communication has become encrypted, proxy caches in the path can only tunnel a response and can't behave as a cache, in many cases. So in that scenario, there is no need to worry about outdated proxy cache implementations that cannot even see the response.

On the other hand, if a TLS bridge proxy decrypts all communications in a person-in-the-middle manner by installing a certificate from a CA (certificate authority) managed by the organization on the PC, and performs access control, etc. — it is possible to see the contents of the response and cache it. However, since CT (certificate transparency) has become widespread in recent years, and some browsers only allow certificates issued with an SCT (signed certificate timestamp), this method requires the application of an enterprise policy. In such a controlled environment, there is no need to worry about the proxy cache being "out of date and not updated".

#### Managed caches

Managed caches are explicitly deployed by service developers to offload the origin server and to deliver content efficiently. Examples include reverse proxies, CDNs, and service workers in combination with the Cache API.

The characteristics of managed caches vary depending on the product deployed. In most cases, you can control the cache's behavior through the `Cache-Control` header and your own configuration files or dashboards.

For example, the HTTP Caching specification essentially does not define a way to explicitly delete a cache — but with a managed cache, the stored response can be deleted at any time through dashboard operations, API calls, restarts, and so on. That allows for a more proactive caching strategy.

It is also possible to ignore the standard HTTP Caching spec protocols in favor of explicit manipulation. For example, the following can be specified to opt-out of a private cache or proxy cache, while using your own strategy to cache only in a managed cache.

```http
Cache-Control: no-store
```

For example, Varnish Cache uses VCL (Varnish Configuration Language, a type of DSL) logic to handle cache storage, while service workers in combination with the Cache API allow you to create that logic in JavaScript.

That means if a managed cache intentionally ignores a `no-store` directive, there is no need to perceive it as being "non-compliant" with the standard. What you should do is, avoid using kitchen-sink headers, but carefully read the documentation of whatever managed-cache mechanism you're using, and ensure you're controlling the cache properly in the ways provided by the mechanism you've chosen to use.

Note that some CDNs provide their own headers that are effective only for that CDN (for example, `Surrogate-Control`). Currently, work is underway to define a `CDN-Cache-Control` header to standardize those.

![Type of Cache](/en-US/docs/Web/HTTP/Caching/type-of-cache.png)

Heuristic caching
-----------------

HTTP is designed to cache as much as possible, so even if no `Cache-Control` is given, responses will get stored and reused if certain conditions are met. This is called **heuristic caching**.

For example, take the following response. This response was last updated 1 year ago.

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT

<!doctype html>
…
```

It is heuristically known that content which has not been updated for a full year will not be updated for some time after that. Therefore, the client stores this response (despite the lack of `max-age`) and reuses it for a while. How long to reuse is up to the implementation, but the specification recommends about 10% (in this case 0.1 year) of the time after storing.

Heuristic caching is a workaround that came before `Cache-Control` support became widely adopted, and basically all responses should explicitly specify a `Cache-Control` header.

Fresh and stale based on age
----------------------------

Stored HTTP responses have two states: **fresh** and **stale**. The *fresh* state usually indicates that the response is still valid and can be reused, while the *stale* state means that the cached response has already expired.

The criterion for determining when a response is fresh and when it is stale is **age**. In HTTP, age is the time elapsed since the response was generated. This is similar to the TTL in other caching mechanisms.

Take the following example response (604800 seconds is one week):

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=604800

<!doctype html>
…
```

The cache that stored the example response calculates the time elapsed since the response was generated and uses the result as the response's *age*.

For the example response, the meaning of `max-age` is the following:

* If the age of the response is *less* than one week, the response is *fresh*.
* If the age of the response is *more* than one week, the response is *stale*.

As long as the stored response remains fresh, it will be used to fulfill client requests.

When a response is stored in a shared cache, it is possible to tell the client the age of the response. Continuing with the example, if the shared cache stored the response for one day, the shared cache would send the following response to subsequent client requests.

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=604800
Age: 86400

<!doctype html>
…
```

The client which receives that response will find it to be fresh for the remaining 518400 seconds, the difference between the response's `max-age` and `Age`.

Expires or max-age
------------------

In HTTP/1.0, freshness used to be specified by the `Expires` header.

The `Expires` header specifies the lifetime of the cache using an explicit time rather than by specifying an elapsed time.

```http
Expires: Tue, 28 Feb 2022 22:22:22 GMT
```

However, the time format is difficult to parse, many implementation bugs were found, and it is possible to induce problems by intentionally shifting the system clock; therefore, `max-age` — for specifying an elapsed time — was adopted for `Cache-Control` in HTTP/1.1.

If both `Expires` and `Cache-Control: max-age` are available, `max-age` is defined to be preferred. So it is not necessary to provide `Expires` now that HTTP/1.1 is widely used.

Vary
----

The way that responses are distinguished from one another is essentially based on their URLs:

![keyed with url](/en-US/docs/Web/HTTP/Caching/keyed-with-url.png)

But the contents of responses are not always the same, even if they have the same URL. Especially when content negotiation is performed, the response from the server can depend on the values of the `Accept`, `Accept-Language`, and `Accept-Encoding` request headers.

For example, for English content returned with an `Accept-Language: en` header and cached, it is undesirable to then reuse that cached response for requests that have an `Accept-Language: ja` request header. In this case, you can cause the responses to be cached separately — based on language — by adding "`Accept-Language`" to the value of the `Vary` header.

```http
Vary: Accept-Language
```

That causes the cache to be keyed based on a composite of the response URL and the `Accept-Language` request header — rather than being based just on the response URL.

![keyed with url and language](/en-US/docs/Web/HTTP/Caching/keyed-with-url-and-language.png)

Also, if you are providing content optimization (for example, for responsive design) based on the user agent, you may be tempted to include "`User-Agent`" in the value of the `Vary` header. However, the `User-Agent` request header generally has a very large number of variations, which drastically reduces the chance that the cache will be reused. So if possible, instead consider a way to vary behavior based on feature detection rather than based on the `User-Agent` request header.

For applications that employ cookies to prevent others from reusing cached personalized content, you should specify `Cache-Control: private` instead of specifying a cookie for `Vary`.

Validation
----------

Stale responses are not immediately discarded. HTTP has a mechanism to transform a stale response into a fresh one by asking the origin server. This is called **validation**, or sometimes, **revalidation**.

Validation is done by using a **conditional request** that includes an `If-Modified-Since` or `If-None-Match` request header.

### If-Modified-Since

The following response was generated at 22:22:22 and has a `max-age` of 1 hour, so you know that it is fresh until 23:22:22.

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600

<!doctype html>
…
```

At 23:22:22, the response becomes stale and the cache cannot be reused. So the request below shows a client sending a request with an `If-Modified-Since` request header, to ask the server if there have been any changes made since the specified time.

```http
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT
```

The server will respond with `304 Not Modified` if the content has not changed since the specified time.

Since this response only indicates "no change", there is no response body — there's just a status code — so the transfer size is extremely small.

```http
HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2022 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600
```

Upon receiving that response, the client reverts the stored stale response back to being fresh and can reuse it during the remaining 1 hour.

The server can obtain the modification time from the operating-system file system, which is relatively easy to do for the case of serving static files. However, there are some problems; for example, the time format is complex and difficult to parse, and distributed servers have difficulty synchronizing file-update times.

To solve such problems, the `ETag` response header was standardized as an alternative.

### ETag/If-None-Match

The value of the `ETag` response header is an arbitrary value generated by the server. There are no restrictions on how the server must generate the value, so servers are free to set the value based on whatever means they choose — such as a hash of the body contents or a version number.

As an example, if a hash value is used for the `ETag` header and the hash value of the `index.html` resource is `33a64df5`, the response will be as follows:

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600

<!doctype html>
…
```

If that response is stale, the client takes the value of the `ETag` response header for the cached response, and puts it into the `If-None-Match` request header, to ask the server if the resource has been modified:

```http
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "33a64df5"
```

The server will return `304 Not Modified` if the value of the `ETag` header it determines for the requested resource is the same as the `If-None-Match` value in the request.

But if the server determines the requested resource should now have a different `ETag` value, the server will instead respond with a `200 OK` and the latest version of the resource.

**Note:** RFC9110 prefers that servers send both `ETag` and `Last-Modified` for a `200` response if possible.
 During cache revalidation, if both `If-Modified-Since` and `If-None-Match` are present, then `If-None-Match` takes precedence for the validator.
 If you are only considering caching, you may think that `Last-Modified` is unnecessary.
 However, `Last-Modified` is not just useful for caching; it is a standard HTTP header that is also used by content-management (CMS) systems to display the last-modified time, by crawlers to adjust crawl frequency, and for other various purposes.
 So considering the overall HTTP ecosystem, it is better to provide both `ETag` and `Last-Modified`.

### Force Revalidation

If you do not want a response to be reused, but instead want to always fetch the latest content from the server, you can use the `no-cache` directive to force validation.

By adding `Cache-Control: no-cache` to the response along with `Last-Modified` and `ETag` — as shown below — the client will receive a `200 OK` response if the requested resource has been updated, or will otherwise receive a `304 Not Modified` response if the requested resource has not been updated.

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
ETag: deadbeef
Cache-Control: no-cache

<!doctype html>
…
```

It is often stated that the combination of `max-age=0` and `must-revalidate` has the same meaning as `no-cache`.

```http
Cache-Control: max-age=0, must-revalidate
```

`max-age=0` means that the response is immediately stale, and `must-revalidate` means that it must not be reused without revalidation once it is stale — so, in combination, the semantics seem to be the same as `no-cache`.

However, that usage of `max-age=0` is a remnant of the fact that many implementations prior to HTTP/1.1 were unable to handle the `no-cache` directive — and so to deal with that limitation, `max-age=0` was used as a workaround.

But now that HTTP/1.1-conformant servers are widely deployed, there's no reason to ever use that `max-age=0` and `must-revalidate` combination — you should instead just use `no-cache`.

Don't cache
-----------

The `no-cache` directive does not prevent the storing of responses but instead prevents the reuse of responses without revalidation.

If you don't want a response stored in any cache, use `no-store`.

```http
Cache-Control: no-store
```

However, in general, a "do not cache" requirement in practice amounts to the following set of circumstances:

* Don't want the response stored by anyone other than the specific client, for privacy reasons.
* Want to provide up-to-date information always.
* Don't know what could happen in outdated implementations.

Under that set of circumstances, `no-store` is not always the most-appropriate directive.

The following sections look at the circumstances in more detail.

### Do not share with others

It would be problematic if a response with personalized content is unexpectedly visible to other users of a cache.

In such a case, using the `private` directive will cause the personalized response to only be stored with the specific client and not be leaked to any other user of the cache.

```http
Cache-Control: private
```

In such a case, even if `no-store` is given, `private` must also be given.

### Provide up-to-date content every time

The `no-store` directive prevents a response from being stored, but does not delete any already-stored response for the same URL.

In other words, if there is an old response already stored for a particular URL, returning `no-store` will not prevent the old response from being reused.

However, a `no-cache` directive will force the client to send a validation request before reusing any stored response.

```http
Cache-Control: no-cache
```

If the server does not support conditional requests, you can force the client to access the server every time and always get the latest response with `200 OK`.

### Dealing with outdated implementations

As a workaround for outdated implementations that ignore `no-store`, you may see kitchen-sink headers such as the following being used.

```http
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
```

It is recommended to use `no-cache` as an alternative for dealing with such outdated implementations, and it is not a problem if `no-cache` is given from the beginning, since the server will always receive the request.

If it is the shared cache that you are concerned about, you can make sure to prevent unintended caching by also adding `private`:

```http
Cache-Control: no-cache, private
```

### What's lost by `no-store`

You may think adding `no-store` would be the right way to opt-out of caching.

However, it's not recommended to grant `no-store` liberally, because you lose many advantages that HTTP and browsers have, including the browser's back/forward cache.

Therefore, to get the advantages of the full feature set of the web platform, prefer the use of `no-cache` in combination with `private`.

Reload and force reload
-----------------------

Validation can be performed for requests as well as responses.

The **reload** and **force reload** actions are common examples of validation performed from the browser side.

### Reload

For recovering from window corruption or updating to the latest version of the resource, browsers provide a reload function for users.

A simplified view of the HTTP request sent during a browser reload looks as follows:

```http
GET / HTTP/1.1
Host: example.com
Cache-Control: max-age=0
If-None-Match: "deadbeef"
If-Modified-Since: Tue, 22 Feb 2022 20:20:20 GMT
```

(The requests from Chrome, Edge, and Firefox look very much like the above; the requests from Safari will look a bit different.)

The `max-age=0` directive in the request specifies "reuse of responses with an age of 0 or less" — so, in effect, intermediately stored responses are not reused.

As a result, a request is validated by `If-None-Match` and `If-Modified-Since`.

That behavior is also defined in the Fetch standard and can be reproduced in JavaScript by calling `fetch()` with the cache mode set to `no-cache` (note that `reload` is not the right mode for this case):

```js
// Note: "reload" is not the right mode for a normal reload; "no-cache" is
fetch("/", { cache: "no-cache" });
```

### Force reload

Browsers use `max-age=0` during reloads for backward-compatibility reasons — because many outdated implementations prior to HTTP/1.1 did not understand `no-cache`. But `no-cache` is fine now in this use case, and **force reload** is an additional way to bypass cached responses.

The HTTP Request during a browser **force reload** looks as follows:

```http
GET / HTTP/1.1
Host: example.com
Pragma: no-cache
Cache-Control: no-cache
```

(The requests from Chrome, Edge, and Firefox look very much like the above; the requests from Safari will look a bit different.)

Since that's not a conditional request with `no-cache`, you can be sure you'll get a `200 OK` from the origin server.

That behavior is also defined in the Fetch standard and can be reproduced in JavaScript by calling `fetch()` with the cache mode set to `reload` (note that it's not `force-reload`):

```js
// Note: "reload" — rather than "no-cache" — is the right mode for a "force reload"
fetch("/", { cache: "reload" });
```

### Avoiding revalidation

Content that never changes should be given a long `max-age` by using cache busting — that is, by including a version number, hash value, etc., in the request URL.

However, when the user reloads, a revalidation request is sent even though the server knows that the content is immutable.

To prevent that, the `immutable` directive can be used to explicitly indicate that revalidation is not required because the content never changes.

```http
Cache-Control: max-age=31536000, immutable
```

That prevents unnecessary revalidation during reloads.

Note that, instead of implementing that directive, Chrome has changed its implementation so that revalidation is not performed during reloads for subresources.

Deleting stored responses
-------------------------

There is basically no way to delete responses that have already been stored with a long `max-age`.

Imagine that the following response from `https://example.com/` was stored.

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: max-age=31536000

<!doctype html>
…
```

You may want to overwrite that response once it expired on the server, but there is nothing the server can do once the response is stored — since no more requests reach the server due to caching.

One of the methods mentioned in the specification is to send a request for the same URL with an unsafe method such as `POST`, but that is usually difficult to intentionally do for many clients.

There is also a specification for a `Clear-Site-Data: cache` header and value, but not all browsers support it — and even when it's used, it only affects browser caches and has no effect on intermediate caches.

Therefore, it should be assumed that any stored response will remain for its `max-age` period unless the user manually performs a reload, force-reload, or clear-history action.

Caching reduces access to the server, which means that the server loses control of that URL. If the server does not want to lose control of a URL — for example, in the case that a resource is frequently updated — you should add `no-cache` so that the server will always receive requests and send the intended responses.

Request collapse
----------------

The shared cache is primarily located before the origin server and is intended to reduce traffic to the origin server.

Thus, if multiple identical requests arrive at a shared cache at the same time, the intermediate cache will forward a single request on behalf of itself to the origin, which can then reuse the result for all clients. This is called ***request collapse***.

Request collapse occurs when requests are arriving at the same time, so even if `max-age=0` or `no-cache` is given in the response, it will be reused.

If the response is personalized to a particular user and you do not want it to be shared in collapse, you should add the `private` directive:

![Request Collapse](/en-US/docs/Web/HTTP/Caching/request-collapse.png)

Common caching patterns
-----------------------

There are many directives in the `Cache-Control` spec, and it may be difficult to understand all of them. But most websites can be covered by a combination of a handful of patterns.

This section describes the common patterns in designing caches.

### Default settings

As mentioned above, the default behavior for caching (that is, for a response without `Cache-Control`) is not simply "don't cache" but implicit caching according to so-called "heuristic caching".

To avoid that heuristic caching, it's preferable to explicitly give all responses a default `Cache-Control` header.

To ensure that by default the latest versions of resources will always be transferred, it's common practice to make the default `Cache-Control` value include `no-cache`:

```http
Cache-Control: no-cache
```

In addition, if the service implements cookies or other login methods, and the content is personalized for each user, `private` must be given too, to prevent sharing with other users:

```http
Cache-Control: no-cache, private
```

### Cache Busting

The resources that work best with caching are static immutable files whose contents never change. And for resources that *do* change, it is a common best practice to change the URL each time the content changes, so that the URL unit can be cached for a longer period.

As an example, consider the following HTML:

```html
<script src="bundle.js"></script>
<link rel="stylesheet" href="build.css" />
<body>
  hello
</body>
```

In modern web development, JavaScript and CSS resources are frequently updated as development progresses. Also, if the versions of JavaScript and CSS resources that a client uses are out of sync, the display will break.

So the HTML above makes it difficult to cache `bundle.js` and `build.css` with `max-age`.

Therefore, you can serve the JavaScript and CSS with URLs that include a changing part based on a version number or hash value. Some of the ways to do that are shown below.
```

# version in filename
bundle.v123.js

# version in query
bundle.js?v=123

# hash in filename
bundle.YsAIAAAA-QG4G6kCMAMBAAAAAAAoK.js

# hash in query
bundle.js?v=YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

Since the cache distinguishes resources from one another based on their URLs, the cache will not be reused again if the URL changes when a resource is updated.

```html
<script src="bundle.v123.js"></script>
<link rel="stylesheet" href="build.v123.css" />
<body>
  hello
</body>
```

With that design, both JavaScript and CSS resources can be cached for a long time. So how long should `max-age` be set to? The QPACK specification provides an answer to that question.

QPACK is a standard for compressing HTTP header fields, with tables of commonly-used field values defined.

Some commonly-used cache-header values are shown below.
```

36 cache-control max-age=0
37 cache-control max-age=604800
38 cache-control max-age=2592000
39 cache-control no-cache
40 cache-control no-store
41 cache-control public, max-age=31536000
```

If you select one of those numbered options, you can compress values in 1 byte when transferred via HTTP3.

Numbers `37`, `38`, and `41` are for periods of one week, one month, and one year.

Because the cache removes old entries when new entries are saved, the probability that a stored response still exists after one week is not that high — even if `max-age` is set to 1 week. Therefore, in practice, it does not make much difference which one you choose.

Note that number `41` has the longest `max-age` (1 year), but with `public`.

The `public` value has the effect of making the response storable even if the `Authorization` header is present.

**Note:** The `public` directive should only be used if there is a need to store the response when the `Authorization` header is set.
 It is not required otherwise, because a response will be stored in the shared cache as long as `max-age` is given.

So if the response is personalized with basic authentication, the presence of `public` may cause problems. If you are concerned about that, you can choose the second-longest value, `38` (1 month).

```http
# response for bundle.v123.js

# If you never personalize responses via Authorization
Cache-Control: public, max-age=31536000

# If you can't be certain
Cache-Control: max-age=2592000
```

### Validation

Don't forget to set the `Last-Modified` and `ETag` headers, so that you don't have to re-transmit a resource when reloading. It's easy to generate those headers for pre-built static files.

The `ETag` value here may be a hash of the file.

```http
# response for bundle.v123.js
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

In addition, `immutable` can be added to prevent validation on reload.

The combined result is shown below.

```http
# bundle.v123.js
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Length: 1024
Cache-Control: public, max-age=31536000, immutable
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
```

**Cache busting** is a technique to make a response cacheable over a long period by changing the URL when the content changes. The technique can be applied to all subresources, such as images.

**Note:** When evaluating the use of `immutable` and QPACK:
 If you're concerned that `immutable` changes the predefined value provided by QPACK, consider that
 in this case, the `immutable` part can be encoded separately by splitting the `Cache-Control` value into two lines — though this is dependent on the encoding algorithm a particular QPACK implementation uses.

```http
Cache-Control: public, max-age=31536000
Cache-Control: immutable
```

### Main resources

Unlike subresources, main resources cannot be cache busted because their URLs can't be decorated in the same way that subresource URLs can be.

If the following HTML itself is stored, the latest version cannot be displayed even if the content is updated on the server side.

```html
<script src="bundle.v123.js"></script>
<link rel="stylesheet" href="build.v123.css" />
<body>
  hello
</body>
```

For that case, `no-cache` would be appropriate — rather than `no-store` — since we don't want to store HTML, but instead just want it to always be up-to-date.

Furthermore, adding `Last-Modified` and `ETag` will allow clients to send conditional requests, and a `304 Not Modified` can be returned if there have been no updates to the HTML:

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: no-cache
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: AAPuIbAOdvAGEETbgAAAAAAABAAE
```

That setting is appropriate for non-personalized HTML, but for a response that gets personalized using cookies — for example, after a login — don't forget to also specify `private`:

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Cache-Control: no-cache, private
Last-Modified: Tue, 22 Feb 2022 20:20:20 GMT
ETag: AAPuIbAOdvAGEETbgAAAAAAABAAE
Set-Cookie: \_\_Host-SID=AHNtAyt3fvJrUL5g5tnGwER; Secure; Path=/; HttpOnly
```

The same can be used for `favicon.ico`, `manifest.json`, `.well-known`, and API endpoints whose URLs cannot be changed using cache busting.

Most web content can be covered by a combination of the two patterns described above.

### More about managed caches

With the method described in previous sections, subresources can be cached for a long time by using cache busting, but main resources (which are usually HTML documents) can't be.

Caching main resources is difficult because, using just standard directives from the HTTP Caching specification, there's no way to actively delete cache contents when content is updated on the server.

However, it is possible by deploying a managed cache such as a CDN or service worker.

For example, a CDN that allows cache purging via an API or dashboard operation would allow for a more aggressive caching strategy by storing the main resource and explicitly purging the relevant cache only when an update occurs on the server.

A service worker could do the same if it could delete the contents in the Cache API when an update occurs on the server.

For more information, see the documentation for your CDN, and consult the service worker documentation.

See also
--------

* RFC 9111: Hypertext Transfer Protocol (HTTP/1.1): Caching
* Caching Tutorial - Mark Nottingham


HTTP conditional requests - HTTP

HTTP conditional requests
=========================

HTTP has a concept of *conditional requests*, where the result, and even the success of a request, can be changed by comparing the affected resources with the value of a *validator*. Such requests can be useful to validate the content of a cache, and sparing a useless control, to verify the integrity of a document, like when resuming a download, or when preventing lost updates when uploading or modifying a document on the server.

Principles
----------

HTTP conditional requests are requests that are executed differently, depending on the value of specific headers. These headers define a precondition, and the result of the request will be different if the precondition is matched or not.

The different behaviors are defined by the method of the request used, and by the set of headers used for a precondition:

* for safe methods, like `GET`, which usually tries to fetch a document, the conditional request can be used to send back the document, if relevant only. Therefore, this spares bandwidth.
* for unsafe methods, like `PUT`, which usually uploads a document, the conditional request can be used to upload the document, only if the original it is based on is the same as that stored on the server.
Validators
----------

All conditional headers try to check if the resource stored on the server matches a specific version. To achieve this, the conditional requests need to indicate the version of the resource. As comparing the whole resource byte to byte is impracticable, and not always what is wanted, the request transmits a value describing the version. Such values are called *validators*, and are of two kinds:

* the date of last modification of the document, the *last-modified* date.
* an opaque string, uniquely identifying each version, called the *entity tag*, or the *etag*.

Comparing versions of the same resource is a bit tricky: depending on the context, there are two kinds of *equality checks*:

* *Strong validation* is used when byte to byte identity is expected, for example when resuming a download.
* *Weak validation* is used when the user-agent only needs to determine if two resources have the same content. The resources may be considered the same even if minor differences exist, such as different ads or a footer with a different date.

The kind of validation is independent of the validator used. Both `Last-Modified` and `ETag` allow both types of validation, though the complexity to implement it on the server side may vary. HTTP uses strong validation by default, and it specifies when weak validation can be used.

### Strong validation

Strong validation consists of guaranteeing that the resource is, byte to byte, identical to the one it is compared to. This is mandatory for some conditional headers, and the default for the others. Strong validation is very strict and may be difficult to guarantee at the server level, but it does guarantee no data loss at any time, sometimes at the expense of performance.

It is quite difficult to have a unique identifier for strong validation with `Last-Modified`. Often this is done using an `ETag` with the MD5 hash of the resource (or a derivative).

### Weak validation

Weak validation differs from strong validation, as it considers two versions of the document as identical if the content is equivalent. For example, a page that would differ from another only by a different date in its footer, or different advertising, would be considered *identical* to the other with weak validation. These same two versions are considered *different* when using strong validation. Building a system of etags that creates weak validation may be complex, as it involves knowing the importance of the different elements of a page, but is very useful towards optimizing cache performance.

Conditional headers
-------------------

Several HTTP headers, called conditional headers, lead to conditional requests. These are:

`If-Match`

Succeeds if the `ETag` of the distant resource is equal to one listed in this header. It performs a strong validation.

`If-None-Match`

Succeeds if the `ETag` of the distant resource is different to each listed in this header. It performs a weak validation.

`If-Modified-Since`

Succeeds if the `Last-Modified` date of the distant resource is more recent than the one given in this header.

`If-Unmodified-Since`

Succeeds if the `Last-Modified` date of the distant resource is older or the same as the one given in this header.

`If-Range`

Similar to `If-Match`, or `If-Unmodified-Since`, but can have only one single etag, or one date. If it fails, the range request fails, and instead of a `206` `Partial Content` response, a `200` `OK` is sent with the complete resource.

Use cases
---------

### Cache update

The most common use case for conditional requests is updating a cache. With an empty cache, or without a cache, the requested resource is sent back with a status of `200` `OK`.

![The request issued when the cache is empty triggers the resource to be downloaded, with both validator values sent as headers. The cache is then filled.](/en-US/docs/Web/HTTP/Conditional_requests/cache1.png)

Together with the resource, the validators are sent in the headers. In this example, both `Last-Modified` and `ETag` are sent, but it could equally have been only one of them. These validators are cached with the resource (like all headers) and will be used to craft conditional requests, once the cache becomes stale.

As long as the cache is not stale, no requests are issued at all. But once it has become stale, this is mostly controlled by the `Cache-Control` header, the client doesn't use the cached value directly but issues a *conditional request*. The value of the validator is used as a parameter of the `If-Modified-Since` and `If-None-Match` headers.

If the resource has not changed, the server sends back a `304` `Not Modified` response. This makes the cache fresh again, and the client uses the cached resource. Although there is a response/request round-trip that consumes some resources, this is more efficient than to transmit the whole resource over the wire again.

![With a stale cache, the conditional request is sent. The server can determine if the resource changed, and, as in this case, decide not to send it again as it is the same.](/en-US/docs/Web/HTTP/Conditional_requests/httpcache2.png)

 If the resource has changed, the server just sends back a `200 OK` response, with the new version of the resource (as though the request wasn't conditional).
 The client uses this new resource (and caches it).

![In the case where the resource was changed, it is sent back as if the request wasn't conditional.](/en-US/docs/Web/HTTP/Conditional_requests/httpcache3.png)

Besides the setting of the validators on the server side, this mechanism is transparent: all browsers manage a cache and send such conditional requests without any special work to be done by Web developers.

### Integrity of a partial download

Partial downloading of files is a functionality of HTTP that allows resuming previous operations, saving bandwidth and time, by keeping the already obtained information:

![A download has been stopped and only partial content has been retrieved.](/en-US/docs/Web/HTTP/Conditional_requests/httpresume1.png)

A server supporting partial downloads broadcasts this by sending the `Accept-Ranges` header. Once this happens, the client can resume a download by sending a `Ranges` header with the missing ranges:

![The client resumes the requests by indicating the range he needs and preconditions checking the validators of the partially obtained request.](/en-US/docs/Web/HTTP/Conditional_requests/httpresume2.png)

The principle is simple, but there is one potential problem: if the downloaded resource has been modified between both downloads, the obtained ranges will correspond to two different versions of the resource, and the final document will be corrupted.

To prevent this, conditional requests are used. For ranges, there are two ways of doing this. The more flexible one makes use of `If-Unmodified-Since` and `If-Match` and the server returns an error if the precondition fails; the client then restarts the download from the beginning:

![When the partially downloaded resource has been modified, the preconditions will fail and the resource will have to be downloaded again completely.](/en-US/docs/Web/HTTP/Conditional_requests/httpresume3.png)

Even if this method works, it adds an extra response/request exchange when the document has been changed. This impairs performance, and HTTP has a specific header to avoid this scenario: `If-Range`:

![The If-Range headers allows the server to directly send back the complete resource if it has been modified, no need to send a 412 error and wait for the client to re-initiate the download.](/en-US/docs/Web/HTTP/Conditional_requests/httpresume4.png)

This solution is more efficient, but slightly less flexible, as only one etag can be used in the condition. Rarely is such additional flexibility needed.

### Avoiding the lost update problem with optimistic locking

A common operation in Web applications is to *update* a remote document. This is very common in any file system or source control applications, but any application that allows to store remote resources needs such a mechanism. Common websites, like wikis and other CMS, have such a need.

With the `PUT` method you are able to implement this. The client first reads the original files, modifies them, and finally pushes them to the server:

![Updating a file with a PUT is very simple when concurrency is not involved.](/en-US/docs/Web/HTTP/Conditional_requests/httplock1.png)

Unfortunately, things get a little inaccurate as soon as we take into account concurrency. While a client is locally modifying its new copy of the resource, a second client can fetch the same resource and do the same on its copy. What happens next is very unfortunate: when they commit back to the server, the modifications from the first client are discarded by the next client push, as this second client is unaware of the first client's changes to the resource. The decision on who wins is not communicated to the other party. Which client's changes are to be kept, will vary with the speed they commit; this depends on the performance of the clients, of the server, and even of the human editing the document at the client. The winner will change from one time to the next. This is a *race condition* and leads to problematic behaviors, which are difficult to detect and to debug:

![When several clients update the same resource in parallel, we are facing a race condition: the slowest win, and the others don't even know they lost. Problematic!](/en-US/docs/Web/HTTP/Conditional_requests/httplock2.png)

There is no way to deal with this problem without annoying one of the two clients. However, lost updates and race conditions are to be avoided. We want predictable results, and expect that the clients are notified when their changes are rejected.

Conditional requests allow implementing the *optimistic locking algorithm* (used by most wikis or source control systems). The concept is to allow all clients to get copies of the resource, then let them modify it locally, controlling concurrency by successfully allowing the first client to submit an update. All subsequent updates, based on the now obsolete version of the resource, are rejected:

![Conditional requests allow to implement optimistic locking: now the quickest wins, and the others get an error.](/en-US/docs/Web/HTTP/Conditional_requests/httplock3.png)

This is implemented using the `If-Match` or `If-Unmodified-Since` headers. If the etag doesn't match the original file, or if the file has been modified since it has been obtained, the change is rejected with a `412` `Precondition Failed` error. It is then up to the client to deal with the error: either by notifying the user to start again (this time on the newest version), or by showing the user a *diff* of both versions, helping them decide which changes they wish to keep.

### Dealing with the first upload of a resource

The first upload of a resource is an edge case of the previous. Like any update of a resource, it is subject to a race condition if two clients try to perform at similar times. To prevent this, conditional requests can be used: by adding `If-None-Match` with the special value of `'*'`, representing any etag. The request will succeed, only if the resource didn't exist before:

![Like for a regular upload, the first upload of a resource is subject to a race condition: If-None-Match can prevent it.](/en-US/docs/Web/HTTP/Conditional_requests/httpfirst.png)

`If-None-Match` will only work with HTTP/1.1 (and later) compliant servers. If unsure if the server will be compliant, you need first to issue a `HEAD` request to the resource to check this.

Conclusion
----------

Conditional requests are a key feature of HTTP, and allow the building of efficient and complex applications. For caching or resuming downloads, the only work required for webmasters is to configure the server correctly; setting correct etags in some environments can be tricky. Once achieved, the browser will serve the expected conditional requests.

For locking mechanisms, it is the opposite: Web developers need to issue a request with the proper headers, while webmasters can mostly rely on the application to carry out the checks for them.

In both cases it's clear, conditional requests are a fundamental feature behind the Web.


Compression in HTTP - HTTP

Compression in HTTP
===================

**Compression** is an important way to increase the performance of a website. For some documents, size reduction of up to 70% lowers the bandwidth capacity needs. Over the years, algorithms also got more efficient, and new ones are supported by clients and servers.

In practice, web developers don't need to implement compression mechanisms, both browsers and servers have it implemented already, but they have to be sure that the server is configured adequately. Compression happens at three different levels:

* first some file formats are compressed with specific optimized methods,
* then general encryption can happen at the HTTP level (the resource is transmitted compressed from end to end),
* and finally compression can be defined at the connection level, between two nodes of an HTTP connection.
File format compression
-----------------------

Each data type has some redundancy, that is *wasted space*, in it. If text can typically have as much as 60% redundancy, this rate can be much higher for some other media like audio and video. Unlike text, these other media types use a lot of space to store their data and the need to optimize storage and regain space was apparent very early. Engineers designed the optimized compression algorithm used by file formats designed for this specific purpose. Compression algorithms used for files can be grouped into two broad categories:

* *Loss-less compression*, where the compression-uncompression cycle doesn't alter the data that is recovered. It matches (byte to byte) with the original.
 For images, `gif` or `png` are using lossless compression.
* *Lossy compression*, where the cycle alters the original data in a (hopefully) imperceptible way for the user.
 Video formats on the Web are lossy; the `jpeg` image format is also lossy.

Some formats can be used for both loss-less or lossy compression, like `webp`, and usually lossy algorithm can be configured to compress more or less, which then of course leads to less or more quality. For better performance of a website, it is ideal to compress as much as possible, while keeping an acceptable level of quality. For images, an image generated by a tool could be not optimized enough for the Web; it is recommended to use tools that will compress as much as possible with the required quality. There are numerous tools that are specialized for this.

Lossy compression algorithms are usually more efficient than loss-less ones.

**Note:** As compression works better on a specific kind of files, it usually provides nothing to compress them a second time. In fact, this is often counterproductive as the cost of the overhead (algorithms usually need a dictionary that adds to the initial size) can be higher than the extra gain in compression resulting in a larger file. Do not use the two following techniques for files in a compressed format.

End-to-end compression
----------------------

For compression, end-to-end compression is where the largest performance improvements of websites reside. End-to-end compression refers to a compression of the body of a message that is done by the server and will last unchanged until it reaches the client. Whatever the intermediate nodes are, they leave the body untouched.

![A server sending a compressed HTTP body to a client via network nodes. The body is not decompressed at any hop through the network until it reaches the client.](/en-US/docs/Web/HTTP/Compression/httpenco1.png)

All modern browsers and servers do support it and the only thing to negotiate is the compression algorithm to use. These algorithms are optimized for text. In the 1990s, compression technology was advancing at a rapid pace and numerous successive algorithms have been added to the set of possible choices. Nowadays, only two are relevant: `gzip`, the most common one, and `br` the new challenger.

To select the algorithm to use, browsers and servers use proactive content negotiation. The browser sends an `Accept-Encoding` header with the algorithm it supports and its order of precedence, the server picks one, uses it to compress the body of the response and uses the `Content-Encoding` header to tell the browser the algorithm it has chosen. As content negotiation has been used to choose a representation based on its encoding, the server must send a `Vary` header containing at least `Accept-Encoding` alongside this header in the response; that way, caches will be able to cache the different representations of the resource.

![A client requesting content with an 'Accept-Encoding: br, gzip' header. The server responds with a body compressed using the Brotli algorithm and the required 'Content-Encoding' and 'Vary' headers.](/en-US/docs/Web/HTTP/Compression/httpcompression1.png)

As compression brings significant performance improvements, it is recommended to activate it for all files, but already compressed ones like images, audio files and videos.

Apache supports compression and uses mod\_deflate; for Nginx there is ngx\_http\_gzip\_module; for IIS, the `<httpCompression>` element.

Hop-by-hop compression
----------------------

Hop-by-hop compression, though similar to end-to-end compression, differs by one fundamental element: the compression doesn't happen on the resource in the server, creating a specific representation that is then transmitted, but on the body of the message between any two nodes on the path between the client and the server. Connections between successive intermediate nodes may apply a *different* compression.

![A server sending an uncompressed HTTP body to a client via network nodes. The body is compressed and decompressed by nodes on the network depending on 'Transfer-Encoding' headers before it reaches the client.](/en-US/docs/Web/HTTP/Compression/httpte1.png)

To do this, HTTP uses a mechanism similar to the content negotiation for end-to-end compression: the node transmitting the request advertizes its will using the `TE` header and the other node chooses the adequate method, applies it, and indicates its choice with the `Transfer-Encoding` header.

![A client requesting content from a server with no compression-related headers. The server responds with an uncompressed body. The body is compressed and decompressed by nodes on the network before it reaches the client.](/en-US/docs/Web/HTTP/Compression/httpcomp2.png)

In practice, hop-by-hop compression is transparent for the server and the client, and is rarely used. `TE` and `Transfer-Encoding` are mostly used to send a response by chunks, allowing to start transmitting a resource without knowing its length.

Note that using `Transfer-Encoding` and compression at the hop level is so rare that most servers, like Apache, Nginx, or IIS, have no easy way to configure it. Such configuration usually happens at the proxy level.


Protocol upgrade mechanism - HTTP

Protocol upgrade mechanism
==========================

The HTTP/1.1 protocol provides a special mechanism that can be used to upgrade an already established connection to a different protocol, using the `Upgrade` header field.

This mechanism is optional; it cannot be used to insist on a protocol change. Implementations can choose not to take advantage of an upgrade even if they support the new protocol, and in practice, this mechanism is used mostly to bootstrap a WebSockets connection.

Note also that HTTP/2 explicitly disallows the use of this mechanism; it is specific to HTTP/1.1.

Upgrading HTTP/1.1 Connections
------------------------------

The `Upgrade` header field is used by clients to invite the server to switch to one of the listed protocols, in descending preference order.

Because `Upgrade` is a hop-by-hop header, it also needs to be listed in the `Connection` header field. This means that a typical request that includes Upgrade would look something like:

```http
GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: example/1, foo/2
```

Other headers may be required depending on the requested protocol; for example, WebSocket upgrades allow additional headers to configure details about the WebSocket connection as well as to offer a degree of security in opening the connection. See Upgrading to a WebSocket connection for more details.

If the server decides to upgrade the connection, it sends back a `101 Switching Protocols` response status with an Upgrade header that specifies the protocol(s) being switched to. If it does not (or cannot) upgrade the connection, it ignores the `Upgrade` header and sends back a regular response (for example, a `200 OK`).

Right after sending the `101` status code, the server can begin speaking the new protocol, performing any additional protocol-specific handshakes as necessary. Effectively, the connection becomes a two-way pipe as soon as the upgraded response is complete, and the request that initiated the upgrade can be completed over the new protocol.

Common uses for this mechanism
------------------------------

Here we look at the most common use cases for the `Upgrade` header.

### Upgrading to a WebSocket connection

By far, the most common use case for upgrading an HTTP connection is to use WebSockets, which are always implemented by upgrading an HTTP or HTTPS connection. Keep in mind that if you're opening a new connection using the WebSocket API, or any library that does WebSockets, most or all of this is done for you. For example, opening a WebSocket connection is as simple as:

```js
webSocket = new WebSocket("ws://destination.server.ext", "optionalProtocol");
```

The `WebSocket()` constructor does all the work of creating an initial HTTP/1.1 connection then handling the handshaking and upgrade process for you.

**Note:** You can also use the `"wss://"` URL scheme to open a secure WebSocket connection.

If you need to create a WebSocket connection from scratch, you'll have to handle the handshaking process yourself. After creating the initial HTTP/1.1 session, you need to request the upgrade by adding to a standard request the `Upgrade` and `Connection` headers, as follows:

```http
Connection: Upgrade
Upgrade: websocket
```

### WebSocket-specific headers

The following headers are involved in the WebSocket upgrade process. Other than the `Upgrade` and `Connection` headers, the rest are generally optional or handled for you by the browser and server when they're talking to each other.

#### `Sec-WebSocket-Extensions`

Specifies one or more protocol-level WebSocket extensions to ask the server to use. Using more than one `Sec-WebSocket-Extension` header in a request is permitted; the result is the same as if you included all of the listed extensions in one such header.

```http
Sec-WebSocket-Extensions: extensions
```

`extensions`

A comma-separated list of extensions to request (or agree to support). These should be selected from the IANA WebSocket Extension Name Registry. Extensions which take parameters do so by using semicolon delineation.

For example:

```http
Sec-WebSocket-Extensions: superspeed, colormode; depth=16
```

#### `Sec-WebSocket-Key`

Provides information to the server which is needed in order to confirm that the client is entitled to request an upgrade to WebSocket. This header can be used when insecure (HTTP) clients wish to upgrade, in order to offer some degree of protection against abuse. The value of the key is computed using an algorithm defined in the WebSocket specification, so this *does not provide security*. Instead, it helps to prevent non-WebSocket clients from inadvertently, or through misuse, requesting a WebSocket connection. In essence, then, this key confirms that "Yes, I really mean to open a WebSocket connection."

This header is automatically added by clients that choose to use it; it cannot be added using the `fetch()` or `XMLHttpRequest.setRequestHeader()` methods.

```http
Sec-WebSocket-Key: key
```

`key`

The key for this request to upgrade. The client adds this if it wishes to do so, and the server will include in the response a key of its own, which the client will validate before delivering the upgrade response to you.

The server's response's `Sec-WebSocket-Accept` header will have a value computed based upon the specified `key`.

#### `Sec-WebSocket-Protocol`

The `Sec-WebSocket-Protocol` header specifies one or more WebSocket protocols that you wish to use, in order of preference. The first one that is supported by the server will be selected and returned by the server in a `Sec-WebSocket-Protocol` header included in the response. You can use this more than once in the header, as well; the result is the same as if you used a comma-delineated list of subprotocol identifiers in a single header.

```http
Sec-WebSocket-Protocol: subprotocols
```

`subprotocols`

A comma-separated list of subprotocol names, in the order of preference. The subprotocols may be selected from the IANA WebSocket Subprotocol Name Registry or may be a custom name jointly understood by the client and the server.

#### `Sec-WebSocket-Version`

##### Request header

Specifies the WebSocket protocol version the client wishes to use, so the server can confirm whether or not that version is supported on its end.

```http
Sec-WebSocket-Version: version
```

`version`

The WebSocket protocol version the client wishes to use when communicating with the server. This number should be the most recent version possible listed in the IANA WebSocket Version Number Registry. The most recent final version of the WebSocket protocol is version 13.

##### Response header

If the server can't communicate using the specified version of the WebSocket protocol, it will respond with an error (such as 426 Upgrade Required) that includes in its headers a `Sec-WebSocket-Version` header with a comma-separated list of the supported protocol versions. If the server does support the requested protocol version, no `Sec-WebSocket-Version` header is included in the response.

```http
Sec-WebSocket-Version: supportedVersions
```

`supportedVersions`

A comma-delineated list of the WebSocket protocol versions supported by the server.

### Response-only headers

The response from the server may include these.

#### `Sec-WebSocket-Accept`

Included in the response message from the server during the opening handshake process when the server is willing to initiate a WebSocket connection. It will appear no more than once in the response headers.

```http
Sec-WebSocket-Accept: hash
```

`hash`

If a `Sec-WebSocket-Key` header was provided, the value of this header is computed by taking the value of the key, concatenating the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" to it, taking the SHA-1 hash of that concatenated string, resulting in a 20-byte value. That value is then base64 encoded to obtain the value of this property.

References
----------

* WebSocket API
* HTTP
* Specifications and RFCs:
    + RFC 7230
    + RFC 6455
    + RFC 7540


A typical HTTP session - HTTP

A typical HTTP session
======================

In client-server protocols, like HTTP, sessions consist of three phases:

1. The client establishes a TCP connection (or the appropriate connection if the transport layer is not TCP).
2. The client sends its request, and waits for the answer.
3. The server processes the request, sending back its answer, providing a status code and appropriate data.

As of HTTP/1.1, the connection is no longer closed after completing the third phase, and the client is now granted a further request: this means the second and third phases can now be performed any number of times.

Establishing a connection
-------------------------

In client-server protocols, it is the client which establishes the connection. Opening a connection in HTTP means initiating a connection in the underlying transport layer, usually this is TCP.

With TCP the default port, for an HTTP server on a computer, is port 80. Other ports can also be used, like 8000 or 8080. The URL of a page to fetch contains both the domain name, and the port number, though the latter can be omitted if it is 80. See Identifying resources on the Web for more details.

**Note:** The client-server model does not allow the server to send data to the client without an explicit request for it. However, various Web APIs enable this use case, including the Push API, Server-sent events, and the WebSockets API.

Sending a client request
------------------------

Once the connection is established, the user-agent can send the request (a user-agent is typically a web browser, but can be anything else, a crawler, for example). A client request consists of text directives, separated by CRLF (carriage return, followed by line feed), divided into three blocks:

1. The first line contains a request method followed by its parameters:
    * the path of the document, as an absolute URL without the protocol or domain name
    * the HTTP protocol version
2. Subsequent lines represent an HTTP header, giving the server information about what type of data is appropriate (for example, what language, what MIME types), or other data altering its behavior (for example, not sending an answer if it is already cached). These HTTP headers form a block which ends with an empty line.
3. The final block is an optional data block, which may contain further data mainly used by the POST method.
### Example requests

Fetching the root page of developer.mozilla.org, (`https://developer.mozilla.org/`), and telling the server that the user-agent would prefer the page in French, if possible:

```http
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

Observe that final empty line, this separates the data block from the header block. As there is no `Content-Length` provided in an HTTP header, this data block is presented empty, marking the end of the headers, allowing the server to process the request the moment it receives this empty line.

For example, sending the result of a form:

```http
POST /contact\_form.php HTTP/1.1
Host: developer.mozilla.org
Content-Length: 64
Content-Type: application/x-www-form-urlencoded

name=Joe%20User&request=Send%20me%20one%20of%20your%20catalogue
```

### Request methods

HTTP defines a set of request methods indicating the desired action to be performed upon a resource. Although they can also be nouns, these requests methods are sometimes referred as HTTP verbs. The most common requests are `GET` and `POST`:

* The `GET` method requests a data representation of the specified resource. Requests using `GET` should only retrieve data.
* The `POST` method sends data to a server so it may change its state. This is the method often used for HTML Forms.
Structure of a server response
------------------------------

After the connected agent has sent its request, the web server processes it, and ultimately returns a response. Similar to a client request, a server response is formed of text directives, separated by CRLF, though divided into three blocks:

1. The first line, the *status line*, consists of an acknowledgment of the HTTP version used, followed by a response status code (and its brief meaning in human-readable text).
2. Subsequent lines represent specific HTTP headers, giving the client information about the data sent (for example, type, data size, compression algorithm used, hints about caching). Similarly to the block of HTTP headers for a client request, these HTTP headers form a block ending with an empty line.
3. The final block is a data block, which contains the optional data.
### Example responses

Successful web page response:

```http
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 55743
Connection: keep-alive
Cache-Control: s-maxage=300, public, max-age=0
Content-Language: en-US
Date: Thu, 06 Dec 2018 17:37:18 GMT
ETag: "2e77ad1dc6ab0b53a2996dfd4653c1c3"
Server: meinheld/0.6.1
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
Age: 7

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>A simple webpage</title>
</head>
<body>
  <h1>Simple HTML webpage</h1>
  <p>Hello, world!</p>
</body>
</html>
```

Notification that the requested resource has permanently moved:

```http
HTTP/1.1 301 Moved Permanently
Server: Apache/2.4.37 (Red Hat)
Content-Type: text/html; charset=utf-8
Date: Thu, 06 Dec 2018 17:33:08 GMT
Location: https://developer.mozilla.org/ (this is the new link to the resource; it is expected that the user-agent will fetch it)
Keep-Alive: timeout=15, max=98
Accept-Ranges: bytes
Via: Moz-Cache-zlb05
Connection: Keep-Alive
Content-Length: 325 (the content contains a default page to display if the user-agent is not able to follow the link)

<!DOCTYPE html>… (contains a site-customized page helping the user to find the missing resource)
```

Notification that the requested resource doesn't exist:

```http
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Content-Length: 38217
Connection: keep-alive
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Content-Language: en-US
Date: Thu, 06 Dec 2018 17:35:13 GMT
Expires: Thu, 06 Dec 2018 17:35:13 GMT
Server: meinheld/0.6.1
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
X-Cache: Error from cloudfront

<!DOCTYPE html>… (contains a site-customized page helping the user to find the missing resource)
```

### Response status codes

HTTP response status codes indicate if a specific HTTP request has been successfully completed. Responses are grouped into five classes: informational responses, successful responses, redirects, client errors, and server errors.

* `200`: OK. The request has succeeded.
* `301`: Moved Permanently. This response code means that the URI of requested resource has been changed.
* `404`: Not Found. The server cannot find the requested resource.
See also
--------

* Identifying resources on the Web
* HTTP headers
* HTTP request methods
* HTTP response status codes


HTTP Messages - HTTP

HTTP Messages
=============

HTTP messages are how data is exchanged between a server and a client. There are two types of messages: *requests* sent by the client to trigger an action on the server, and *responses*, the answer from the server.

HTTP messages are composed of textual information encoded in ASCII, and span over multiple lines. In HTTP/1.1, and earlier versions of the protocol, these messages were openly sent across the connection. In HTTP/2, the once human-readable message is now divided up into HTTP frames, providing optimization and performance improvements.

Web developers, or webmasters, rarely craft these textual HTTP messages themselves: software, a Web browser, proxy, or Web server, perform this action. They provide HTTP messages through config files (for proxies or servers), APIs (for browsers), or other interfaces.

![From a user-, script-, or server- generated event, an HTTP/1.x msg is generated, and if HTTP/2 is in use, it is binary framed into an HTTP/2 stream, then sent.](/en-US/docs/Web/HTTP/Messages/httpmsg2.png)

HTTP requests, and responses, share similar structure and are composed of:

1. A *start-line* describing the requests to be implemented, or its status of whether successful or a failure. This is always a single line.
2. An optional set of *HTTP headers* specifying the request, or describing the body included in the message.
3. A blank line indicating all meta-information for the request has been sent.
4. An optional *body* containing data associated with the request (like content of an HTML form), or the document associated with a response. The presence of the body and its size is specified by the start-line and HTTP headers.

The start-line and HTTP headers of the HTTP message are collectively known as the *head* of the requests, whereas its payload is known as the *body*.

![Requests and responses share a common structure in HTTP](/en-US/docs/Web/HTTP/Messages/httpmsgstructure2.png)

HTTP Requests
-------------

### Request line

*Note: The start-line is called the "request-line" in requests.*

HTTP requests are messages sent by the client to initiate an action on the server. Their *request-line* contain three elements:

1. An *HTTP method*, a verb (like `GET`, `PUT` or `POST`) or a noun (like `HEAD` or `OPTIONS`), that describes the action to be performed. For example, `GET` indicates that a resource should be fetched or `POST` means that data is pushed to the server (creating or modifying a resource, or generating a temporary document to send back).
2. The *request target*, usually a URL, or the absolute path of the protocol, port, and domain are usually characterized by the request context. The format of this request target varies between different HTTP methods. It can be
    * An absolute path, ultimately followed by a `'?'` and query string. This is the most common form, known as the *origin form*, and is used with `GET`, `POST`, `HEAD`, and `OPTIONS` methods.
        + `POST / HTTP/1.1`
        + `GET /background.png HTTP/1.0`
        + `HEAD /test.html?query=alibaba HTTP/1.1`
        + `OPTIONS /anypage.html HTTP/1.0`
    * A complete URL, known as the *absolute form*, is mostly used with `GET` when connected to a proxy.
     `GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1`
    * The authority component of a URL, consisting of the domain name and optionally the port (prefixed by a `':'`), is called the *authority form*. It is only used with `CONNECT` when setting up an HTTP tunnel.
     `CONNECT developer.mozilla.org:80 HTTP/1.1`
    * The *asterisk form*, a simple asterisk (`'*'`) is used with `OPTIONS`, representing the server as a whole.
     `OPTIONS * HTTP/1.1`
3. The *HTTP version*, which defines the structure of the remaining message, acting as an indicator of the expected version to use for the response.
### Headers

HTTP headers from a request follow the same basic structure of an HTTP header: a case-insensitive string followed by a colon (`':'`) and a value whose structure depends upon the header. The whole header, including the value, consists of one single line, which can be quite long.

Many different headers can appear in requests. They can be divided in several groups:

* General headers, like `Via`, apply to the message as a whole.
* Request headers, like `User-Agent` or `Accept`, modify the request by specifying it further (like `Accept-Language`), by giving context (like `Referer`), or by conditionally restricting it (like `If-None-Match`).
* Representation headers like `Content-Type` that describe the original format of the message data and any encoding applied (only present if the message has a body).

![Example of headers in an HTTP request](/en-US/docs/Web/HTTP/Messages/http_request_headers3.png)

### Body

The final part of the request is its body. Not all requests have one: requests fetching resources like `GET` or `HEAD` usually don't need a body. Requests that send data to the server to create a resource, such as `PUT` or `POST` requests, typically require a body with the data used to fulfill the request (for instance, HTML form data).

Bodies can be broadly divided into two categories:

* Single-resource bodies, consisting of one single file, defined by the two headers: `Content-Type` and `Content-Length`.
* Multiple-resource bodies, consisting of a multipart body, each containing a different bit of information. This is typically associated with HTML Forms.
HTTP Responses
--------------

### Status line

*Note: The start-line is called the "status line" in requests.*

The start line of an HTTP response, called the *status line*, contains the following information:

1. The *protocol version*, usually `HTTP/1.1`, but can also be `HTTP/1.0`.
2. A *status code*, indicating success or failure of the request. Common status codes are `200`, `404`, or `302`.
3. A *status text*. A brief, purely informational, textual description of the status code to help a human understand the HTTP message.

A typical status line looks like: `HTTP/1.1 404 Not Found`.

### Headers

HTTP headers for responses follow the same structure as any other header: a case-insensitive string followed by a colon (`':'`) and a value whose structure depends upon the type of the header. The whole header, including its value, presents as a single line.

Many different headers can appear in responses. These can be divided into several groups:

* General headers, like `Via`, apply to the whole message.
* Response headers, like `Vary` and `Accept-Ranges`, give additional information about the server which doesn't fit in the status line.
* Representation headers like `Content-Type` that describe the original format of the message data and any encoding applied (only present if the message has a body).

![Example of headers in an HTTP response](/en-US/docs/Web/HTTP/Messages/http_response_headers3.png)

### Body

The last part of a response is the body. Not all responses have one: responses with a status code that sufficiently answers the request without the need for corresponding payload (like `201` **`Created`** or `204` **`No Content`**) usually don't.

Bodies can be broadly divided into three categories:

* Single-resource bodies, consisting of a single file of known length, defined by the two headers: `Content-Type` and `Content-Length`.
* Single-resource bodies, consisting of a single file of unknown length, encoded by chunks with `Transfer-Encoding` set to `chunked`.
* Multiple-resource bodies, consisting of a multipart body, each containing a different section of information. These are relatively rare.
HTTP/2 Frames
-------------

HTTP/1.x messages have a few drawbacks for performance:

* Headers, unlike bodies, are uncompressed.
* Headers are often very similar from one message to the next one, yet still repeated across connections.
* Although HTTP/1.1 has pipelining, it's not activated by default in most browsers, and doesn't allow for multiplexing (i.e. sending requests concurrently). Several connections need opening on the same server to send requests concurrently; and warm TCP connections are more efficient than cold ones.

HTTP/2 introduces an extra step: it divides HTTP/1.x messages into frames which are embedded in a stream. Data and header frames are separated, which allows header compression. Several streams can be combined together, a process called *multiplexing*, allowing more efficient use of underlying TCP connections.

![HTTP/2 modifies the HTTP message to divide them in frames (part of a single stream), allowing for more optimization.](/en-US/docs/Web/HTTP/Messages/binary_framing2.png)

HTTP frames are now transparent to Web developers. This is an additional step in HTTP/2, between HTTP/1.1 messages and the underlying transport protocol. No changes are needed in the APIs used by Web developers to utilize HTTP frames; when available in both the browser and the server, HTTP/2 is switched on and used.

Conclusion
----------

HTTP messages are the key in using HTTP; their structure is simple, and they are highly extensible. The HTTP/2 framing mechanism adds a new intermediate layer between the HTTP/1.x syntax and the underlying transport protocol, without fundamentally modifying it: building upon proven mechanisms.