SomeRandomPhysicist
SomeRandomPhysicist

Reputation: 1599

How to call struct method from axum server route?

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?

Upvotes: 7

Views: 2028

Answers (1)

USA LOVER
USA LOVER

Reputation: 155

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(),
    }
};

Upvotes: 6

Related Questions