use axum::response::IntoResponse;
use http::StatusCode;
use std::{net::SocketAddr, pin, sync, time::Duration};
use tokio::sync::broadcast;
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
use axum::{
body,
response::sse::{Event, KeepAlive, Sse},
};
pub static RELOADER_SCRIPT_BYTES: &'static [u8] = include_bytes!("./reloader.js");
pub static RELOADER_SCRIPT_ENDPOINT: &'static str = "/static/sse/reloader.js";
pub static RELOADER_SSE_ENDPOINT: &'static str = "/static/sse/reload";
pub fn sse_endpoint_script(
_addr: SocketAddr,
_request: crate::types::HyperRequest,
) -> pin::Pin<Box<crate::types::HyperFuture>> {
Box::pin(async move {
let body = body::Body::new(crate::full(bytes::Bytes::from(RELOADER_SCRIPT_BYTES)));
Ok(hyper::Response::builder()
.header("Content-Type", "text/javascript")
.status(StatusCode::OK)
.body(body)
.unwrap())
})
}
fn sse_endpoint_reloader(
_addr: SocketAddr,
_request: crate::types::HyperRequest,
running_notification: broadcast::Receiver<()>,
) -> pin::Pin<Box<crate::types::HyperFuture>> {
Box::pin(async move {
let running_stream = BroadcastStream::new(running_notification);
Ok(Sse::new(
running_stream.map(|_| -> Result<Event, crate::types::BoxedError> {
Ok(Event::default()
.data("ready")
.comment("indicates we should reload page")
.event("reload"))
}),
)
.keep_alive(
KeepAlive::new()
.interval(Duration::from_secs(1))
.text("keep-alive"),
)
.into_response())
})
}
pub fn create_sse_endpoint_handler(
running_notification: broadcast::Sender<()>,
) -> sync::Arc<crate::types::HyperFunc> {
sync::Arc::new(move |addr, request| {
sse_endpoint_reloader(addr, request, running_notification.subscribe())
})
}