feat(chat): share a chat by link — anonymous read-only /shared/<token> page, share/unshare
This commit is contained in:
+21
-7
@@ -6,9 +6,10 @@ Two layers, one module:
|
||||
append to their asset URLs (``?v=<token>``).
|
||||
* **Response middleware** (``CachingMiddleware`` / ``configure_caching``)
|
||||
— applies the caching behavior at the transport layer: the known
|
||||
HTML pages (``HTML_PAGES``) are always revalidated (``no-cache``) and
|
||||
their local asset references are rewritten to carry ``?v=<token>``;
|
||||
``/assets/*`` is
|
||||
HTML pages (``HTML_PAGES``) and the dynamic share page
|
||||
``/shared/<token>`` (phase 51) are always revalidated (``no-cache``)
|
||||
and their local asset references are rewritten to carry
|
||||
``?v=<token>``; ``/assets/*`` is
|
||||
served ``immutable`` for a year; everything else — all of ``/api/*``,
|
||||
including the SSE chat stream — passes through byte-identical.
|
||||
|
||||
@@ -125,6 +126,11 @@ HTML_PAGES: tuple[str, ...] = (
|
||||
"/tuning.html",
|
||||
"/git-sources.html", # phase 35: the admin git sources page
|
||||
"/history.html", # phase 50: the admin saved-chats page
|
||||
# phase 51: the shared page's STATIC path (the static mount serves
|
||||
# shared.html at /shared.html as well as the real route serves the
|
||||
# dynamic /shared/<token> — both must carry the no-cache + ?v=
|
||||
# contract, so the direct URL can never pin stale assets).
|
||||
"/shared.html",
|
||||
)
|
||||
|
||||
#: Prefix of the versioned static assets (header-only caching; the body is
|
||||
@@ -194,9 +200,10 @@ class CachingMiddleware(BaseHTTPMiddleware):
|
||||
|
||||
* ``/assets/*`` — ``Cache-Control: public, max-age=31536000, immutable``
|
||||
(header only — the body is never read).
|
||||
* the known HTML pages (``HTML_PAGES``) — ``Cache-Control: no-cache``,
|
||||
and (for ``text/html`` bodies) every local asset reference gains
|
||||
``?v=<token>``.
|
||||
* the known HTML pages (``HTML_PAGES``) plus the dynamic share page
|
||||
``/shared/<token>`` (phase 51, by path prefix) —
|
||||
``Cache-Control: no-cache``, and (for ``text/html`` bodies) every
|
||||
local asset reference gains ``?v=<token>``.
|
||||
|
||||
Everything else — all of ``/api/*`` (including the SSE chat stream) —
|
||||
passes through byte-identical: no header changes, the body stream is
|
||||
@@ -213,7 +220,14 @@ class CachingMiddleware(BaseHTTPMiddleware):
|
||||
response.headers["Cache-Control"] = ASSET_CACHE_CONTROL
|
||||
return response
|
||||
|
||||
if path not in HTML_PAGES:
|
||||
# Phase 51: the dynamic share page — ``/shared/<token>`` is a
|
||||
# REAL route (not a static file) serving ``shared.html``, so it
|
||||
# joins the known-page contract by path prefix: no-cache +
|
||||
# ``?v=`` asset rewrite. (``/api/shared/<token>`` — the JSON
|
||||
# read — starts with ``/api/`` and passes through below.)
|
||||
is_known_page = path in HTML_PAGES or path.startswith("/shared/")
|
||||
|
||||
if not is_known_page:
|
||||
# /api/* (incl. SSE), /favicon.ico, unknown paths: untouched.
|
||||
return response
|
||||
|
||||
|
||||
Reference in New Issue
Block a user