- From: Uku Sõrmus <notifications@github.com>
- Date: Fri, 16 May 2025 05:15:36 -0700
- To: whatwg/fetch <fetch@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/fetch/issues/1824/2886554337@github.com>
ukusormus left a comment (whatwg/fetch#1824)
Should the two opposing terms used to describe the request type span both same-origin and cross-origin scenarios, or be explicitly only bothered with cross-origin scenarios? This changes what the two terms can be that would still be logically coherent.
Example argument for "should span both same-origin and cross-origin scenarios":
1) the Fetch Standard itself spans both scenarios;
2) it may be easier to precisely talk about certain situations, starting first from the action -- request and its type ("simple" / "non-simple") -- and *then* delve into the context -- relations of the request initiator and the request destination (like same-origin / cross-origin, same-site / cross-site)
To illustrate the second point, here's a recent example where I had to describe when are cookies attached to requests. This IMO gets more convoluted (more depth and possible alternatives) when NOT starting first from the request type:
<details>
<summary>Example</summary>
I. Starting first from request type ("simple" / "non-simple"):
```
Cookies are attached to ...
a. "simple" request
a.1. same-site => always
a.2. cross-site => depends on browser settings, SameSite attribute etc.
b. "non-simple" request
b.1. same-origin => yes by default (if not credentials: omit)
b.2. cross-origin => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
```
^ note that using "non-preflighted" and "preflighted" instead of "simple" and "non-simple" wouldn't hold up here, since "preflighted" would be a parent of "same-origin", which can never happen
II.a) Starting first from initiator-destination relation (origin):
```
Cookies are attached to ...
a. same-origin request => yes by default (if not credentials: omit)
b. cross-origin request
b.1. same-site
b.1.1. "simple" => always
b.1.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
b.2. cross-site
b.1.1. "simple" => depends on browser settings, SameSite attribute etc.
b.1.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
```
or alternatively (I think best alternative)
```
a. same-origin request => yes by default (if not credentials: omit)
b. cross-origin request
b.1. "simple"
b.1.1. same-site => always
b.1.2. cross-site => depends on browser settings, SameSite attribute etc.
b.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
```
II.b) Starting first from initiator-destination relation (site):
```
Cookies are attached to ...
a. same-site request
a.1. same-origin => yes by default (if not credentials: omit)
a.2. cross-origin
a.2.1. "simple" => always
a.2.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
b. cross-site requests
b.1. "simple" => depends on browser settings, SameSite attribute etc.
b.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
```
or alternatively
```
Cookies are attached to ...
a. same-site request
a.1. "simple" => always
a.2. "non-simple"
a.2.1. same-origin => yes by default (if not credentials: omit)
a.2.2. cross-origin => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
b. cross-site request
b.1. "simple" => depends on browser settings, SameSite attribute etc.
b.2. "non-simple" => no by default (preflighted; preflight needs to minimally return Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: <origin>)
```
</details>
<details>
<summary>Assumptions</summary>
1. Same-origin requests are *never* preflighted. (Even if we wanted to trigger a [CORS-preflight request](https://fetch.spec.whatwg.org/#cors-preflight-request) manually, by definition, the request requires `Access-Control-Request-Method` which is a [forbidden request header](https://fetch.spec.whatwg.org/#forbidden-request-header))
2. Cross-origin requests *can* be preflighted:
a. they are not preflighted if the request is "simple" (safe methods, safe headers, no event listeners are registered on the object returned by `XMLHttpRequest.upload`, etc.)
b. they are preflighted otherwise ("non-simple" type of request)
</details>
<br>
A table illustrating this possible viewpoint:
| | "simple" / "CORS-safe" | "non-simple" / "CORS-unsafe" |
|--------------------------|---------------------|------------------------|
| **same-origin request** | *never preflighted* | *never preflighted* |
| **cross-origin request** | *never preflighted* | **always preflighted** |
So we can say:
> same-origin requests are never preflighted, whether they are "simple" or "non-simple";
> cross-origin requests are preflighted only if they are "non-simple"
This mental model breaks down if instead of "simple" / "non-simple" ("CORS-safe" / "CORS-unsafe", or anything similar), we use the term pair "non-preflighted" & "preflighted" to mean the same thing, as the table above doesn't hold up anymore:
| | "non-preflighted" | "preflighted" |
|--------------------------|---------------------|------------------------|
| **same-origin request** | *never preflighted* | *never preflighted* (**contradiction!**) |
| **cross-origin request** | *never preflighted* | **always preflighted** |
Contradiction: a same-origin request is never preflighted, but is now categorized under "preflighted" since it is a "non-simple" request. What should we then call a "non-simple" same-origin request if we have made "non-simple" mean "preflighted"?
---
If we believe the two opposing terms should explicitly only bothered with cross-origin scenarios, then "non-preflighted" and "preflighted" are totally fine, as the table becomes just a single row (doesn't even need to be a table):
| | "non-preflighted" | "preflighted" |
|--------------------------|---------------------|------------------------|
| **cross-origin request** | *never preflighted* | *always preflighted* |
For same-origin requests, then, there's no "type" to talk about really. We can only talk about just "same-origin requests", not specifying anything further. This means we have to always specify initiator-destination relation first, then talk about the action and its type.
--
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/issues/1824#issuecomment-2886554337
You are receiving this because you are subscribed to this thread.
Message ID: <whatwg/fetch/issues/1824/2886554337@github.com>
Received on Friday, 16 May 2025 12:15:40 UTC