opentally-server/src/web.rs

87 lines
2.5 KiB
Rust

use crate::TallyState;
use actix::prelude::*;
use actix_web::{server, App, HttpResponse};
use futures::future::Future;
use std::sync::mpsc;
use std::thread;
use typed_html::dom::DOMTree;
use typed_html::html;
fn build_template() -> DOMTree<String> {
html!(
<html>
<head>
<title>"OpenTally Control"</title>
<script src="/script.js" type="text/javascript"></script>
</head>
<body>
<h1>"OpenTally Control"</h1>
</body>
</html>
)
}
pub struct WebServer {
addr: Addr<actix_net::server::Server>,
shutdown_rx: mpsc::Receiver<()>,
}
impl WebServer {
pub fn run(addr: std::net::SocketAddr) -> WebServer {
// todo: not have the damn js inline in the func
const JS: &'static str = r#"
var sock = new WebSocket("ws://" + window.location.host + "/ws");
sock.onmessage = function (e) {
console.log(e);
}
sock.onopen = function (e) {
sock.send("Hello!");
}"#;
let (shutdown_tx, shutdown_rx) = mpsc::channel();
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let sys = actix::System::new("test");
let addr = server::new(|| {
App::new()
.resource("/", |r| {
r.f(|_r| {
HttpResponse::Ok()
.content_type("text/html")
.body(build_template().to_string())
})
})
.resource("script.js", |r| {
r.f(|_r| HttpResponse::Ok().content_type("text/javascript").body(JS))
})
//.resource("/ws", )
})
.bind(addr)
.expect("Error binding to address.")
.start();
tx.send(addr).unwrap();
sys.run();
shutdown_tx.send(()).unwrap(); // Notify that we have shutdown
});
let addr = rx.recv().unwrap();
WebServer {
addr: addr,
shutdown_rx: shutdown_rx,
}
}
pub fn shutdown(self) {
log::debug!("Web server shutting down...");
self.addr
.send(actix_web::server::StopServer { graceful: true })
.wait()
.unwrap()
.unwrap();
let _ = self.shutdown_rx.recv().unwrap(); // wait for webserver shutdown
log::info!("Web server shutdown");
}
}