-
Notifications
You must be signed in to change notification settings - Fork 337
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
redirects and etag/if-none-match #1770
Comments
Just to clarify: Given request reqA that receives a response resA, and resA contains a redirection status code and If it's a stored response from B, I agree that the request should contain a conditional (although it is not required to by HTTP, at least). However, if it's from reqA, that's problematic; ETags obtained from A have nothing to do with B. |
This is the order of operations:
So the question here is whether it's appropriate for subsequent requests to A to contain the header since a previous response had an ETag, even though the status code is a redirect. |
Ah, I see, thanks. |
Okay so if HTTP-network-or-cache fetch step 8.25.1 gives us a non-200 response we should not be pretending we can revalidate. I guess the Chromium code says it makes sense for 206 as well, but isn't a 304 always translated to a 200? |
That's my understanding, at least. (I suppose it's also plausible that the
What does 304 translating to a 200 mean? From what I can tell, a 304 response causes the client to completely ignore the response body. So 304 behavior in practice seems inconsistent among browsers. See https://cr.kungfoo.net/mrpickles/http_cache/res_304_with_200_first.php for a quick demo of 304 and ETag behavior.
|
Does something like MrPickles@92fee8d look to be on the right track? (This is my first time doing web standards stuff.) If so, I can open up a pull request. |
We end up replacing a 304 network response with its stored response (so that a fetch caller almost never sees a 304, unless they control the revalidating headers themselves). We currently don't assert that the stored response has a 200 status code, but I think the HTTP specifications do end up requiring that. Might need to be further clarified as well. @mnot's input on this would be appreciated.
That does look good, modulo whether we should check for "ok status", "200", or "200 or 206". |
There may be additional filtering elsewhere. From observation, the browser doesn't send
Would it reasonable to start with specifying "ok status" and then tightening the spec as we gain more certainty around the intended behavior? Since step 8.25.2 currently specifies no restrictions, I'd imagine we'd want to start with the smallest reasonable "logical spec diff" and incrementally proceed from there. |
Typically for changes to the standard we try to apply "measure twice cut once". As per https://whatwg.org/working-mode#changes we'll also need tests and from those we'd be able to inform ourselves as to what to require and which implementations might need changes. (This isn't always possible, but I think for this change it should be.) |
Ack, sounds good. I did a bit of poking around to see how the different browsers react (demo here). From what I'm seeing, the browser behaviors are inconsistent, and I haven't been able to pattern-match on what they actually do. Let me get back to you on this once I've investigated a bit more and have a more rigorous description of each browser's behavior. |
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
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
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
Safari is weird. It doesn't care about the response code. Rather, it seems that for every other request, it clears the ETag. |
The browser behaviors seem pretty inconsistent, so I'm at a loss for what the proper spec should be. Unless we keep the spec super vague, at least one browser will be violating the spec. How would you recommend proceeding? |
Any opinions? It seems like chrome and firefox are pretty close. We could try to sidebar about it at TPAC. |
I was chatting with @wanderview and it would seem as if what Chrome does makes the most sense (and the spec should generally match Chrome's behavior). Here are some thoughts:
I can draft a PR with the proposed spec changes and write a matching WPT. (But please let me know if the proposed spec or the approach seems unreasonable.) |
Non-200 status codes can be stored and revalidated, and are in practice. Please don't deviate from the HTTP caching spec without good reason - reinventing it causes interop issues with non-browser caches. |
Are any browsers following that spec currently here, though? See the results of testing here: Edit: And we are open to suggestions for a path to interop here. |
I was speaking more in general - e.g., see the link to the cache tests, where browsers do cache non-200 status codes. |
@MrPickles apologies for the late reply, but the general approach sounds reasonable. Mark has a point though that we need to figure out the discrepancies with https://cache-tests.fyi/#status as following HTTP is a goal where that is possible. |
I took a look through the cache tests and spec, and from what I can tell, it doesn't actually seem to conflict with the fetch spec changes. (Note that this isn't any proposal to change any spec, but rather my observations on the existing specs and whether they'd conflict.) If we look at the cache tests, the logic basically goes as follows:
The section of the fetch spec goes over the slightly different logic:
The fetch spec changes discussed in this thread focus more on when the client chooses to send So from what I can tell, tweaking behavior around the fetch spec does not have to conflict with the HTTP cache spec, since the behavior we're looking to adjust is around request headers. This is my understanding after looking around at the specs, so please double check my thought process and correct me if I'm mistaken or missing something. Miscellaneous/tangential observationsTo amend a previous quote:
Also, from what I can tell, the "conditional requests" section of the cache tests (https://cache-tests.fyi/#conditional-inm) cover how the cache should response if The caching spec does bring up a fair point that all response status codes should be cache-able. So checking status code in step |
I initially thought that would go against the specification (as Mark did mention revalidation above, which is what you're talking about), but https://httpwg.org/specs/rfc9111.html#rfc.section.4.3 does suggest to me that revalidation is optional (emphasis mine):
It seems that we could decide that for the web platform that while we can cache all status codes, we're not going to validate all of them as we don't believe that to be useful or web compatible. |
What is the issue with the Fetch Standard?
@MrPickles and I were looking into how redirects and http caching work together recently. We noticed that redirects (301/302) don't seem to send
if-none-match
headers even if the redirect response contains an etag. This behavior seems consistent across chrome, firefox, and safari.Does the spec currently reflect this? I can't seem to find where it defines this restriction. Step 25.2.2.2.1 of http-network-or-cache-fetch doesn't seem to check the status code of the stored response at all. I also don't see it in the http-caching RFC. Am I missing it somewhere or do we need to add this check to the spec?
For reference, I think this is where chromium restricts the status code:
https://source.chromium.org/chromium/chromium/src/+/main:net/http/http_cache_transaction.cc;l=3029;drc=aeeec53b304d068aa96fe84816d1d6c9d96f454e
The text was updated successfully, but these errors were encountered: