Skip to content

Commit 346cdfe

Browse files
authored
Make async provide credentials async-trait compatible (#588)
1 parent 4002a74 commit 346cdfe

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

aws/rust-runtime/aws-auth/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ zeroize = "1.2.0"
1414
[dev-dependencies]
1515
http = "0.2.3"
1616
tokio = { version = "1.0", features = ["rt", "macros"] }
17+
async-trait = "0.1.50"

aws/rust-runtime/aws-auth/src/middleware.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,16 @@ impl AsyncMapRequest for CredentialsStage {
7272

7373
fn apply(&self, mut request: Request) -> BoxFuture<Result<Request, Self::Error>> {
7474
Box::pin(async move {
75-
let cred_future = {
75+
let provider = {
7676
let config = request.config();
7777
let credential_provider = config
7878
.get::<CredentialsProvider>()
7979
.ok_or(CredentialsStageError::MissingCredentialsProvider)?;
80-
credential_provider.provide_credentials()
80+
// we need to enable releasing the config lock so that we don't hold the config
81+
// lock across an await point
82+
credential_provider.clone()
8183
};
84+
let cred_future = { provider.provide_credentials() };
8285
let credentials = cred_future.await?;
8386
request.config_mut().insert(credentials);
8487
Ok(request)

aws/rust-runtime/aws-auth/src/provider.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,17 @@ impl Error for CredentialsError {
4040
}
4141

4242
pub type CredentialsResult = Result<Credentials, CredentialsError>;
43-
type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
43+
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
4444

4545
/// An asynchronous credentials provider
4646
///
4747
/// If your use-case is synchronous, you should implement [`ProvideCredentials`] instead. Otherwise,
4848
/// consider using [`async_provide_credentials_fn`] with a closure rather than directly implementing
4949
/// this trait.
5050
pub trait AsyncProvideCredentials: Send + Sync {
51-
fn provide_credentials(&self) -> BoxFuture<CredentialsResult>;
51+
fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
52+
where
53+
Self: 'a;
5254
}
5355

5456
pub type CredentialsProvider = Arc<dyn AsyncProvideCredentials>;
@@ -66,7 +68,10 @@ where
6668
T: Fn() -> F + Send + Sync,
6769
F: Future<Output = CredentialsResult> + Send + 'static,
6870
{
69-
fn provide_credentials(&self) -> BoxFuture<CredentialsResult> {
71+
fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
72+
where
73+
Self: 'a,
74+
{
7075
Box::pin((self.f)())
7176
}
7277
}
@@ -81,9 +86,13 @@ where
8186
/// use aws_auth::Credentials;
8287
/// use aws_auth::provider::async_provide_credentials_fn;
8388
///
89+
/// async fn load_credentials() -> Credentials {
90+
/// todo!()
91+
/// }
92+
///
8493
/// async_provide_credentials_fn(|| async {
8594
/// // Async process to retrieve credentials goes here
86-
/// let credentials: Credentials = todo!().await?;
95+
/// let credentials = load_credentials().await;
8796
/// Ok(credentials)
8897
/// });
8998
/// ```
@@ -107,7 +116,10 @@ impl<T> AsyncProvideCredentials for T
107116
where
108117
T: ProvideCredentials,
109118
{
110-
fn provide_credentials(&self) -> BoxFuture<CredentialsResult> {
119+
fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
120+
where
121+
Self: 'a,
122+
{
111123
let result = self.provide_credentials();
112124
Box::pin(future::ready(result))
113125
}
@@ -130,12 +142,33 @@ pub fn set_provider(config: &mut PropertyBag, provider: Arc<dyn AsyncProvideCred
130142

131143
#[cfg(test)]
132144
mod test {
145+
use crate::provider::{AsyncProvideCredentials, BoxFuture, CredentialsResult};
133146
use crate::Credentials;
147+
use async_trait::async_trait;
134148

135149
fn assert_send_sync<T: Send + Sync>() {}
136150

137151
#[test]
138152
fn creds_are_send_sync() {
139153
assert_send_sync::<Credentials>()
140154
}
155+
156+
#[async_trait]
157+
trait AnotherTrait: Send + Sync {
158+
async fn creds(&self) -> Credentials;
159+
}
160+
161+
struct AnotherTraitWrapper<T> {
162+
inner: T,
163+
}
164+
165+
impl<T: AnotherTrait> AsyncProvideCredentials for AnotherTraitWrapper<T> {
166+
fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
167+
where
168+
Self: 'a,
169+
{
170+
let inner_fut = self.inner.creds();
171+
Box::pin(async move { Ok(inner_fut.await) })
172+
}
173+
}
141174
}

0 commit comments

Comments
 (0)