From 09d3afc542ded437445a054cdd06acfc3fe67c22 Mon Sep 17 00:00:00 2001 From: allen0099 Date: Fri, 25 Sep 2026 13:41:53 +0000 Subject: [PATCH] docs: show what each Cache-Control directive actually does The directive table marked header-only directives as simply supported and described them with the spec's wording. Show how each one is set, whether it is sent, and its effect on the server-side cache, and document that the request's own Cache-Control is ignored by design. Tone down the README claims of comprehensive / complete directive support. Closes #143 --- CHANGELOG.md | 6 ++++++ README.md | 2 +- docs/HTTP_CACHING.md | 49 +++++++++++++++++++++++++++++--------------- docs/README.zh-TW.md | 38 +++++++++++++++++++--------------- 4 files changed, 60 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2017651..329ea04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,12 @@ Note that 0.3.3 was never released; 0.3.4 follows 0.3.2. ### Fixed +- The Cache-Control table in the HTTP caching guide no longer marks + header-only directives as simply "supported". It now shows, for each + directive, how to set it, whether it is sent, and what it does to the + server-side cache. A new section documents that the request's own + `Cache-Control` is ignored by design. + - Docstrings and guides that disagreed with the code are corrected. Most visible: - `SessionConfig.sliding_threshold` now describes renewal once less than diff --git a/README.md b/README.md index 9f30f2a..ba8429d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [English](https://github.com/allen0099/FastAPI-CacheX/blob/master/README.md) | [繁體中文](https://github.com/allen0099/FastAPI-CacheX/blob/master/docs/README.zh-TW.md) -A high-performance caching extension for FastAPI, providing comprehensive HTTP caching support and optional session management. +A high-performance caching extension for FastAPI: a server-side response cache with `Cache-Control` and `ETag` support, application-level caching, and optional session management. **Documentation:** — guides and the full API reference. diff --git a/docs/HTTP_CACHING.md b/docs/HTTP_CACHING.md index 6590c65..eaddfe4 100644 --- a/docs/HTTP_CACHING.md +++ b/docs/HTTP_CACHING.md @@ -38,25 +38,40 @@ when it is missing. If no backend has been configured, `@cache` falls back to a ## Cache-Control directives -| Directive | Supported | Description | -|--------------------------|--------------------|---------------------------------------------------------------------------------------------------------| -| `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. | -| `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. | -| `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. | -| `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. | -| `no-transform` | :x: | Instructs caches not to transform the response content. | -| `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. | -| `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. | -| `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. | -| `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. | -| `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. | -| `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. | -| `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. | -| `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. | - -How each decorator argument turns into the header is described in +`@cache` plays two roles. It writes a `Cache-Control` header for browsers and +intermediaries (CDNs, reverse proxies), and it keeps its own server-side cache in +the backend. Most directives only affect the first: they are written into the +header, and the server-side cache behaves the same with or without them. + +| Directive | Set with | Sent in header | Effect on the server-side cache | +|--------------------------|------------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------| +| `max-age` | `ttl=N` | :white_check_mark: | The stored response is served for `N` seconds without running the handler (`ttl=0` or unset: never served directly). | +| `no-cache` | `no_cache=True` | :white_check_mark: | The handler runs on every request; the response is still stored, and a matching `If-None-Match` gets a 304. | +| `no-store` | `no_store=True` | :white_check_mark: | Nothing is read or stored, and no ETag is set. | +| `private` | `private=True` | :white_check_mark: | The backend is bypassed; the handler runs on every request, and ETag revalidation still works. | +| `public` | `public=True` | :white_check_mark: | None (header only). | +| `immutable` | `immutable=True` | :white_check_mark: | None (header only). | +| `must-revalidate` | `must_revalidate=True` | :white_check_mark: | None (header only). | +| `stale-while-revalidate` | `stale="revalidate", stale_ttl=N` | :white_check_mark: | None (header only): the server-side cache never serves stale content. | +| `stale-if-error` | `stale="error", stale_ttl=N` | :white_check_mark: | None (header only): a failing handler is not answered from the cache. | +| `s-maxage` | — | :x: | — | +| `proxy-revalidate` | — | :x: | — | +| `no-transform` | — | :x: | — | +| `must-understand` | — | :x: | — | + +`no_cache=True` and `no_store=True` replace the rest of the header: with +`no_cache` only `no-cache` (and `must-revalidate`, when set) is sent, and with +`no_store` only `no-store`. How the other arguments combine is described in [Cache flow](CACHE_FLOW.md#2-cache-control-directives). +### The request's `Cache-Control` is ignored + +A client's own `Cache-Control` request header (`no-cache`, `max-age=0`, as sent +by a browser's hard reload, and so on) does not change what `@cache` does. This +is deliberate: if a request header could bypass the cache, any client could +send every request straight to your handler. Conditional requests are honoured: +a matching `If-None-Match` gets a 304. + ## Cache hit behavior When a cached entry is valid (within TTL): diff --git a/docs/README.zh-TW.md b/docs/README.zh-TW.md index 9815a2a..fbb9674 100644 --- a/docs/README.zh-TW.md +++ b/docs/README.zh-TW.md @@ -14,7 +14,7 @@ [English](https://github.com/allen0099/FastAPI-CacheX/blob/master/README.md) | [繁體中文](README.zh-TW.md) -FastAPI-CacheX 是一個為 FastAPI 框架設計的高效能快取擴充套件,提供完整的 HTTP 快取功能支援和可選的 Session 管理。 +FastAPI-CacheX 是一個為 FastAPI 框架設計的高效能快取擴充套件,提供伺服器端回應快取(支援 `Cache-Control` 與 `ETag`)、應用層快取和可選的 Session 管理。 ## 功能特點 @@ -27,7 +27,7 @@ FastAPI-CacheX 是一個為 FastAPI 框架設計的高效能快取擴充套件 - Redis - Memcached - 記憶體內快取 -- 完整實現 Cache-Control 指令 +- 可在回應中設定常用的 Cache-Control 指令(詳見下表) - 簡單易用的 `@cache` 裝飾器 ### Session 管理(可選擴充套件) @@ -43,21 +43,25 @@ FastAPI-CacheX 是一個為 FastAPI 框架設計的高效能快取擴充套件 ### Cache-Control 指令 -| 指令 | 支援狀態 | 說明 | -|--------------------------|--------------------|---------------------------------| -| `max-age` | :white_check_mark: | 指定資源被認為是新鮮的最長時間。 | -| `s-maxage` | :x: | 在共享快取中資源被認為是新鮮的最長時間。 | -| `no-cache` | :white_check_mark: | 強制快取在釋放快取副本前向原始伺服器驗證請求。 | -| `no-store` | :white_check_mark: | 指示快取不儲存請求或回應的任何部分。 | -| `no-transform` | :x: | 指示快取不要轉換回應內容。 | -| `must-revalidate` | :white_check_mark: | 強制快取在資源過期後向原始伺服器重新驗證。 | -| `proxy-revalidate` | :x: | 類似 `must-revalidate`,但僅適用於共享快取。 | -| `must-understand` | :x: | 表示接收者必須理解該指令,否則應視為錯誤。 | -| `private` | :white_check_mark: | 表示回應僅供單一使用者使用,不應被共享快取儲存。 | -| `public` | :white_check_mark: | 表示回應可被任何快取儲存,即使通常是無法快取的。 | -| `immutable` | :white_check_mark: | 表示回應內容不會隨時間改變,允許更長時間的快取。 | -| `stale-while-revalidate` | :white_check_mark: | 表示快取可以在背景重新驗證時提供過期的回應。 | -| `stale-if-error` | :white_check_mark: | 表示當原始伺服器無法訪問時,快取可以提供過期的回應。 | +`@cache` 有兩個角色:替瀏覽器與中間層(CDN、反向代理)寫出 `Cache-Control` 標頭,以及在後端維護自己的伺服器端快取。大部分指令只影響前者:它們會寫進標頭,但伺服器端快取的行為不會因此改變。 + +| 指令 | 設定方式 | 寫入標頭 | 對伺服器端快取的影響 | +|--------------------------|-------------------------------------|--------------------|-------------------------------------------------------------| +| `max-age` | `ttl=N` | :white_check_mark: | `N` 秒內直接回傳已儲存的回應,不執行 handler(`ttl=0` 或未設定:不直接回傳)。 | +| `no-cache` | `no_cache=True` | :white_check_mark: | 每次都執行 handler;回應仍會儲存,`If-None-Match` 相符時回 304。 | +| `no-store` | `no_store=True` | :white_check_mark: | 不讀取也不儲存,也不設定 ETag。 | +| `private` | `private=True` | :white_check_mark: | 完全不經過後端;每次都執行 handler,ETag 重新驗證仍有效。 | +| `public` | `public=True` | :white_check_mark: | 無(僅寫入標頭)。 | +| `immutable` | `immutable=True` | :white_check_mark: | 無(僅寫入標頭)。 | +| `must-revalidate` | `must_revalidate=True` | :white_check_mark: | 無(僅寫入標頭)。 | +| `stale-while-revalidate` | `stale="revalidate", stale_ttl=N` | :white_check_mark: | 無(僅寫入標頭):伺服器端快取不會回傳過期內容。 | +| `stale-if-error` | `stale="error", stale_ttl=N` | :white_check_mark: | 無(僅寫入標頭):handler 失敗時不會改用快取回應。 | +| `s-maxage` | — | :x: | — | +| `proxy-revalidate` | — | :x: | — | +| `no-transform` | — | :x: | — | +| `must-understand` | — | :x: | — | + +請求端的 `Cache-Control`(例如瀏覽器強制重新整理時送出的 `no-cache`、`max-age=0`)不會改變 `@cache` 的行為。這是刻意的設計:若請求標頭能繞過快取,任何用戶端都能讓每個請求直接打到 handler。條件式請求仍會處理:`If-None-Match` 相符時回 304。 ## 安裝指南