6

I want to instantiate a struct instance and then call a method of that instance in an api route. Here's an example of what I want, but it results in an error:

use axum::{http::StatusCode, routing::get, Router, Server};

#[derive(Clone)]
struct Api {
    name: String
}

impl Api {
    async fn hello(&self) -> Result<String, StatusCode> {
        Ok(format!("Hello {}!", self.name))
    }
}

#[tokio::main]
async fn main() {
    let api = Api { name: "Alice".to_owned() };

    let app = Router::new()
        .route("/hello-user", get(api.hello));

    Server::bind(&([127, 0, 0, 1], 3000).into())
        .serve(app.into_make_service())
        .await
        .unwrap();
}
error[E0615]: attempted to take value of method `hello` on type `Api`
  --> src\main.rs:19:39
   |
19 |         .route("/hello-user", get(api.hello));
   |                                       ^^^^^ method, not a field

I have attempted to get around this by defining a function which calls the instance method:

let hello_method = move || async { 
    match api.hello().await {
        Ok(response) => response,
        Err(_) => "error".to_owned(),
    }
};

let app = Router::new()
    .route("/hello-user", get(hello_method));

However, with this I get a "lifetime may not live long enough" error. How should I go about calling an instance method from an axum server route?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
SomeRandomPhysicist
  • 1,531
  • 4
  • 19
  • 42

1 Answers1

6

You can move api into the closure and then into the future:

let hello_method = move || async move { 
    match api.hello().await {
        Ok(response) => response,
        Err(_) => "error".to_owned(),
    }
};

or with using of nightly feature #![feature(async_closure)]:

let hello_method = async move || { 
    match api.hello().await {
        Ok(response) => response,
        Err(_) => "error".to_owned(),
    }
};
kmdreko
  • 42,554
  • 6
  • 57
  • 106
USA LOVER
  • 145
  • 5
  • 2
    If you use `api` for multiple routes, you'll either need to clone it for each route or use shared ownership by wrapping it in an `Arc`. – kmdreko Sep 18 '22 at 23:18