1

I have a provider setup like this:

#[async_trait]
pub trait AsyncKeyProvider {
    async fn get_key_async(&mut self, key_id: &str) -> Result<Option<Jwk>, ()>;
}


#[derive(Clone)]
pub struct GoogleKeyProvider {
    cached: Option<JwkSet>,
    expiration_time: Instant,
}


impl AsyncKeyProvider for GoogleKeyProvider {
    async fn get_key_async(&mut self, key_id: &str) -> Result<Option<Jwk>, ()> {
        {...}
    }
}

I'm trying to pass an instance of GoogleKeyProvider to my validate handler, using the built-in app_data() method that's in actix-web, like so:

let key_provider: web::Data<dyn AsyncKeyProvider> = web::Data::from(Arc::new(GoogleKeyProvider));

let server = HttpServer::new(move || {
    App::new()
        .app_data(key_provider.clone())
        .wrap(Logger::default())
        .route("/ping", web::get().to(health_check))
        .route("/validate", web::post().to(validate))
})
.listen(listener)?
.run();
Ok(server)

With validate having a signature of:

pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<dyn AsyncKeyProvider>) -> impl Responder {
    {...}
}

As I understand it from this answer: https://stackoverflow.com/a/65646165, this should make it so that I can access the provider object using let provider_object = provider.into_inner(); or something similar.

However, I instead get the following errors:

error[E0599]: the method `into_inner` exists for struct `actix_web::web::Data<dyn key_providers::key_providers::AsyncKeyProvider>`, but its trait bounds were not satisfied
  --> src\routes\validate.rs:26:36
   |
26 |     let provider_object = provider.into_inner()
   |                                    ^^^^^^^^^^ method cannot be called on `actix_web::web::Data<dyn key_providers::key_providers::AsyncKeyProvider>` due to unsatisfied trait bounds
   |
  ::: src\key_providers\key_providers.rs:53:1
   |
53 | pub trait AsyncKeyProvider {
   | -------------------------- doesn't satisfy `_: std::marker::Sized`
   |
   = note: the following trait bounds were not satisfied:
           `dyn key_providers::key_providers::AsyncKeyProvider: std::marker::Sized`

error[E0277]: the size for values of type `dyn key_providers::key_providers::AsyncKeyProvider` cannot be known at compilation time
   --> src\startup.rs:9:73
    |
9   |     let key_provider: web::Data<dyn AsyncKeyProvider> = web::Data::from(Arc::new(GoogleKeyProvider));
    |                                                                         ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn key_providers::key_providers::AsyncKeyProvider`
note: required by `Arc::<T>::new`
   --> C:\Users\dantd\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\sync.rs:342:5
    |
342 |     pub fn new(data: T) -> Arc<T> {
    |     ^^^^^^^^^^^^^^^^^^^

Would anyone be able to help me figure out how exactly to solve this? I've done some looking into std::marker::Sized but I can't figure out how to use that to address this.

dantdj
  • 1,237
  • 3
  • 19
  • 40
  • I included the actix-web tag as this is technically going through methods for that framework, but I'm reasonably sure this is going to be a core Rust thing that I'm not understanding right now, so feel free to remove the tag if desired – dantdj Sep 01 '21 at 18:00

1 Answers1

3

The parameter provider: web::Data<dyn AsyncKeyProvider> doesn't have a known size at compilation time because it can contain any of the implementing types. You need to use type web::Data<std::boxed::Box<dyn AsyncKeyProvider>> instead.

loa_in_
  • 1,030
  • 9
  • 20
  • Is that keeping to the `into_inner` call? If I swap the parameter to be of the type you mentioned I get this error instead: `expected struct key_providers::key_providers::GoogleKeyProvider` found struct `Arc>` – dantdj Sep 01 '21 at 18:58
  • Ah right, just realized that's gonna be because it's using the trait still and I need to force it into the implementation? – dantdj Sep 01 '21 at 19:00