Skip to content

Commit 42a17db

Browse files
Set Cache-Control: no-store on the Bokeh document page (#8636)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2102b17 commit 42a17db

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

panel/io/server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,11 @@ def _render_auth_error(self, auth_error: str) -> str:
635635

636636
@authenticated
637637
async def get(self, *args, **kwargs):
638+
# Prevent the browser from caching the document page. The page embeds
639+
# a short-lived Bokeh session token; a cached page served after a
640+
# logout/login cycle would carry a stale token and the subsequent
641+
# WebSocket connection would fail (see e.g. holoviz/panel#8634).
642+
self.set_header("Cache-Control", "no-store")
638643
prefix = self.application.prefix
639644
if prefix and self.request.path == prefix and not prefix.endswith('/'):
640645
query_string = self.request.query if self.request.query else ''

panel/tests/test_server.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ def test_server_prefix_root_redirect():
157157
assert response.status_code == 200
158158
assert response.url.endswith('/foo/')
159159

160+
def test_server_doc_page_is_not_cached():
161+
# The document page embeds a short-lived Bokeh session token, so it must
162+
# not be cached by the browser (a stale token breaks the WebSocket).
163+
html = Markdown('# Title')
164+
165+
r = serve_and_request(html)
166+
167+
assert r.status_code == 200
168+
assert r.headers.get('Cache-Control') == 'no-store'
169+
160170
def test_server_static_dirs_index():
161171
html = Markdown('# Title')
162172

0 commit comments

Comments
 (0)