//! datse server over HTTP use super::*; use futures::{ future::{ OptionFuture, FutureExt, }, stream, }; use warp::{ Filter, hyper::body::Bytes, }; use std::{ str, sync::Arc, convert::Infallible, }; use cryptohelpers::{ sha256, rsa, }; use uuid::Uuid; mod ban; mod source; mod forwarded_list; fn routing<'a>() -> impl warp::Filter + Clone + 'a { let auth = warp::path("auth").and({ //let req = warp::path("req") warp::post() }); let push = warp::path("push").and({ warp::post() }); let get = warp::path("get").and({ warp::get() }); auth.or(push).or(get) } pub async fn serve(cfg: impl Into) -> eyre::Result<()> { let cfg = cfg.into(); let bans = ban::Banlist::new(); // Filter: Extract the client IP from the remote address of the connection of the X-Forwarded-For header if it is trusted in `cfg`. let client_ip = warp::addr::remote() .and(warp::header("X-Forwarded-For")) .map(source::extract(cfg.trust_x_forwarded_for)) // Extract the IP .and_then(|req: Result| async move { req.map_err(warp::reject::custom) }) // Enforce banlist .and_then(bans.filter()); //.and_then(|req: source::ClientInfo| async move { Result::<_, std::convert::Infallible>::Ok(req) }); let r = warp::path("api").and(routing()); Ok(()) } // /// Main entry point for web server // pub async fn main(state: ServerState, cfg: Settings) -> eyre::Result<()> // { // let state = Arc::new(State::new(state, cfg.clone())); // let state = warp::any().map(move || state.clone()); // // Extract the client IP or fail with custom rejection // let client_ip = warp::addr::remote() // .and(warp::header("X-Forwarded-For")) // .map(source::extract(cfg.trust_x_forwarded_for)) // .and_then(|req: Result| async move {req.map_err(warp::reject::custom)}); // // /auth/req - Request an auth ID and information about how to respond (data to sign / password salt / what is supported, etc) // // /auth/resp//pw/ - Respond to an auth ID with a hashed password, salted with the salt obtained from the req call. // // /auth/resp//si[/] - Respond to an auth ID with one or more signatures of the data to be signed obtained in the auth request. If no number is provided, 1 is assumed. // let auth = { // let req = warp::path("req") // .and(client_ip.clone()).and(state.clone()) // .and_then(auth::auth_req); // let resp = { // let resp_auth_with_state = warp::post() // .and(client_ip.clone()).and(state.clone()) // .and(warp::path::param().map(|req_id: uuid::Uuid| req_id)); // let resp_auth_key = resp_auth_with_state.clone() // .and(warp::path("si") // .and(warp::path::param().map(|num: usize| std::cmp::min(std::cmp::max(1, // num), // cfg.max_key_sigs_per_auth_response)) // .or(warp::path::end().map(|| 1usize)).unify())) // .and(warp::body::content_length_limit(cfg.max_body_len.0)) // .and(warp::body::bytes()) // .and_then(auth::auth_key); // // -- Paths -- // let resp_auth_pass = { // let pw_path = resp_auth_with_state // .and(warp::path("pw")); // if cfg.allow_passwd_auth { // pw_path.and(warp::path::param().map(|hash: auth::Sha256Hash| hash.0)) // .and(warp::path::end()) // .and_then(auth::auth_pass).boxed() // } else { // pw_path.and_then(|_addr, _state, _hash| async move {Err(warp::reject::not_found())}).boxed() // } // }; // let resp = warp::path("resp") // .and(resp_auth_key // .or(resp_auth_pass)); // // /resp//pw/ // // /resp//si[/] // resp // }; // warp::path("auth") // .and(req.or(resp)) // .recover(auth::AuthError::recover) // }; // todo!() // }