use ntex::util::Bytes;
use serde_json::{json, Value};
pub const CONTENT_TYPE: &str = "text/event-stream";
pub fn event(name: &str, data: &Value) -> Bytes {
Bytes::from(format!("event: {name}\ndata: {data}\n\n"))
}
pub fn delta(text: &str) -> Bytes {
event("delta", &json!({ "text": text }))
}
pub fn failure(message: &str) -> Bytes {
event("error", &json!({ "error": message }))
}
pub fn done(data: &Value) -> Bytes {
event("done", data)
}
pub fn headers(response: &mut ntex::web::HttpResponseBuilder) {
response
.content_type(CONTENT_TYPE)
.header("cache-control", "no-cache, no-transform")
.header("connection", "keep-alive")
.header("x-accel-buffering", "no");
}
#[derive(Debug)]
pub enum Never {}
impl std::fmt::Display for Never {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {}
}
}
impl std::error::Error for Never {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_event_is_one_frame_with_a_json_payload() {
assert_eq!(
delta("Hel"),
Bytes::from("event: delta\ndata: {\"text\":\"Hel\"}\n\n")
);
}
#[test]
fn a_newline_in_the_text_cannot_break_the_framing() {
let frame = delta("one\ntwo");
let text = std::str::from_utf8(&frame).unwrap();
assert_eq!(text.matches("\n\n").count(), 1);
assert!(text.ends_with("\n\n"));
assert!(text.contains(r#"{"text":"one\ntwo"}"#));
}
}