clemsbot/src/app/web.rs

80 lines
2.7 KiB
Rust

mod template;
mod route;
use warp::{
Filter, Rejection, Reply,
http::StatusCode,
};
use self::route::*;
use crate::app::State;
use std::{
borrow::Cow,
convert::Infallible,
sync::Arc,
};
pub async fn start_web(state: Arc<State>) {
println!("starting web server");
let cookie_state = Arc::clone(&state);
let authed = warp::cookie("access_token")
.or(warp::header("x-api-key"))
.unify()
.and_then(move |access_token: String| {
let state = Arc::clone(&cookie_state);
async move {
if access_token == state.user_config.bot.access_token {
Ok(())
} else {
Err(warp::reject::custom(CustomRejection::InvalidAccessToken))
}
}
})
.untuple_one()
.and(
commands_routes(Arc::clone(&state))
.or(redemptions_routes(Arc::clone(&state)))
.or(livesplit_routes(Arc::clone(&state)))
.or(events_routes(Arc::clone(&state)))
);
let unauthed = access_token_routes();
let routes = authed.or(unauthed).recover(handle_rejection);
warp::serve(routes)
.run((state.user_config.web.address, state.user_config.web.port))
.await;
}
#[derive(Debug)]
enum CustomRejection {
InvalidAccessToken,
InvalidForm,
TwitchError,
InvalidCommand,
}
impl warp::reject::Reject for CustomRejection {}
async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
let (code, message) = if err.is_not_found() {
(StatusCode::NOT_FOUND, Cow::from("404 - Not Found"))
} else if let Some(custom) = err.find::<CustomRejection>() {
match custom {
CustomRejection::InvalidAccessToken => (StatusCode::UNAUTHORIZED, Cow::from("invalid access token")),
CustomRejection::InvalidForm => (StatusCode::BAD_REQUEST, Cow::from("invalid form submission")),
CustomRejection::TwitchError => (StatusCode::INTERNAL_SERVER_ERROR, Cow::from("twitch error")),
CustomRejection::InvalidCommand => (StatusCode::BAD_REQUEST, Cow::from("invalid command")),
// CustomRejection::Askama(e) => (StatusCode::INTERNAL_SERVER_ERROR, Cow::from(format!("templating error: {:#?}", e))),
}
} else if let Some(e) = err.find::<warp::reject::MissingCookie>() {
(StatusCode::BAD_REQUEST, Cow::from(format!("missing `{}` cookie", e.name())))
} else if let Some(e) = err.find::<warp::reject::InvalidHeader>() {
(StatusCode::BAD_REQUEST, Cow::from(format!("missing `{}` header", e.name())))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Cow::from(format!("unhandled error: {:#?}", err)))
};
Ok(warp::reply::with_status(message, code))
}