diff --git a/src/main.rs b/src/main.rs index d27bf5a..c5b3c3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -123,16 +123,14 @@ async fn main() { let _ = domani::service::http::new( &mut task_stack, domain_manager.clone(), - config.domain_checker_target_a, - config.passphrase, - config.http_listen_addr, - config.http_domain, - config - .https_listen_addr - .map(|listen_addr| domani::service::http::HTTPSParams { - listen_addr, - cert_resolver: domain_manager.clone(), - }), + domain_manager.clone(), + domani::service::http::Config { + http_addr: config.http_listen_addr, + https_addr: config.https_listen_addr, + primary_domain: config.http_domain, + target_a: config.domain_checker_target_a, + passphrase: config.passphrase, + }, ); let mut signals = diff --git a/src/service/http.rs b/src/service/http.rs index 7acb3b3..bcf7b82 100644 --- a/src/service/http.rs +++ b/src/service/http.rs @@ -1,6 +1,9 @@ +mod config; mod tasks; mod tpl; +pub use config::*; + use hyper::{Body, Method, Request, Response}; use serde::{Deserialize, Serialize}; @@ -12,57 +15,30 @@ use crate::{domain, service, util}; pub struct Service { domain_manager: sync::Arc, - target_a: net::Ipv4Addr, - passphrase: String, - http_domain: domain::Name, + cert_resolver: sync::Arc, handlebars: handlebars::Handlebars<'static>, -} - -pub struct HTTPSParams { - pub listen_addr: net::SocketAddr, - pub cert_resolver: sync::Arc, + config: Config, } pub fn new( task_stack: &mut util::TaskStack, domain_manager: sync::Arc, - target_a: net::Ipv4Addr, - passphrase: String, - http_listen_addr: net::SocketAddr, - http_domain: domain::Name, - https_params: Option, + cert_resolver: sync::Arc, + config: Config, ) -> sync::Arc { + let https_enabled = config.https_addr.is_some(); let service = sync::Arc::new(Service { domain_manager: domain_manager.clone(), - target_a, - passphrase, - http_domain: http_domain.clone(), + cert_resolver, handlebars: tpl::get(), + config, }); - task_stack.push_spawn(|canceller| { - tasks::listen_http( - service.clone(), - canceller, - http_listen_addr, - http_domain.clone(), - ) - }); + task_stack.push_spawn(|canceller| tasks::listen_http(service.clone(), canceller)); - if let Some(https_params) = https_params { - task_stack.push_spawn(|canceller| { - tasks::listen_https( - service.clone(), - canceller, - https_params.cert_resolver.clone(), - https_params.listen_addr, - http_domain.clone(), - ) - }); - - task_stack.push_spawn(|canceller| { - tasks::cert_refresher(domain_manager.clone(), canceller, http_domain.clone()) - }); + if https_enabled { + task_stack.push_spawn(|canceller| tasks::listen_https(service.clone(), canceller)); + task_stack.push_spawn(|canceller| tasks::cert_refresher(service.clone(), canceller)); } service @@ -277,7 +253,7 @@ impl<'svc> Service { Response { domain: args.domain, flat_config: config.into(), - target_a: self.target_a, + target_a: self.config.target_a, challenge_token: config_hash, }, ) @@ -288,7 +264,7 @@ impl<'svc> Service { args: DomainSyncArgs, domain_config: service::util::FlatConfig, ) -> Response { - if args.passphrase != self.passphrase.as_str() { + if args.passphrase != self.config.passphrase.as_str() { return self.render_error_page(401, "Incorrect passphrase"); } @@ -358,8 +334,8 @@ impl<'svc> Service { .map(strip_port), req.uri().host().map(strip_port), ) { - (Some(h), _) if h != self.http_domain.as_str() => Some(h), - (_, Some(h)) if h != self.http_domain.as_str() => Some(h), + (Some(h), _) if h != self.config.primary_domain.as_str() => Some(h), + (_, Some(h)) if h != self.config.primary_domain.as_str() => Some(h), _ => None, } .and_then(|h| domain::Name::from_str(h).ok()); diff --git a/src/service/http/config.rs b/src/service/http/config.rs new file mode 100644 index 0000000..cc480b1 --- /dev/null +++ b/src/service/http/config.rs @@ -0,0 +1,12 @@ +use crate::domain; +use serde::Deserialize; +use std::net; + +#[derive(Deserialize)] +pub struct Config { + pub http_addr: net::SocketAddr, + pub https_addr: Option, + pub primary_domain: domain::Name, + pub target_a: net::Ipv4Addr, + pub passphrase: String, +} diff --git a/src/service/http/tasks.rs b/src/service/http/tasks.rs index cc5e247..7bef7e7 100644 --- a/src/service/http/tasks.rs +++ b/src/service/http/tasks.rs @@ -1,7 +1,7 @@ use crate::error::unexpected::{self, Mappable}; -use crate::{domain, service}; +use crate::service; -use std::{convert, future, net, sync}; +use std::{convert, future, sync}; use futures::StreamExt; use tokio_util::sync::CancellationToken; @@ -9,9 +9,10 @@ use tokio_util::sync::CancellationToken; pub async fn listen_http( service: sync::Arc, canceller: CancellationToken, - addr: net::SocketAddr, - domain: domain::Name, ) -> Result<(), unexpected::Error> { + let addr = service.config.http_addr.clone(); + let primary_domain = service.config.primary_domain.clone(); + let make_service = hyper::service::make_service_fn(move |_| { let service = service.clone(); @@ -25,7 +26,11 @@ pub async fn listen_http( async move { Ok::<_, convert::Infallible>(hyper_service) } }); - log::info!("Listening on http://{}:{}", domain.as_str(), addr.port()); + log::info!( + "Listening on http://{}:{}", + primary_domain.as_str(), + addr.port(), + ); let server = hyper::Server::bind(&addr).serve(make_service); let graceful = server.with_graceful_shutdown(async { @@ -38,10 +43,11 @@ pub async fn listen_http( pub async fn listen_https( service: sync::Arc, canceller: CancellationToken, - cert_resolver: sync::Arc, - addr: net::SocketAddr, - domain: domain::Name, ) -> Result<(), unexpected::Error> { + let cert_resolver = service.cert_resolver.clone(); + let addr = service.config.https_addr.unwrap().clone(); + let primary_domain = service.config.primary_domain.clone(); + let make_service = hyper::service::make_service_fn(move |_| { let service = service.clone(); @@ -77,7 +83,11 @@ pub async fn listen_https( let incoming = hyper::server::accept::from_stream(incoming); - log::info!("Listening on https://{}:{}", domain.as_str(), addr.port()); + log::info!( + "Listening on https://{}:{}", + primary_domain.as_str(), + addr.port() + ); let server = hyper::Server::builder(incoming).serve(make_service); @@ -89,12 +99,13 @@ pub async fn listen_https( } pub async fn cert_refresher( - domain_manager: sync::Arc, + service: sync::Arc, canceller: CancellationToken, - http_domain: domain::Name, ) -> Result<(), unexpected::Error> { use tokio::time; + let domain_manager = service.domain_manager.clone(); + let primary_domain = service.config.primary_domain.clone(); let mut interval = time::interval(time::Duration::from_secs(60 * 60)); loop { @@ -104,12 +115,12 @@ pub async fn cert_refresher( } _ = domain_manager - .sync_cert(http_domain.clone()) + .sync_cert(primary_domain.clone()) .await .inspect_err(|err| { log::error!( "Error while getting cert for {}: {err}", - http_domain.as_str() + primary_domain.as_str() ) });