From c299c2f5b876026c0d199781560e0e9eba011914 Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Mon, 17 May 2021 11:24:33 +0200 Subject: [PATCH] feat: add reqwest ClientBuilder parameter to schema registry builder This change enables the ability to add any arbitrary change to the HTTP client used by the registry client. Therein, we get the chance to add TLS and more notably mTLS support (even with whichever chain we wish, such as rustls). This change is required as we wish to use a registry protected with mTLS, and will therefore need special configuration from reqwest. Signed-off-by: Mariell Hoversholm --- src/async_impl/schema_registry.rs | 47 ++++++++++++++++++++++--------- src/blocking/schema_registry.rs | 47 ++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/async_impl/schema_registry.rs b/src/async_impl/schema_registry.rs index 3fdc72e..b52c8b5 100644 --- a/src/async_impl/schema_registry.rs +++ b/src/async_impl/schema_registry.rs @@ -9,7 +9,7 @@ use futures::future::{BoxFuture, FutureExt}; use futures::stream::{self, StreamExt}; use reqwest::header; use reqwest::header::{HeaderName, ACCEPT, CONTENT_TYPE}; -use reqwest::Client; +use reqwest::{Client, ClientBuilder}; use serde_json::{json, Map, Value}; use crate::error::SRCError; @@ -130,8 +130,33 @@ impl SrSettingsBuilder { self } + /// Build the settings with your own HTTP client. + /// + /// This method allows you to bring your own TLS client and configuration. + /// + /// NOTE: The other values (headers, proxy, etc.) will still be merged in + /// and they all have higher precedence than your own builder's configuration. + /// This means that if you set a proxy both with this builde rand your + /// client's builder, this builder will overwrite the client's builder. + pub fn build_with(&mut self, builder: ClientBuilder) -> Result { + let client = self.build_client(builder)?; + let urls = self.urls.clone(); + let authorization = self.authorization.clone(); + Ok(SrSettings { + urls, + client, + authorization, + }) + } + + /// Build the settings. + /// + /// If you need your own client, see `build_with`. pub fn build(&mut self) -> Result { - let mut builder = Client::builder(); + self.build_with(Client::builder()) + } + + fn build_client(&mut self, mut builder: ClientBuilder) -> Result { if !self.headers.is_empty() { let mut header_map = header::HeaderMap::new(); for (k, v) in self.headers.iter() { @@ -155,18 +180,14 @@ impl SrSettingsBuilder { }; } builder = builder.timeout(self.timeout); - let urls = self.urls.clone(); - let authorization = self.authorization.clone(); match builder.build() { - Ok(client) => Ok(SrSettings { - urls, - client, - authorization, - }), - Err(e) => Err(SRCError::non_retryable_with_cause( - e, - "could not create new client", - )), + Ok(client) => Ok(client), + Err(e) => { + return Err(SRCError::non_retryable_with_cause( + e, + "could not create new client", + )) + } } } } diff --git a/src/blocking/schema_registry.rs b/src/blocking/schema_registry.rs index dd6aa18..e865233 100644 --- a/src/blocking/schema_registry.rs +++ b/src/blocking/schema_registry.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use std::str; use std::time::Duration; -use reqwest::blocking::Client; +use reqwest::blocking::{Client, ClientBuilder}; use reqwest::header; use reqwest::header::{HeaderName, ACCEPT, CONTENT_TYPE}; use serde_json::{json, Map, Value}; @@ -128,8 +128,33 @@ impl SrSettingsBuilder { self } + /// Build the settings with your own HTTP client. + /// + /// This method allows you to bring your own TLS client and configuration. + /// + /// NOTE: The other values (headers, proxy, etc.) will still be merged in + /// and they all have higher precedence than your own builder's configuration. + /// This means that if you set a proxy both with this builde rand your + /// client's builder, this builder will overwrite the client's builder. + pub fn build_with(&mut self, client: ClientBuilder) -> Result { + let client = self.build_client(client)?; + let urls = self.urls.clone(); + let authorization = self.authorization.clone(); + Ok(SrSettings { + urls, + client, + authorization, + }) + } + + /// Build the settings. + /// + /// If you need your own client, see `build_with`. pub fn build(&mut self) -> Result { - let mut builder = Client::builder(); + self.build_with(Client::builder()) + } + + fn build_client(&mut self, mut builder: ClientBuilder) -> Result { if !self.headers.is_empty() { let mut header_map = header::HeaderMap::new(); for (k, v) in self.headers.iter() { @@ -153,18 +178,14 @@ impl SrSettingsBuilder { }; } builder = builder.timeout(self.timeout); - let urls = self.urls.clone(); - let authorization = self.authorization.clone(); match builder.build() { - Ok(client) => Ok(SrSettings { - urls, - client, - authorization, - }), - Err(e) => Err(SRCError::non_retryable_with_cause( - e, - "could not create new client", - )), + Ok(client) => Ok(client), + Err(e) => { + return Err(SRCError::non_retryable_with_cause( + e, + "could not create new client", + )) + } } } }