From 2273403d5f7c0e8994d7cefcfe641475e76f1d87 Mon Sep 17 00:00:00 2001 From: Jokler Date: Sun, 9 Feb 2020 18:52:36 +0100 Subject: Split web_server module into separate components --- src/web_server/api.rs | 48 +++++++++++++++++++++++++++++ src/web_server/bot_executor.rs | 63 ++++++++++++++++++++++++++++++++++++++ src/web_server/default.rs | 24 +++++++++++++++ src/web_server/front_end_cookie.rs | 8 ++--- src/web_server/tmtu.rs | 41 +++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 src/web_server/api.rs create mode 100644 src/web_server/bot_executor.rs create mode 100644 src/web_server/default.rs create mode 100644 src/web_server/tmtu.rs (limited to 'src/web_server') diff --git a/src/web_server/api.rs b/src/web_server/api.rs new file mode 100644 index 0000000..4deedad --- /dev/null +++ b/src/web_server/api.rs @@ -0,0 +1,48 @@ +use actix::Addr; +use actix_web::{get, web, HttpResponse, Responder, ResponseError}; +use derive_more::Display; +use serde::Serialize; + +use crate::web_server::{BotDataListRequest, BotDataRequest, BotExecutor}; + +#[get("/bots")] +pub async fn get_bot_list(bot: web::Data>) -> impl Responder { + let bot_datas = match bot.send(BotDataListRequest).await.unwrap() { + Ok(data) => data, + Err(_) => Vec::with_capacity(0), + }; + + web::Json(bot_datas) +} + +#[get("/bots/{name}")] +pub async fn get_bot(bot: web::Data>, name: web::Path) -> impl Responder { + if let Some(bot_data) = bot.send(BotDataRequest(name.into_inner())).await.unwrap() { + Ok(web::Json(bot_data)) + } else { + Err(ApiErrorKind::NotFound) + } +} + +#[derive(Serialize)] +struct ApiError { + error: String, + description: String, +} + +#[derive(Debug, Display)] +enum ApiErrorKind { + #[display(fmt = "Not Found")] + NotFound, +} + +impl ResponseError for ApiErrorKind { + fn error_response(&self) -> HttpResponse { + match *self { + ApiErrorKind::NotFound => HttpResponse::NotFound().json(ApiError { + error: self.to_string(), + description: String::from("The requested resource was not found"), + }), + } + } +} diff --git a/src/web_server/bot_executor.rs b/src/web_server/bot_executor.rs new file mode 100644 index 0000000..fde3c08 --- /dev/null +++ b/src/web_server/bot_executor.rs @@ -0,0 +1,63 @@ +use std::sync::Arc; + +use actix::{Actor, Handler, Message, SyncContext}; + +use crate::bot::MasterBot; +use crate::web_server::BotData; + +pub struct BotExecutor(pub Arc); + +impl Actor for BotExecutor { + type Context = SyncContext; +} + +pub struct BotNameListRequest; + +impl Message for BotNameListRequest { + // A plain Vec does not work for some reason + type Result = Result, ()>; +} + +impl Handler for BotExecutor { + type Result = Result, ()>; + + fn handle(&mut self, _: BotNameListRequest, _: &mut Self::Context) -> Self::Result { + let bot = &self.0; + + Ok(bot.bot_names()) + } +} + +pub struct BotDataListRequest; + +impl Message for BotDataListRequest { + // A plain Vec does not work for some reason + type Result = Result, ()>; +} + +impl Handler for BotExecutor { + type Result = Result, ()>; + + fn handle(&mut self, _: BotDataListRequest, _: &mut Self::Context) -> Self::Result { + let bot = &self.0; + + Ok(bot.bot_datas()) + } +} + +pub struct BotDataRequest(pub String); + +impl Message for BotDataRequest { + type Result = Option; +} + +impl Handler for BotExecutor { + type Result = Option; + + fn handle(&mut self, r: BotDataRequest, _: &mut Self::Context) -> Self::Result { + let name = r.0; + let bot = &self.0; + + bot.bot_data(name) + } +} diff --git a/src/web_server/default.rs b/src/web_server/default.rs new file mode 100644 index 0000000..b3c8291 --- /dev/null +++ b/src/web_server/default.rs @@ -0,0 +1,24 @@ +use actix::Addr; +use actix_web::{web, Error, HttpResponse}; +use askama::actix_web::TemplateIntoResponse; +use askama::Template; + +use crate::web_server::{filters, BotData, BotDataListRequest, BotExecutor}; + +#[derive(Template)] +#[template(path = "index.htm")] +struct OverviewTemplate<'a> { + bots: &'a [BotData], +} + +pub async fn index(bot: web::Data>) -> Result { + let bot_datas = match bot.send(BotDataListRequest).await.unwrap() { + Ok(data) => data, + Err(_) => Vec::with_capacity(0), + }; + + OverviewTemplate { + bots: &bot_datas[..], + } + .into_response() +} diff --git a/src/web_server/front_end_cookie.rs b/src/web_server/front_end_cookie.rs index 0207933..4812d0d 100644 --- a/src/web_server/front_end_cookie.rs +++ b/src/web_server/front_end_cookie.rs @@ -10,7 +10,7 @@ use serde::Deserialize; #[derive(PartialEq, Deserialize)] #[serde(rename_all = "lowercase")] pub enum FrontEnd { - Lazy, + Default, Tmtu, } @@ -19,7 +19,7 @@ impl FrontEnd { fn cookie(&self) -> String { let name = match self { - FrontEnd::Lazy => "lazy", + FrontEnd::Default => "default", FrontEnd::Tmtu => "tmtu", }; @@ -39,7 +39,7 @@ impl FromRequest for FrontEnd { let mut split = c.split('='); if Some(Self::COOKIE_NAME) == split.next() { match split.next() { - Some("lazy") => return ok(FrontEnd::Lazy), + Some("default") => return ok(FrontEnd::Default), Some("tmtu") => return ok(FrontEnd::Tmtu), _ => (), } @@ -48,7 +48,7 @@ impl FromRequest for FrontEnd { } } - ok(FrontEnd::Lazy) + ok(FrontEnd::Default) } } diff --git a/src/web_server/tmtu.rs b/src/web_server/tmtu.rs new file mode 100644 index 0000000..0645ee4 --- /dev/null +++ b/src/web_server/tmtu.rs @@ -0,0 +1,41 @@ +use actix::Addr; +use actix_web::{http::header, web, Error, HttpResponse}; +use askama::actix_web::TemplateIntoResponse; +use askama::Template; + +use crate::web_server::{filters, BotData, BotDataRequest, BotExecutor, BotNameListRequest}; + +#[derive(Template)] +#[template(path = "tmtu/index.htm")] +struct TmtuTemplate { + bot_names: Vec, + bot: Option, +} + +pub async fn index(bot: web::Data>) -> Result { + let bot_names = bot.send(BotNameListRequest).await.unwrap().unwrap(); + + TmtuTemplate { + bot_names, + bot: None, + } + .into_response() +} + +pub async fn get_bot( + bot: web::Data>, + name: String, +) -> Result { + let bot_names = bot.send(BotNameListRequest).await.unwrap().unwrap(); + + if let Some(bot) = bot.send(BotDataRequest(name)).await.unwrap() { + TmtuTemplate { + bot_names, + bot: Some(bot), + } + .into_response() + } else { + // TODO to 404 or not to 404 + Ok(HttpResponse::Found().header(header::LOCATION, "/").finish()) + } +} -- cgit v1.2.3-70-g09d2