commit d824539220c6ce5105a4937b7b4c3c0c04ce423c
parent b29468f52db172037b861e7c6a907d2d66dfaf11
Author: Silas Brack <silasbrack@gmail.com>
Date: Thu, 11 Jun 2026 12:30:33 +0200
feat: add SSE helper module for Datastar-compliant responses
Adds src/sse.rs with helpers that format proper SSE
datastar-patch-elements events per the Datastar SSE spec,
replacing the non-standard custom header approach.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -3,6 +3,7 @@ mod db;
mod error;
mod handlers;
mod routes;
+mod sse;
mod state;
mod templates;
mod trailbase;
diff --git a/src/sse.rs b/src/sse.rs
@@ -0,0 +1,35 @@
+use axum::{body::Body, http::{StatusCode, header}, response::Response};
+
+pub fn patch_elements(html: &str) -> Response {
+ patch_elements_with_options(html, None, None)
+}
+
+pub fn patch_elements_with_selector(html: &str, selector: &str) -> Response {
+ patch_elements_with_options(html, Some(selector), None)
+}
+
+fn patch_elements_with_options(
+ html: &str,
+ selector: Option<&str>,
+ mode: Option<&str>,
+) -> Response {
+ let mut data_lines = Vec::new();
+ if let Some(sel) = selector {
+ data_lines.push(format!("data: selector {sel}"));
+ }
+ if let Some(m) = mode {
+ data_lines.push(format!("data: mode {m}"));
+ }
+ for line in html.lines() {
+ data_lines.push(format!("data: elements {line}"));
+ }
+
+ let body = format!("event: datastar-patch-elements\n{}\n\n", data_lines.join("\n"));
+
+ Response::builder()
+ .status(StatusCode::OK)
+ .header(header::CONTENT_TYPE, "text/event-stream")
+ .header(header::CACHE_CONTROL, "no-cache")
+ .body(Body::from(body))
+ .unwrap()
+}