use std::net::SocketAddr; use serde::{Deserialize, Deserializer}; use chrono::Duration; use rocket::{Request, State, http::Status, request::{FromRequest, Outcome}}; use rocket::outcome::try_outcome; use crate::dns::{DnsClient, DnsConnectorClient, RecordConnector, ZoneConnector}; #[derive(Debug, Deserialize)] pub struct Config { pub dns: DnsClientConfig, pub web_app: WebAppConfig, } #[derive(Debug, Deserialize)] pub struct DnsClientConfig { pub server: SocketAddr } #[derive(Debug, Deserialize)] pub struct WebAppConfig { #[serde(deserialize_with = "from_duration")] pub token_duration: Duration, } fn from_duration<'de, D>(deserializer: D) -> Result where D: Deserializer<'de> { use serde::de::Error; String::deserialize(deserializer) .and_then(|string| humantime::parse_duration(&string).map_err(|err| Error::custom(err.to_string()))) .and_then(|duration| Duration::from_std(duration).map_err(|err| Error::custom(err.to_string()))) } // TODO: Maybe remove this #[rocket::async_trait] impl<'r> FromRequest<'r> for DnsClient { type Error = (); async fn from_request(request: &'r Request<'_>) -> Outcome { let config = try_outcome!(request.guard::<&State>().await); match DnsClient::new(config.dns.server).await { Err(e) => { error!("Failed to connect to DNS server: {}", e); Outcome::Failure((Status::InternalServerError, ())) }, Ok(c) => Outcome::Success(c) } } } #[rocket::async_trait] impl<'r> FromRequest<'r> for Box { type Error = (); async fn from_request(request: &'r Request<'_>) -> Outcome { let config = try_outcome!(request.guard::<&State>().await); match DnsClient::new(config.dns.server).await { Err(e) => { error!("Failed to connect to DNS server: {}", e); Outcome::Failure((Status::InternalServerError, ())) }, Ok(c) => Outcome::Success(Box::new(DnsConnectorClient::new(c))) } } } #[rocket::async_trait] impl<'r> FromRequest<'r> for Box { type Error = (); async fn from_request(request: &'r Request<'_>) -> Outcome { let config = try_outcome!(request.guard::<&State>().await); match DnsClient::new(config.dns.server).await { Err(e) => { error!("Failed to connect to DNS server: {}", e); Outcome::Failure((Status::InternalServerError, ())) }, Ok(c) => Outcome::Success(Box::new(DnsConnectorClient::new(c))) } } }