客户端导航控件是否应该重新使用旧响应或旧请求?

Should client navigation controls re-use old responses or old requests?

从 1999 年的 HTTP/1.1 RFC 2616,§ 13.13. ‘History Lists’:

13.13 History Lists

User agents often have history mechanisms, such as "Back" buttons and history lists, which can be used to redisplay an entity retrieved earlier in a session.

History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved.

By default, an expiration time does not apply to history mechanisms. If the entity is still in storage, a history mechanism SHOULD display it even if the entity has expired, unless the user has specifically configured the agent to refresh expired history documents.

This is not to be construed to prohibit the history mechanism from telling the user that a view might be stale.

Note: if history list mechanisms unnecessarily prevent users from viewing stale resources, this will tend to force service authors to avoid using HTTP expiration controls and cache controls when they would otherwise like to. Service authors may consider it important that users not be presented with error messages or warning messages when they use navigation controls (such as BACK) to view previously fetched resources. Even though sometimes such resources ought not to cached, or ought to expire quickly, user interface considerations may force service authors to resort to other means of preventing caching (e.g. "once-only" URLs) in order not to suffer the effects of improperly functioning history mechanisms.

来自 2014 年的 HTTP/1.1 RFC 7234,§ 6. ‘History Lists’

6. History Lists

User agents often have history mechanisms, such as "Back" buttons and history lists, that can be used to redisplay a representation retrieved earlier in a session.

The freshness model (Section 4.2) does not necessarily apply to history mechanisms. That is, a history mechanism can display a previous representation even if it has expired.

This does not prohibit the history mechanism from telling the user that a view might be stale or from honoring cache directives (e.g., Cache-Control: no-store).

这是否意味着客户端导航控件应该重新使用旧的 responses 而不是旧的 requests?前者不会通过服务器的新响应触发新的网络交互,而后者会。这意味着客户端的历史应该存储响应而不是请求。

如果是这样,为什么 Web 浏览器有时会重复使用旧请求?例如,在发送带有表单参数的 POST 请求后返回可能会警告用户旧请求即将重新发送(表单重新提交)。

来自 Firefox 开发人员发行说明 ‘Using Firefox 1.5 caching’

Firefox 1.5 uses in-memory caching for entire Web pages, including their JavaScript states, for a single browser session. Going backward and forward between visited pages requires no page loading and the JavaScript states are preserved. This feature, referred to by some as bfcache (for "Back-Forward Cache"), makes page navigation very fast. This caching state is preserved until the user closes the browser.

There are instances in which Firefox doesn’t cache pages. Below are some common programmatic reasons that a page is not cached:

  • the page uses an unload or beforeunload handler;
  • the page sets "cache-control: no-store".
  • the site is HTTPS and page sets at least one of:
    • "Cache-Control: no-cache"
    • "Pragma: no-cache"
    • with "Expires: 0" or "Expires" with a date value in the past relative to the value of the "Date" header (unless "Cache-Control: max-age=" is also specified);
  • the page is not completely loaded when the user navigates away from it or has pending network requests for other reasons (e.g. XMLHttpRequest)); the page has running IndexedDB transactions;
  • the top-level page contains frames (e.g. <iframe>) that are not cacheable for any of the reasons listed here;
  • the page is in a frame and the user loads a new page within that frame (in this case, when the user navigates away from the page, the content that was last loaded into the frames is what is cached).

因此,如 RFC 7234 中所述并在 Firefox 1.5 发行说明中确认,客户端导航控件应重新使用旧响应而不是旧请求,除非在缓存指令中明确告知不要这样做。

这也许可以解释有时返回时出现的表单重新提交的警告消息。