Axum type checking forbids me to use futures

150 views Asked by At

I am writing the rust code of an axum endpoint. This endpoint fetches data from a db. I then want to create futures to call an API using these data (so that I can send all queries at once). It is not fully finished but the syntax seems correct, but weirdly it doesn't compile with an error I don't understand.

Here is my code:


pub async fn handler(
    State(state): State<Arc<AppState>>,
    Query(query): Query<AddrQuery>,
) -> impl IntoResponse {
    let id_owners = state
        .starknetid_db
        .collection::<mongodb::bson::Document>("id_owners");

    let pipeline = [
        // mongodb pipeline
    ];

    let aggregate_options = AggregateOptions::default();
    let cursor = id_owners.aggregate(pipeline, aggregate_options).await;

    match cursor {
        Ok(mut cursor) => {
            let mut temp_full_ids = Vec::new();
            while let Some(doc) = cursor.next().await {
                if let Ok(doc) = doc {
                    let id = FieldElement::from_hex_be(
                        &doc.get_str("id").unwrap_or_default().to_owned(),
                    )
                    .unwrap()
                    .to_string();
                    let domain = doc.get_str("domain").ok().map(String::from);
                    let domain_expiry = doc.get_i32("domain_expiry").ok();
                    let pp_verifier_data = doc.get_array("pp_verifier_data").ok();
                    let mut pp_url_future: Option<Pin<Box<dyn Future<Output = Option<String>>>>> =
                        None;
                    if let Some(data) = pp_verifier_data {
                        if data.len() >= 2 {
                            if let (Some(contract_data), Some(id_data)) = (data.get(0), data.get(1))
                            {
                                if let (Bson::Document(contract_doc), Bson::Document(id_doc)) =
                                    (contract_data, id_data)
                                {
                                    if let (Ok(contract_str), Ok(data_id)) = (
                                        contract_doc.get_str("data"),
                                        id_doc.get_array("extended_data"),
                                    ) {
                                        let id_felts: Vec<String> = data_id
                                            .into_iter()
                                            .map(|b| match b {
                                                Bson::String(s) => s.to_owned(),
                                                _ => b.to_string(),
                                            })
                                            .collect();
                                        let id = to_u256(
                                            id_felts.get(0).unwrap(),
                                            id_felts.get(1).unwrap(),
                                        )
                                        .to_string();
                                        let api_url = state.conf.starkscan.api_url.clone();
                                        let api_key = state.conf.starkscan.api_key.clone();
                                        let contract_str = contract_str.to_string();
                                        let id = id.to_string();

                                        pp_url_future = Some(Box::pin(async move {
                                            fetch_img_url(&api_url, &api_key, contract_str, id)
                                                .await
                                        })
                                            as Pin<Box<dyn Future<Output = Option<String>>>>);
                                    }
                                }
                            }
                        }
                    }
                    temp_full_ids.push(TempsFullId {
                        id,
                        domain,
                        domain_expiry,
                        pp_url_future,
                    });
                }
            }
            let response = FullIdResponse {
                full_ids: temp_full_ids
                    .iter()
                    .map(|id| FullId {
                        id: id.id.clone(),
                        domain: id.domain.clone(),
                        domain_expiry: id.domain_expiry,
                        pp_url: None,
                    })
                    .collect::<Vec<FullId>>(),
            };
            (StatusCode::OK, Json(response)).into_response()
        }
        Err(_) => get_error("Error while fetching from database".to_string()),
    }
}

And on my router, when trying to add the route:

        .route(
            "/addr_to_full_ids",
            get(endpoints::addr_to_full_ids::handler),
        )

I get:

   Compiling starknetid_server v0.1.0 (/Users/thomas/starknetid/api.starknet.id)
error[E0277]: the trait bound `fn(axum::extract::State<Arc<AppState>>, Query<addr_to_full_ids::AddrQuery>) -> impl futures::Future<Output = impl IntoResponse> {addr_to_full_ids::handler}: Handler<_, _, _>` is not satisfied
   --> src/main.rs:66:17
    |
66  |             get(endpoints::addr_to_full_ids::handler),
    |             --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(axum::extract::State<Arc<AppState>>, Query<addr_to_full_ids::AddrQuery>) -> impl futures::Future<Output = impl IntoResponse> {addr_to_full_ids::handler}`
    |             |
    |             required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S, B>`:
              <Layered<L, H, T, S, B, B2> as Handler<T, S, B2>>
              <MethodRouter<S, B> as Handler<(), S, B>>
note: required by a bound in `axum::routing::get`
   --> /Users/thomas/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.6.18/src/routing/method_routing.rs:403:1
    |
403 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `starknetid_server` (bin "starknetid_server") due to previous error
0

There are 0 answers