@@ -21,15 +21,16 @@ use std::fmt::{Debug, Formatter};
21
21
use http:: StatusCode ;
22
22
use iceberg:: { Error , ErrorKind , Result } ;
23
23
use 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 } ;
25
26
use serde:: de:: DeserializeOwned ;
26
27
use tokio:: sync:: Mutex ;
27
28
28
29
use crate :: RestCatalogConfig ;
29
30
use crate :: types:: { ErrorResponse , TokenResponse } ;
30
31
31
32
pub ( crate ) struct HttpClient {
32
- client : Client ,
33
+ client : ClientWithMiddleware ,
33
34
34
35
/// The token to be used for authentication.
35
36
///
@@ -56,10 +57,39 @@ impl Debug for HttpClient {
56
57
57
58
impl HttpClient {
58
59
/// Create a new http client.
60
+ #[ allow( unused_mut) ]
59
61
pub fn new ( cfg : & RestCatalogConfig ) -> Result < Self > {
60
62
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
+
61
90
Ok ( HttpClient {
62
- client : cfg. client ( ) . unwrap_or_default ( ) ,
91
+ client : client_builder. build ( ) ,
92
+
63
93
token : Mutex :: new ( cfg. token ( ) ) ,
64
94
token_endpoint : cfg. get_token_endpoint ( ) ,
65
95
credential : cfg. credential ( ) ,
@@ -77,8 +107,26 @@ impl HttpClient {
77
107
. then ( || cfg. extra_headers ( ) )
78
108
. transpose ( ) ?
79
109
. 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
+
80
128
Ok ( HttpClient {
81
- client : cfg . client ( ) . unwrap_or ( self . client ) ,
129
+ client,
82
130
token : Mutex :: new ( cfg. token ( ) . or_else ( || self . token . into_inner ( ) ) ) ,
83
131
token_endpoint : if !cfg. get_token_endpoint ( ) . is_empty ( ) {
84
132
cfg. get_token_endpoint ( )
0 commit comments