mailspy/src/http.rs

95 lines
2.6 KiB
Rust

use crate::mail::{Mail, Mailbox};
use poem::{
endpoint::{EmbeddedFileEndpoint, EmbeddedFilesEndpoint},
get, handler,
listener::TcpListener,
middleware::AddData,
web::{Data, Json},
EndpointExt, Route, Server,
};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "ui/build"]
pub struct Files;
#[handler]
async fn messages(mailbox: Data<&Mailbox>) -> Json<Vec<Mail>> {
Json(mailbox.all().await)
}
#[handler]
async fn clear(mailbox: Data<&Mailbox>) -> String {
mailbox.clear().await;
"OK".to_string()
}
pub async fn server(mailbox: Mailbox, port: u16) -> anyhow::Result<()> {
tokio::spawn(async move {
let app = Route::new()
.at("/messages", get(messages))
.at("/", EmbeddedFileEndpoint::<Files>::new("index.html"))
.nest("/", EmbeddedFilesEndpoint::<Files>::new())
.with(AddData::new(mailbox));
if let Err(e) = Server::new(TcpListener::bind(format!("0.0.0.0:{}", port)))
.run(app)
.await
{
tracing::error!("Webserver error: {}", e);
}
});
Ok(())
}
#[cfg(test)]
mod tests {
use super::{clear, messages};
use crate::mail::{Mail, Mailbox};
use poem::{
middleware::AddData,
test::{TestClient, TestJson},
EndpointExt, Route,
};
async fn request_data<'a>(url: &str, mb: &Mailbox) -> TestJson {
let app = Route::new()
.at("/messages", messages)
.at("/clear", clear)
.with(AddData::new(mb.clone()));
let client = TestClient::new(app);
let resp = client.get(url).send().await;
resp.assert_status_is_ok();
resp.json().await
}
async fn request_void<'a>(url: &str, mb: &Mailbox) {
let app = Route::new()
.at("/messages", messages)
.at("/clear", clear)
.with(AddData::new(mb.clone()));
let client = TestClient::new(app);
let resp = client.get(url).send().await;
resp.assert_status_is_ok();
}
#[tokio::test]
async fn test_messages_endpoint() {
let mb = Mailbox::new();
let resp = request_data("/messages", &mb).await;
let data = resp.value();
data.array().assert_is_empty();
mb.store(Mail::default()).await;
let resp = request_data("/messages", &mb).await;
let data = resp.value();
assert_eq!(data.array().len(), 1);
}
#[tokio::test]
async fn test_clear_endpoint() {
let mb = Mailbox::new();
mb.store(Mail::default()).await;
request_void("/clear", &mb).await;
assert_eq!(mb.len().await, 0);
}
}