Reputation: 2534
I've moved from using actix-web
3.x.x to 4.x.x. and the code that's been running perfectly fine before is now throwing this error:
the trait bound `fn(actix_web::web::Query<TweetParams>, actix_web::web::Data<Pool<Postgres>>) -> impl std::future::Future {tweets4}: Handler<_, _>` is not satisfied
--> src/routes/all_routes.rs:74:14
|
74 | pub async fn tweets4(
| ^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(actix_web::web::Query<TweetParams>, actix_web::web::Data<Pool<Postgres>>) -> impl std::future::Future {tweets4}`
After some googling it seems there is indeed a Handler
trait in the actix
ecosystem (however, not actix-web I think).
I can't figure out where I need to implement the trait. The error message seems to suggest that it's missing on the function itself, but my understanding is that you can only implement traits on structs
and enums
, not functions?
Here's the handler code:
#[get("/tweets4")]
pub async fn tweets4(
form: web::Query<TweetParams>,
pool: web::Data<PgPool>,
) -> Result<HttpResponse, HttpResponse> {
let fake_json_data = r#"
{ "name": "hi" }
"#;
let v: Value = serde_json::from_str(fake_json_data)
.map_err(|_| HttpResponse::InternalServerError().finish())?;
sqlx::query!(
r#"
INSERT INTO users
(id, created_at, twitter_user_id, twitter_name, twitter_handle, profile_image, profile_url, entire_user)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
"#,
Uuid::new_v4(),
Utc::now(),
"3",
"4",
"5",
"6",
"7",
v,
)
.execute(pool.as_ref())
.await
.map_err(|e| {
println!("error is {}", e);
HttpResponse::InternalServerError().finish()
})?;
Ok(HttpResponse::Ok().finish())
}
What am I getting wrong?
If helpful, the entire project is on github here.
Upvotes: 9
Views: 7440
Reputation: 2082
I had a very similar issue. The root cause of the problem was that I forgot to use an async
function. In short, When looking at the documentation at https://actix.rs/docs/response/#json-response, make sure to use async fn index(name: web::Path<String>) -> Result<impl Responder>
and not fn index(name: web::Path<String>) -> Result<impl Responder>
.
Upvotes: 8
Reputation: 21
If you still face the same error, another solution is just to switch to 1.0.8
Upvotes: 1
Reputation: 2534
After sufficient trial and error I discovered that:
HttpResponse
error type and I had to replace with my own:#[derive(Debug)]
pub struct MyError(String); // <-- needs debug and display
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "A validation error occured on the input.")
}
}
impl ResponseError for MyError {} // <-- key
#[get("/tweets4")]
pub async fn tweets4(
form: web::Query<TweetParams>,
pool: web::Data<PgPool>,
) -> Result<HttpResponse, MyError> {
let fake_json_data = r#"
{ "name": "hi" }
"#;
let v: Value = serde_json::from_str(fake_json_data).map_err(|e| {
println!("error is {}", e);
MyError(String::from("oh no")) // <-- here
})?;
sqlx::query!(
//query
)
.execute(pool.as_ref())
.await
.map_err(|e| {
println!("error is {}", e);
MyError(String::from("oh no")) // <-- and here
})?;
Ok(HttpResponse::Ok().finish())
}
Hope helps someone in the future!
Upvotes: 6