Skip to content

Commit

Permalink
Separate HTTPS and HTTP adapter (#196)
Browse files Browse the repository at this point in the history
This prevents issues when ca certs are not available in custom docker images.
  • Loading branch information
bnusunny authored Mar 14, 2023
1 parent 5e8a3f6 commit c7e3179
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 25 deletions.
62 changes: 47 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use http::{
use hyper::{
body,
body::HttpBody,
client::{Client, HttpConnector},
client::{connect::Connect, Client, HttpConnector},
Body,
};
use hyper_rustls::HttpsConnector;
Expand Down Expand Up @@ -99,8 +99,8 @@ impl AdapterOptions {
}

#[derive(Clone)]
pub struct Adapter {
client: Arc<Client<HttpsConnector<HttpConnector>>>,
pub struct Adapter<C> {
client: Arc<Client<C>>,
healthcheck_url: Url,
healthcheck_protocol: Protocol,
async_init: bool,
Expand All @@ -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<HttpsConnector<HttpConnector>> {
/// 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<HttpsConnector<HttpConnector>> {
if let Some(cert_file) = &options.tls_cert_file {
env::set_var("SSL_CERT_FILE", cert_file);
}
Expand All @@ -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!(
"{}://{}:{}{}",
Expand All @@ -160,15 +157,47 @@ impl Adapter {
compression: options.compression,
}
}
}

impl Adapter<HttpConnector> {
/// 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<HttpConnector> {
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<HttpsConnector<HttpConnector>>) -> 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<C> Adapter<C>
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.
Expand Down Expand Up @@ -350,7 +379,10 @@ impl Adapter {

/// Implement a `Tower.Service` that sends the requests
/// to the web server.
impl Service<Request> for Adapter {
impl<C> Service<Request> for Adapter<C>
where
C: Connect + Clone + Send + Sync + 'static,
{
type Response = Response<Body>;
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
Expand Down
33 changes: 23 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}

0 comments on commit c7e3179

Please sign in to comment.