Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

De-XHRify HTTP: everything except CORS #31013

Merged
merged 6 commits into from
Dec 16, 2023
Next Next commit
De-XHRify HTTP: everything except CORS
  • Loading branch information
wbamberg committed Dec 14, 2023
commit 03e87adb6887cada4add25d86b96ff6d4a20198c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ header's value isn't set to `true` to enable their use.
To fix this problem on the client side, revise the code to not request the use of
credentials.

- If using the [Fetch API](/en-US/docs/Web/API/Fetch_API), make sure
{{domxref("Request.credentials")}} is `"omit"`.
- If the request is being issued using {{domxref("XMLHttpRequest")}}, make sure you're
not setting {{domxref("XMLHttpRequest.withCredentials", "withCredentials")}} to
`true`.
- If using [Server-sent events](/en-US/docs/Web/API/Server-sent_events),
make sure {{domxref("EventSource.withCredentials")}} is `false` (it's the
default value).
- If using the [Fetch API](/en-US/docs/Web/API/Fetch_API), make sure
{{domxref("Request.credentials")}} is `"omit"`.

To eliminate this error by changing the server's configuration, adjust the server's
configuration to set the `Access-Control-Allow-Credentials` header's value to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ The {{Glossary("CORS")}} request was attempted with the credentials flag set, bu

To correct this problem on the client side, ensure that the credentials flag's value is `false` when issuing your CORS request.

- If using the [Fetch API](/en-US/docs/Web/API/Fetch_API), make sure {{domxref("Request.credentials")}} is `"omit"`.
- If the request is being issued using {{domxref("XMLHttpRequest")}}, make sure you're not setting {{domxref("XMLHttpRequest.withCredentials", "withCredentials")}} to `true`.
- If using [Server-sent events](/en-US/docs/Web/API/Server-sent_events), make sure {{domxref("EventSource.withCredentials")}} is `false` (it's the default value).
- If using the [Fetch API](/en-US/docs/Web/API/Fetch_API), make sure {{domxref("Request.credentials")}} is `"omit"`.

If, instead, you need to adjust the server's behavior, you'll need to change the value of `Access-Control-Allow-Origin` to grant access to the origin from which the client is loaded.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Reason: CORS request not HTTP
{{Glossary("CORS")}} requests may only use the HTTP or HTTPS URL scheme, but the URL specified by the request is of a different type.
This often occurs if the URL specifies a local file, using the `file:///` scheme.

To fix this problem, make sure you use HTTPS URLs when issuing requests involving CORS, such as {{domxref("XMLHttpRequest")}}, [Fetch](/en-US/docs/Web/API/Fetch_API) APIs, Web Fonts (`@font-face`), and [WebGL textures](/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL), and XSL stylesheets.
To fix this problem, make sure you use HTTPS URLs when issuing requests involving CORS, such as {{domxref("fetch()")}}, {{domxref("XMLHttpRequest")}}, Web Fonts (`@font-face`), and [WebGL textures](/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL), and XSL stylesheets.

### Loading a local file

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,7 @@ requests are not preflighted. So, if a request is made for a resource with
credentials, and if this header is not returned with the resource, the response is ignored
by the browser and not returned to the web content.

The `Access-Control-Allow-Credentials` header works in conjunction with the
{{domxref("XMLHttpRequest.withCredentials")}} property or with the
`credentials` option in the {{domxref("Request.Request()", "Request()")}}
constructor of the Fetch API. For a CORS request with credentials, for browsers
to expose the response to the frontend JavaScript code, both the server (using the
`Access-Control-Allow-Credentials` header) and the client (by setting the
credentials mode for the XHR, Fetch, or Ajax request) must indicate that they're opting
into including credentials.
The `Access-Control-Allow-Credentials` header works in conjunction with the `credentials` option in the {{domxref("Request.Request()", "Request()")}} constructor of the Fetch API or the {{domxref("XMLHttpRequest.withCredentials")}} property. For a CORS request with credentials, for browsers to expose the response to the frontend JavaScript code, both the server (using the `Access-Control-Allow-Credentials` header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they're opting into including credentials.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also find For a CORS request with credentials, for browsers to expose the response to the frontend JavaScript code, both the server (using the Access-Control-Allow-Credentials header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they're opting into including credentials. a very complicated (but correct) sentence; can we express it differently? I'm afraid it would be too complicated for non-native speakers.

Suggested change
The `Access-Control-Allow-Credentials` header works in conjunction with the `credentials` option in the {{domxref("Request.Request()", "Request()")}} constructor of the Fetch API or the {{domxref("XMLHttpRequest.withCredentials")}} property. For a CORS request with credentials, for browsers to expose the response to the frontend JavaScript code, both the server (using the `Access-Control-Allow-Credentials` header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they're opting into including credentials.
The `Access-Control-Allow-Credentials` header works in conjunction with the `credentials` option in the {{domxref("Request.Request()", "Request()")}} constructor of the Fetch API, or with the {{domxref("XMLHttpRequest.withCredentials")}} property. For a CORS request with credentials, for browsers to expose the response to the frontend JavaScript code, both the server (using the `Access-Control-Allow-Credentials` header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they're opting into including credentials.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair. When I made these changes I didn't pay much attention to the wider semantics. Now I do, I don't think this description is very comprehensible, so I have had a go at rewriting it in 121ec81. Would love a fact check.

Resources: https://stackoverflow.com/questions/24687313/what-exactly-does-the-access-control-allow-credentials-header-do

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular I thought phrases like "the response is ignored by the browser and not returned to the web content" are confusing. As a web developer, what does this look like?


<table class="properties">
<tbody>
Expand Down Expand Up @@ -66,21 +59,21 @@ Allow credentials:
Access-Control-Allow-Credentials: true
```

Using [XHR](/en-US/docs/Web/API/XMLHttpRequest) with credentials:
Using {{domxref("fetch()")}} with credentials:

```js
const xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com/", true);
xhr.withCredentials = true;
xhr.send(null);
fetch(url, {
credentials: "include",
});
```

Using [Fetch](/en-US/docs/Web/API/Fetch_API) with credentials:
Using {{domxref("XMLHttpRequest")}} with credentials:

```js
fetch(url, {
credentials: "include",
});
const xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com/", true);
xhr.withCredentials = true;
xhr.send(null);
```

## Specifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ browser-compat: http.headers.Access-Control-Request-Headers

{{HTTPSidebar}}

The **`Access-Control-Request-Headers`** request header is used by browsers when issuing a {{glossary("preflight request")}} to let the server know which [HTTP headers](/en-US/docs/Web/HTTP/Headers) the client might send when the actual request is made (such as with {{domxref("XMLHttpRequest.setRequestHeader()","setRequestHeader()")}}). The complementary server-side header of {{HTTPHeader("Access-Control-Allow-Headers")}} will answer this browser-side header.
The **`Access-Control-Request-Headers`** request header is used by browsers when issuing a {{glossary("preflight request")}} to let the server know which [HTTP headers](/en-US/docs/Web/HTTP/Headers) the client might send when the actual request is made (such as with {{domxref("fetch()")}} or {{domxref("XMLHttpRequest.setRequestHeader()")}}). The complementary server-side header of {{HTTPHeader("Access-Control-Allow-Headers")}} will answer this browser-side header.

<table class="properties">
<tbody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,4 @@ value2

- [HTML Forms](/en-US/docs/Learn/Forms)
- The {{HTTPHeader("Content-Type")}} defining the boundary of the multipart body.
- The {{domxref("FormData")}} interface used to manipulate form data for use in the {{domxref("XMLHttpRequest")}} API.
- The {{domxref("FormData")}} interface used to prepare form data for use in the {{domxref("fetch()")}} or {{domxref("XMLHttpRequest")}} APIs.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ The following connections are blocked and won't load:
```html
<a ping="https://not-example.com">
<script>
const response = fetch("https://not-example.com/");

const xhr = new XMLHttpRequest();
xhr.open("GET", "https://not-example.com/");
xhr.send();
Expand All @@ -94,12 +96,6 @@ The following connections are blocked and won't load:

{{Compat}}

### Compatibility notes

- Prior to Firefox 23, `xhr-src` was used in place of the
`connect-src` directive and only restricted the use of
{{domxref("XMLHttpRequest")}}.

## See also

- {{HTTPHeader("Content-Security-Policy")}}
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/http/headers/sec-fetch-dest/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Servers should ignore this header if it contains any other value.
- `embed`
- : The destination is embedded content. This might originate from an HTML {{HTMLElement("embed")}} tag.
- `empty`
- : The destination is the empty string. This is used for destinations that do not have their own value. For example `fetch()`, {{domxref("navigator.sendBeacon()")}}, {{domxref("EventSource")}}, {{domxref("XMLHttpRequest")}}, {{domxref("WebSocket")}}, etc.
- : The destination is the empty string. This is used for destinations that do not have their own value. For example: {{domxref("fetch()")}}, {{domxref("navigator.sendBeacon()")}}, {{domxref("EventSource")}}, {{domxref("XMLHttpRequest")}}, {{domxref("WebSocket")}}, etc.
- `font`
- : The destination is a font. This might originate from CSS {{cssxref("@font-face")}}.
- `frame`
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/http/methods/post/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ A `POST` request is typically sent via an [HTML form](/en-US/docs/Learn/Forms) a
- `multipart/form-data`: each value is sent as a block of data ("body part"), with a user agent-defined delimiter ("boundary") separating each part. The keys are given in the `Content-Disposition` header of each part.
- `text/plain`

When the `POST` request is sent via a method other than an HTML form — like via an {{domxref("XMLHttpRequest")}} the body can take any type. As described in the HTTP 1.1 specification, `POST` is designed to allow a uniform method to cover the following functions:
When the `POST` request is sent via a method other than an HTML form, such as a {{domxref("fetch()")}} call, the body can take any type. As described in the HTTP 1.1 specification, `POST` is designed to allow a uniform method to cover the following functions:

- Annotation of existing resources
- Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
Expand Down
3 changes: 1 addition & 2 deletions files/en-us/web/http/overview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ Responses consist of the following elements:

## APIs based on HTTP

The most commonly used API based on HTTP is the {{domxref("XMLHttpRequest")}} API, which can be used to exchange data between a {{Glossary("user agent")}} and a server.
The modern {{domxref("Fetch API")}} provides the same features with a more powerful and flexible feature set.
The most commonly used API based on HTTP is the [Fetch API](/en-US/docs/Web/API/Fetch_API), which can be used to make HTTP requests from JavaScript. The Fetch API replaces the {{domxref("XMLHttpRequest")}} API.

Another API, [server-sent events](/en-US/docs/Web/API/Server-sent_events), is a one-way service that allows a server to send events to the client, using HTTP as a transport mechanism.
Using the {{domxref("EventSource")}} interface, the client opens a connection and establishes event handlers.
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/http/protocol_upgrade_mechanism/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Sec-WebSocket-Extensions: superspeed, colormode; depth=16

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 {{domxref("XMLHttpRequest.setRequestHeader()")}} method.
This header is automatically added by clients that choose to use it; it cannot be added using the {{domxref("fetch()")}} or {{domxref("XMLHttpRequest.setRequestHeader()")}} methods.

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