clemsbot/src/app/web.rs

72 lines
2.5 KiB
Rust

mod template;
mod route;
use std::sync::Arc;
use crate::app::State;
use warp::{Filter, Rejection, Reply};
use std::convert::Infallible;
use warp::http::StatusCode;
use std::borrow::Cow;
use self::route::*;
pub async fn start_web(state: Arc<State>) {
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)))
);
let unauthed = access_token_routes();
let routes = authed.or(unauthed).recover(handle_rejection);
warp::serve(routes)
.run(([0, 0, 0, 0], 8000))
.await;
}
#[derive(Debug)]
enum CustomRejection {
InvalidAccessToken,
InvalidForm,
TwitchError,
}
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::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))
}