0

I have been building an http server in Rust to handle requests from a React client. I am using the rocket framework to manage the server configuration and the sqlx crate to create and perform actions on a connection pool. I need asynchronous handler functions to allow awaiting the database connection within the handler, but I can't seem to get the compiler to agree with the handler's return type. I've attempted to write a custom implementation of the Responder trait for sending my User struct as a json string, but the compiler continues to suggest that my struct has inadequate implementation. I've tried responding with serde_json, which is pre-equipped with the Responder implementation, but then the compiler complains that the future generated by the async handler lacks the implementation... I am incredibly new to this inspiring but perplexing language, so I can only hope this question isn't entirely foolish... Any suggestions you have based on prior experience with orchestrating communication between a Rust mysql connection and Rocket server would be outstandingly appreciated!

Here is the main server config:

pub async fn main() {
    //
    // Rocket Server Handler
    //

    let options = Options::Index | Options::DotFiles;

    let sql_pool = db::main().await;

    rocket::ignite()
        .attach(CORS())
        .mount("/api/login", routes![login])
        .mount(
            "/",
            StaticFiles::new(concat!(env!("CARGO_MANIFEST_DIR"), "/static"), options),
        )
        .manage(DBConn {
            connection: sql_pool,
        })
        .launch();
}

And here is the login route that won't compile:

#[post("/", format = "application/json", data = "<input>")]
pub async fn login(sql_pool: State<DBConn, '_>, input: Json<LoginInput>) -> Json<String> {
    let input = input.into_inner();
    println!("{:?}", input);
    let is_valid = db::models::User::login_by_email(
        &sql_pool.connection,
        "jdiehl2236@gmail.com".to_string(),
        "supersecret".to_string(),
    )
    .await;
    let response = LoginResponse {
        username: "userguy".to_string(),
        email: "email@gmail.com".to_string(),
        success: is_valid,
    };
    Json(serde_json::to_string(&response).unwrap())
}

And the compiler error:

the trait bound `impl Future<Output = rocket_contrib::json::Json<std::string::String>>: Responder<'_>` is not satisfied
the following other types implement trait `Responder<'r>`:
  <&'r [u8] as Responder<'r>>
  <&'r str as Responder<'r>>
  <() as Responder<'r>>
  <Flash<R> as Responder<'r>>
  <JavaScript<R> as Responder<'r>>
  <JsonValue as Responder<'a>>
  <LoginResponse as Responder<'r>>
  <MsgPack<R> as Responder<'r>>
and 29 othersrustcClick for full compiler diagnostic
handler.rs(202, 20): required by a bound in `handler::<impl Outcome<rocket::Response<'r>, rocket::http::Status, rocket::Data>>::from`
cafce25
  • 15,907
  • 4
  • 25
  • 31
  • 1
    Does this answer your question? [Can I use an async fn as a handler in Rocket?](https://stackoverflow.com/questions/61323839/can-i-use-an-async-fn-as-a-handler-in-rocket) (You may be using an out of date version of Rocket.) – cdhowie Feb 05 '23 at 23:34
  • That said, I think you are doing a double JSON encoding: first convert the `response` to JSON, serialize that to a string, and then wrap that string into a json again: `"{\"username\": ...}"`. – rodrigo Feb 06 '23 at 00:06
  • Thanks, ya'll. I'll be pretty bummed if the conclusion is that I can't use async with a stable version of Rust ... Maybe there are alternatives that could be combined for a solution? Rocket + tokio async ? – Joshua Diehl Feb 06 '23 at 00:35
  • @JoshuaDiehl From what I can tell, Rocket is no longer very actively maintained. The recommended web server crates are axum or actix-web, which you should probably switch to if this is a new project. – Peter Hall Feb 06 '23 at 03:23

0 Answers0