You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.7 KiB
161 lines
4.7 KiB
//! 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;
|
|
|
|
mod state;
|
|
use state::State;
|
|
|
|
async fn auth(state: State) -> Result<String, warp::Rejection>
|
|
{
|
|
Ok("".to_owned())
|
|
}
|
|
|
|
async fn push(state: State) -> Result<&'static str, warp::Rejection>
|
|
{
|
|
Ok("")
|
|
}
|
|
|
|
async fn get(state: State) -> Result<impl warp::Reply, warp::Rejection>
|
|
{
|
|
Ok(warp::reply())
|
|
}
|
|
|
|
fn routing<'a>(state: State) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = warp::reject::Rejection> + Clone + 'a
|
|
{
|
|
let state = warp::any().map(move || state.clone());
|
|
|
|
let auth = warp::path("auth").and({
|
|
//let req = warp::path("req")
|
|
warp::post().and(state.clone()).and_then(|state: State| auth(state))
|
|
});
|
|
|
|
let push = warp::path("push").and({
|
|
warp::post().and(state.clone()).and_then(|state: State| self::push(state))
|
|
|
|
});
|
|
|
|
let get = warp::path("get").and({
|
|
warp::post().and(state.clone()).and_then(|state: State| self::get(state))
|
|
|
|
});
|
|
|
|
auth.or(push).or(get)
|
|
}
|
|
|
|
pub async fn serve(cfg: Config) -> eyre::Result<()>
|
|
{
|
|
//Create state
|
|
let state = State::new(cfg);
|
|
|
|
// 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(state.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({ let state = state.clone(); move |c| { state.clone().banlist().filter(c) } });
|
|
|
|
//.and_then(|req: source::ClientInfo| async move { Result::<_, std::convert::Infallible>::Ok(req) });
|
|
|
|
let filter = warp::path("api")
|
|
.and(routing(state.clone()));
|
|
|
|
warp::serve(filter).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!()
|
|
// }
|
|
|