Re: [whatwg/fetch] Discussion: the term for non-preflighted request ("simple request") (Issue #1824)

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