httpmcp_rust/sse/
stream.rs

1use actix_web::web::Bytes;
2use serde::Serialize;
3use uuid::Uuid;
4
5/// Server-Sent Event
6#[derive(Debug, Clone)]
7pub struct SseEvent {
8    pub id: Option<String>,
9    pub event: Option<String>,
10    pub data: String,
11}
12
13impl SseEvent {
14    /// Create a new SSE event
15    pub fn new(data: impl Into<String>) -> Self {
16        Self {
17            id: Some(Uuid::new_v4().to_string()),
18            event: Some("message".to_string()),
19            data: data.into(),
20        }
21    }
22
23    /// Create event with custom event type
24    pub fn with_event(mut self, event: impl Into<String>) -> Self {
25        self.event = Some(event.into());
26        self
27    }
28
29    /// Create event from JSON-serializable data
30    pub fn from_json<T: Serialize>(data: &T) -> Result<Self, serde_json::Error> {
31        let json = serde_json::to_string(data)?;
32        Ok(Self::new(json))
33    }
34
35    /// Convert to SSE format bytes
36    pub fn to_bytes(&self) -> Bytes {
37        let mut output = String::new();
38
39        if let Some(id) = &self.id {
40            output.push_str(&format!("id: {}\n", id));
41        }
42
43        if let Some(event) = &self.event {
44            output.push_str(&format!("event: {}\n", event));
45        }
46
47        output.push_str(&format!("data: {}\n\n", self.data));
48
49        Bytes::from(output)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_sse_event_format() {
59        let event = SseEvent {
60            id: Some("123".to_string()),
61            event: Some("message".to_string()),
62            data: "test data".to_string(),
63        };
64
65        let bytes = event.to_bytes();
66        let text = String::from_utf8(bytes.to_vec()).unwrap();
67
68        assert!(text.contains("id: 123\n"));
69        assert!(text.contains("event: message\n"));
70        assert!(text.contains("data: test data\n"));
71    }
72}