Harden HTML5 SSE headers
This commit is contained in:
@@ -1711,7 +1711,7 @@ async def html5_operations_events(
|
|||||||
return StreamingResponse(
|
return StreamingResponse(
|
||||||
stream_operations(),
|
stream_operations(),
|
||||||
media_type="text/event-stream",
|
media_type="text/event-stream",
|
||||||
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
|
headers=_html5_sse_headers(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1777,7 +1777,7 @@ async def html5_project_events(project_id: str, once: bool = False) -> Streaming
|
|||||||
return StreamingResponse(
|
return StreamingResponse(
|
||||||
stream_status(),
|
stream_status(),
|
||||||
media_type="text/event-stream",
|
media_type="text/event-stream",
|
||||||
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
|
headers=_html5_sse_headers(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -2103,7 +2103,7 @@ async def html5_project_setup_events(project_id: str, once: bool = False) -> Str
|
|||||||
return StreamingResponse(
|
return StreamingResponse(
|
||||||
stream_setup(),
|
stream_setup(),
|
||||||
media_type="text/event-stream",
|
media_type="text/event-stream",
|
||||||
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
|
headers=_html5_sse_headers(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -8509,6 +8509,14 @@ def _html5_sse_event(event: str, fragment: str) -> str:
|
|||||||
return f"event: {event}\nretry: 5000\n{data}\n\n"
|
return f"event: {event}\nretry: 5000\n{data}\n\n"
|
||||||
|
|
||||||
|
|
||||||
|
def _html5_sse_headers() -> dict[str, str]:
|
||||||
|
return {
|
||||||
|
"Cache-Control": "no-cache, no-transform",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"X-Accel-Buffering": "no",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _html5_sse_if_changed(last_fragments: dict[str, str], event: str, fragment: str):
|
def _html5_sse_if_changed(last_fragments: dict[str, str], event: str, fragment: str):
|
||||||
if last_fragments.get(event) == fragment:
|
if last_fragments.get(event) == fragment:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -167,6 +167,9 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
assert "__next" not in editor.text
|
assert "__next" not in editor.text
|
||||||
|
|
||||||
with client.stream("GET", f"/html5/projects/{project_id}/events?once=1") as events:
|
with client.stream("GET", f"/html5/projects/{project_id}/events?once=1") as events:
|
||||||
|
assert events.headers["cache-control"] == "no-cache, no-transform"
|
||||||
|
assert events.headers["x-accel-buffering"] == "no"
|
||||||
|
assert events.headers["connection"] == "keep-alive"
|
||||||
first_chunk = "".join(events.iter_text())
|
first_chunk = "".join(events.iter_text())
|
||||||
assert ": project " in first_chunk
|
assert ": project " in first_chunk
|
||||||
assert "retry: 5000" in first_chunk
|
assert "retry: 5000" in first_chunk
|
||||||
@@ -708,6 +711,9 @@ def test_html5_project_setup_renders_server_fragments():
|
|||||||
assert "<html" not in summary.text
|
assert "<html" not in summary.text
|
||||||
|
|
||||||
with client.stream("GET", f"/html5/projects/{project_id}/setup/events?once=1") as events:
|
with client.stream("GET", f"/html5/projects/{project_id}/setup/events?once=1") as events:
|
||||||
|
assert events.headers["cache-control"] == "no-cache, no-transform"
|
||||||
|
assert events.headers["x-accel-buffering"] == "no"
|
||||||
|
assert events.headers["connection"] == "keep-alive"
|
||||||
first_chunk = "".join(events.iter_text())
|
first_chunk = "".join(events.iter_text())
|
||||||
assert ": setup " in first_chunk
|
assert ": setup " in first_chunk
|
||||||
assert "retry: 5000" in first_chunk
|
assert "retry: 5000" in first_chunk
|
||||||
@@ -747,6 +753,9 @@ def test_html5_operations_renders_job_monitor_fragments():
|
|||||||
assert "__next" not in page.text
|
assert "__next" not in page.text
|
||||||
|
|
||||||
with client.stream("GET", "/html5/operations/events?once=1") as events:
|
with client.stream("GET", "/html5/operations/events?once=1") as events:
|
||||||
|
assert events.headers["cache-control"] == "no-cache, no-transform"
|
||||||
|
assert events.headers["x-accel-buffering"] == "no"
|
||||||
|
assert events.headers["connection"] == "keep-alive"
|
||||||
first_chunk = "".join(events.iter_text())
|
first_chunk = "".join(events.iter_text())
|
||||||
assert ": operations heartbeat" in first_chunk
|
assert ": operations heartbeat" in first_chunk
|
||||||
assert "retry: 5000" in first_chunk
|
assert "retry: 5000" in first_chunk
|
||||||
|
|||||||
Reference in New Issue
Block a user