From c7e3179a198ae8189fe2bfa39e947828b17c36cb Mon Sep 17 00:00:00 2001 From: Harold Sun Date: Tue, 14 Mar 2023 22:44:28 +0800 Subject: [PATCH] Separate HTTPS and HTTP adapter (#196) This prevents issues when ca certs are not available in custom docker images. --- src/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++++------------- src/main.rs | 33 +++++++++++++++++++--------- 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 30a81176..fb8d055b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ use http::{ use hyper::{ body, body::HttpBody, - client::{Client, HttpConnector}, + client::{connect::Connect, Client, HttpConnector}, Body, }; use hyper_rustls::HttpsConnector; @@ -99,8 +99,8 @@ impl AdapterOptions { } #[derive(Clone)] -pub struct Adapter { - client: Arc>>, +pub struct Adapter { + client: Arc>, healthcheck_url: Url, healthcheck_protocol: Protocol, async_init: bool, @@ -110,11 +110,11 @@ pub struct Adapter { compression: bool, } -impl Adapter { - /// Create a new Adapter instance. - /// This function initializes a new HTTP client +impl Adapter> { + /// Create a new HTTPS Adapter instance. + /// This function initializes a new HTTPS client /// to talk with the web server. - pub fn new(options: &AdapterOptions) -> Adapter { + pub fn new_https(options: &AdapterOptions) -> Adapter> { if let Some(cert_file) = &options.tls_cert_file { env::set_var("SSL_CERT_FILE", cert_file); } @@ -133,10 +133,7 @@ impl Adapter { let client = Client::builder().pool_idle_timeout(Duration::from_secs(4)).build(https); - let schema = match options.enable_tls { - true => "https", - false => "http", - }; + let schema = "https"; let healthcheck_url = format!( "{}://{}:{}{}", @@ -160,15 +157,47 @@ impl Adapter { compression: options.compression, } } +} + +impl Adapter { + /// Create a new HTTP Adapter instance. + /// This function initializes a new HTTP client + /// to talk with the web server. + pub fn new(options: &AdapterOptions) -> Adapter { + let client = Client::builder() + .pool_idle_timeout(Duration::from_secs(4)) + .build(HttpConnector::new()); + + let schema = "http"; + + let healthcheck_url = format!( + "{}://{}:{}{}", + schema, options.host, options.readiness_check_port, options.readiness_check_path + ) + .parse() + .unwrap(); + + let domain = format!("{}://{}:{}", schema, options.host, options.port) + .parse() + .unwrap(); - /// Switch the default HTTP client with a different one. - pub fn with_client(self, client: Client>) -> Self { Adapter { client: Arc::new(client), - ..self + healthcheck_url, + healthcheck_protocol: options.readiness_check_protocol, + domain, + base_path: options.base_path.clone(), + async_init: options.async_init, + ready_at_init: Arc::new(AtomicBool::new(false)), + compression: options.compression, } } +} +impl Adapter +where + C: Connect + Clone + Send + Sync + 'static, +{ /// Register a Lambda Extension to ensure /// that the adapter is loaded before any Lambda function /// associated with it. @@ -350,7 +379,10 @@ impl Adapter { /// Implement a `Tower.Service` that sends the requests /// to the web server. -impl Service for Adapter { +impl Service for Adapter +where + C: Connect + Clone + Send + Sync + 'static, +{ type Response = Response; type Error = Error; type Future = Pin> + Send>>; diff --git a/src/main.rs b/src/main.rs index db407d6a..0a9334fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,15 +15,28 @@ async fn main() -> Result<(), Error> { // get configuration options from environment variables let options = AdapterOptions::from_env(); - // create an adapter - let mut adapter = Adapter::new(&options); + match options.enable_tls { + false => { + // create a HTTP adapter + let mut adapter = Adapter::new(&options); + // register the adapter as an extension + adapter.register_default_extension(); + // check if the web application is ready + adapter.check_init_health().await; + // start lambda runtime after the web application is ready + adapter.run().await.expect("lambda runtime failed"); + } + true => { + // create a HTTPS adapter + let mut adapter = Adapter::new_https(&options); + // register the adapter as an extension + adapter.register_default_extension(); + // check if the web application is ready + adapter.check_init_health().await; + // start lambda runtime after the web application is ready + adapter.run().await.expect("lambda runtime failed"); + } + } - // register the adapter as an extension - adapter.register_default_extension(); - - // check if the web application is ready - adapter.check_init_health().await; - - // start lambda runtime after the web application is ready - adapter.run().await + Ok(()) }