//! 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 < Error = warp ::reject ::Rejection > + 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 : Config ) -> eyre ::Result < ( ) >
{
let bans : ban ::Banlist = cfg . static_bans . iter ( ) . collect ( ) ;
//TODO: Create state
// 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 < source ::ClientInfo , _ > | 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 filter = warp ::path ( "api" )
//how the FUCK do we insert shit into this????????????????????????
. and ( routing ( ) ) ;
warp ::serve ( client_ip ) . bind_with_graceful_shutdown ( ( [ 127 , 0 , 0 , 1 ] , 8001 ) , tokio ::signal ::ctrl_c ( ) ) . await ;
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<std::net::IpAddr, _>| 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/<req_id>/pw/<passwd hash> - Respond to an auth ID with a hashed password, salted with the salt obtained from the req call.
// // /auth/resp/<req_id>/si[/<num of sigs in body>] - 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/<req_id>/pw/<passwd hash>
// // /resp/<req_id>/si[/<num of sigs in body>]
// resp
// };
// warp::path("auth")
// .and(req.or(resp))
// .recover(auth::AuthError::recover)
// };
// todo!()
// }