Re: [whatwg/fetch] redirects and etag/if-none-match (Issue #1770)

Alright, so I've documented some patterns from the three browsers. This is from making subsequent requests to the same URL that always returns an ETag but returns a random response status code.

Below is the behavior of each browser if you make multiple requests to the same URL. I can't believe I'm saying this, but it's easier to describe the existing behavior using (semi-)normative language...

# Chrome
1. Let _etag_ be the browser's stored ETag value. By default, _etag_ is null.
2. Let _sendIfNoneMatchHeaders_ be a boolean flag. By default, it is false.
3. Let _req_ be the HTTP request the browser is going to send.
4. If _sendIfNoneMatchHeaders_ is true and _etag_ is not null, then:
    1. Set the `If-None-Match` headers of _req_ to be _etag_.
5. Send _req_ to the URL.
6. Let _res_ be the HTTP response from _req_.
7. Let _status_ be the HTTP status code from _res_.
8. Let _responseEtag_ be the contents of the `ETag` header from _res_.
9. If _status_ is 200, then:
    1. If _etag_ null, then:
        1. Set _etag_ to be _responseEtag_.
    2. Set _sendIfNoneMatchHeaders_ to true.
10. If _status_ is not 200 or 206, then:
    1. Set _sendIfNoneMatchHeaders_ to true.
11. Rinse and repeat.

So the way Chrome works is that it'll start storing ETags once it gets a 200. And it'll keep sending the ETag as long as it keeps getting 200's or 206's from the same URL. If the "chain gets broken" by a non-200/206, getting another 200 response will allow the browser to continue sending the original ETag.

# Firefox
1. Let _etag_ be the browser's stored ETag value. By default, _etag_ is null.
2. Let _neverSendIfNoneMatchHeadersEverAgain_ be a boolean flag. By default, it is false.
3. Let _req_ be the HTTP request the browser is going to send.
4. If _neverSendIfNoneMatchHeadersEverAgain_ is false and _etag_ is not null, then:
    1. Set the `If-None-Match` headers of _req_ to be _etag_.
5. Send _req_ to the URL.
6. Let _res_ be the HTTP response from _req_.
7. Let _status_ be the HTTP status code from _res_.
8. Let _responseEtag_ be the contents of the `ETag` header from _res_.
9. If _status_ is 2xx and _etag_ is null, then:
    1. Set _etag_ to be _responseEtag_.
10. If _status_ is not 2xx, then:
    1. Set _neverSendIfNoneMatchHeadersEverAgain_ to true.
11. Rinse and repeat.

Firefox seems to stop sending ETags indefinitely as soon as it receives a non-2xx from the server. But otherwise, it will save the ETag from a 2xx response and keep sending the ETag back as long as it has a 2xx response.

# Safari
1. Let _etag_ be the browser's stored ETag value. By default, _etag_ is null.
2. Let _req_ be the HTTP request the browser is going to send.
3. If _etag_ is not null, then:
    1. Set the `If-None-Match` headers of _req_ to be _etag_.
4. Send _req_ to the URL.
5. Let _res_ be the HTTP response from _req_.
6. Let _responseEtag_ be the contents of the `ETag` header from _res_.
7. Let _shouldClearEtag_ to be whether (_etag_ is not null).
8. Set _etag_ to be _responseEtag_.
9. If _shouldClearEtag_, then:
    1. Set _etag_ to null.
10. Rinse and repeat.

Safari is weird. It doesn't care about the response code. Rather, it seems that for every other request, it clears the ETag.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/issues/1770#issuecomment-2346644945
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/fetch/issues/1770/2346644945@github.com>

Received on Thursday, 12 September 2024 15:44:04 UTC