Config struct for http server

This commit is contained in:
Brian Picciano 2023-07-09 13:43:38 +02:00
parent 9d44593e73
commit 254d9c63d0
4 changed files with 62 additions and 65 deletions

View File

@ -123,16 +123,14 @@ async fn main() {
let _ = domani::service::http::new( let _ = domani::service::http::new(
&mut task_stack, &mut task_stack,
domain_manager.clone(), domain_manager.clone(),
config.domain_checker_target_a, domain_manager.clone(),
config.passphrase, domani::service::http::Config {
config.http_listen_addr, http_addr: config.http_listen_addr,
config.http_domain, https_addr: config.https_listen_addr,
config primary_domain: config.http_domain,
.https_listen_addr target_a: config.domain_checker_target_a,
.map(|listen_addr| domani::service::http::HTTPSParams { passphrase: config.passphrase,
listen_addr, },
cert_resolver: domain_manager.clone(),
}),
); );
let mut signals = let mut signals =

View File

@ -1,6 +1,9 @@
mod config;
mod tasks; mod tasks;
mod tpl; mod tpl;
pub use config::*;
use hyper::{Body, Method, Request, Response}; use hyper::{Body, Method, Request, Response};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -12,57 +15,30 @@ use crate::{domain, service, util};
pub struct Service { pub struct Service {
domain_manager: sync::Arc<dyn domain::manager::Manager>, domain_manager: sync::Arc<dyn domain::manager::Manager>,
target_a: net::Ipv4Addr, cert_resolver: sync::Arc<dyn rustls::server::ResolvesServerCert>,
passphrase: String,
http_domain: domain::Name,
handlebars: handlebars::Handlebars<'static>, handlebars: handlebars::Handlebars<'static>,
} config: Config,
pub struct HTTPSParams {
pub listen_addr: net::SocketAddr,
pub cert_resolver: sync::Arc<dyn rustls::server::ResolvesServerCert>,
} }
pub fn new( pub fn new(
task_stack: &mut util::TaskStack<unexpected::Error>, task_stack: &mut util::TaskStack<unexpected::Error>,
domain_manager: sync::Arc<dyn domain::manager::Manager>, domain_manager: sync::Arc<dyn domain::manager::Manager>,
target_a: net::Ipv4Addr, cert_resolver: sync::Arc<dyn rustls::server::ResolvesServerCert>,
passphrase: String, config: Config,
http_listen_addr: net::SocketAddr,
http_domain: domain::Name,
https_params: Option<HTTPSParams>,
) -> sync::Arc<Service> { ) -> sync::Arc<Service> {
let https_enabled = config.https_addr.is_some();
let service = sync::Arc::new(Service { let service = sync::Arc::new(Service {
domain_manager: domain_manager.clone(), domain_manager: domain_manager.clone(),
target_a, cert_resolver,
passphrase,
http_domain: http_domain.clone(),
handlebars: tpl::get(), handlebars: tpl::get(),
config,
}); });
task_stack.push_spawn(|canceller| { task_stack.push_spawn(|canceller| tasks::listen_http(service.clone(), canceller));
tasks::listen_http(
service.clone(),
canceller,
http_listen_addr,
http_domain.clone(),
)
});
if let Some(https_params) = https_params { if https_enabled {
task_stack.push_spawn(|canceller| { task_stack.push_spawn(|canceller| tasks::listen_https(service.clone(), canceller));
tasks::listen_https( task_stack.push_spawn(|canceller| tasks::cert_refresher(service.clone(), canceller));
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())
});
} }
service service
@ -277,7 +253,7 @@ impl<'svc> Service {
Response { Response {
domain: args.domain, domain: args.domain,
flat_config: config.into(), flat_config: config.into(),
target_a: self.target_a, target_a: self.config.target_a,
challenge_token: config_hash, challenge_token: config_hash,
}, },
) )
@ -288,7 +264,7 @@ impl<'svc> Service {
args: DomainSyncArgs, args: DomainSyncArgs,
domain_config: service::util::FlatConfig, domain_config: service::util::FlatConfig,
) -> Response<Body> { ) -> Response<Body> {
if args.passphrase != self.passphrase.as_str() { if args.passphrase != self.config.passphrase.as_str() {
return self.render_error_page(401, "Incorrect passphrase"); return self.render_error_page(401, "Incorrect passphrase");
} }
@ -358,8 +334,8 @@ impl<'svc> Service {
.map(strip_port), .map(strip_port),
req.uri().host().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.config.primary_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),
_ => None, _ => None,
} }
.and_then(|h| domain::Name::from_str(h).ok()); .and_then(|h| domain::Name::from_str(h).ok());

View File

@ -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<net::SocketAddr>,
pub primary_domain: domain::Name,
pub target_a: net::Ipv4Addr,
pub passphrase: String,
}

View File

@ -1,7 +1,7 @@
use crate::error::unexpected::{self, Mappable}; 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 futures::StreamExt;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
@ -9,9 +9,10 @@ use tokio_util::sync::CancellationToken;
pub async fn listen_http( pub async fn listen_http(
service: sync::Arc<service::http::Service>, service: sync::Arc<service::http::Service>,
canceller: CancellationToken, canceller: CancellationToken,
addr: net::SocketAddr,
domain: domain::Name,
) -> Result<(), unexpected::Error> { ) -> 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 make_service = hyper::service::make_service_fn(move |_| {
let service = service.clone(); let service = service.clone();
@ -25,7 +26,11 @@ pub async fn listen_http(
async move { Ok::<_, convert::Infallible>(hyper_service) } 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 server = hyper::Server::bind(&addr).serve(make_service);
let graceful = server.with_graceful_shutdown(async { let graceful = server.with_graceful_shutdown(async {
@ -38,10 +43,11 @@ pub async fn listen_http(
pub async fn listen_https( pub async fn listen_https(
service: sync::Arc<service::http::Service>, service: sync::Arc<service::http::Service>,
canceller: CancellationToken, canceller: CancellationToken,
cert_resolver: sync::Arc<dyn rustls::server::ResolvesServerCert>,
addr: net::SocketAddr,
domain: domain::Name,
) -> Result<(), unexpected::Error> { ) -> 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 make_service = hyper::service::make_service_fn(move |_| {
let service = service.clone(); let service = service.clone();
@ -77,7 +83,11 @@ pub async fn listen_https(
let incoming = hyper::server::accept::from_stream(incoming); 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); let server = hyper::Server::builder(incoming).serve(make_service);
@ -89,12 +99,13 @@ pub async fn listen_https(
} }
pub async fn cert_refresher( pub async fn cert_refresher(
domain_manager: sync::Arc<dyn domain::manager::Manager>, service: sync::Arc<service::http::Service>,
canceller: CancellationToken, canceller: CancellationToken,
http_domain: domain::Name,
) -> Result<(), unexpected::Error> { ) -> Result<(), unexpected::Error> {
use tokio::time; 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)); let mut interval = time::interval(time::Duration::from_secs(60 * 60));
loop { loop {
@ -104,12 +115,12 @@ pub async fn cert_refresher(
} }
_ = domain_manager _ = domain_manager
.sync_cert(http_domain.clone()) .sync_cert(primary_domain.clone())
.await .await
.inspect_err(|err| { .inspect_err(|err| {
log::error!( log::error!(
"Error while getting cert for {}: {err}", "Error while getting cert for {}: {err}",
http_domain.as_str() primary_domain.as_str()
) )
}); });