@@ -21,15 +21,16 @@ use std::fmt::{Debug, Formatter};
2121use http:: StatusCode ;
2222use iceberg:: { Error , ErrorKind , Result } ;
2323use reqwest:: header:: HeaderMap ;
24- use reqwest:: { Client , IntoUrl , Method , Request , RequestBuilder , Response } ;
24+ use reqwest:: { IntoUrl , Method , Request , Response } ;
25+ use reqwest_middleware:: { ClientBuilder , ClientWithMiddleware , RequestBuilder } ;
2526use serde:: de:: DeserializeOwned ;
2627use tokio:: sync:: Mutex ;
2728
2829use crate :: RestCatalogConfig ;
2930use crate :: types:: { ErrorResponse , TokenResponse } ;
3031
3132pub ( crate ) struct HttpClient {
32- client : Client ,
33+ client : ClientWithMiddleware ,
3334
3435 /// The token to be used for authentication.
3536 ///
@@ -56,10 +57,39 @@ impl Debug for HttpClient {
5657
5758impl HttpClient {
5859 /// Create a new http client.
60+ #[ allow( unused_mut) ]
5961 pub fn new ( cfg : & RestCatalogConfig ) -> Result < Self > {
6062 let extra_headers = cfg. extra_headers ( ) ?;
63+ let mut client_builder = ClientBuilder :: new ( cfg. client ( ) . unwrap_or_default ( ) ) ;
64+
65+ #[ cfg( feature = "sigv4" ) ]
66+ if cfg. sigv4_enabled ( ) {
67+ let mut sigv4_middleware = crate :: middleware:: sigv4:: SigV4Middleware :: new (
68+ & cfg. base_url ( ) ,
69+ cfg. signing_name ( ) . as_deref ( ) . unwrap_or ( "glue" ) ,
70+ cfg. signing_region ( ) . as_deref ( ) ,
71+ ) ;
72+
73+ if let ( Some ( access_key_id) , Some ( secret_access_key) ) =
74+ ( cfg. access_key_id ( ) , cfg. secret_access_key ( ) )
75+ {
76+ sigv4_middleware = sigv4_middleware. with_credentials (
77+ access_key_id,
78+ secret_access_key,
79+ cfg. session_token ( ) ,
80+ ) ;
81+ }
82+
83+ if let Some ( role_arn) = cfg. role_arn ( ) {
84+ sigv4_middleware = sigv4_middleware. with_role ( role_arn, cfg. role_session_name ( ) ) ;
85+ }
86+
87+ client_builder = client_builder. with ( sigv4_middleware) ;
88+ }
89+
6190 Ok ( HttpClient {
62- client : cfg. client ( ) . unwrap_or_default ( ) ,
91+ client : client_builder. build ( ) ,
92+
6393 token : Mutex :: new ( cfg. token ( ) ) ,
6494 token_endpoint : cfg. get_token_endpoint ( ) ,
6595 credential : cfg. credential ( ) ,
@@ -77,8 +107,26 @@ impl HttpClient {
77107 . then ( || cfg. extra_headers ( ) )
78108 . transpose ( ) ?
79109 . unwrap_or ( self . extra_headers ) ;
110+
111+ let client = match cfg. client ( ) {
112+ Some ( client) => {
113+ let mut client_builder = ClientBuilder :: new ( client) ;
114+ #[ cfg( feature = "sigv4" ) ]
115+ if cfg. sigv4_enabled ( ) {
116+ client_builder =
117+ client_builder. with ( crate :: middleware:: sigv4:: SigV4Middleware :: new (
118+ & cfg. base_url ( ) ,
119+ cfg. signing_name ( ) . as_deref ( ) . unwrap_or ( "glue" ) ,
120+ cfg. signing_region ( ) . as_deref ( ) ,
121+ ) ) ;
122+ }
123+ client_builder. build ( )
124+ }
125+ None => ClientBuilder :: from_client ( self . client ) . build ( ) ,
126+ } ;
127+
80128 Ok ( HttpClient {
81- client : cfg . client ( ) . unwrap_or ( self . client ) ,
129+ client,
82130 token : Mutex :: new ( cfg. token ( ) . or_else ( || self . token . into_inner ( ) ) ) ,
83131 token_endpoint : if !cfg. get_token_endpoint ( ) . is_empty ( ) {
84132 cfg. get_token_endpoint ( )
0 commit comments