[SOLVED] How can I get the properties of `std::boxed::Box<dyn futures::Future<Error=actix_web::Error, Item=actix_web::Json<enpoints::people::model::CreatePerson>>>?

#1

I try to extract data from request
let person = Json::::extract(req);
it has the type

std::boxed::Box<(dyn futures::Future<Error=actix_web::Error, Item=actix_web::Json<enpoints::people::model::CreatePerson>> + '<empty>)>

if I try to call the properties like this:

.send(CreatePerson {
            name: person.name.clone(),
            rich: person.rich,
            super_power: person.super_power,
            genius: person.genius,
        })

I get this error:

no field `name` on type `std::boxed::Box<dyn futures::Future<Error=actix_web::Error, Item=actix_web::Json<enpoints::people::model::CreatePerson>>>

How can I get the properties of the person?

The repository of the project is here
I’m really junior in rust :slight_smile:

What's everyone working on this week (47/2018)?
#2

I resolved the issue doing this:

/// Async request handler
pub fn insert_person((person, req): (Json<CreatePerson>, HttpRequest<AppState>))
    -> FutureResponse<HttpResponse> {
    req.state()
        .db
        .send(person.into_inner())
        .from_err()
        .and_then(|res| match res {
            Ok(person) => Ok(HttpResponse::Ok().json(person)),
            Err(_) => Ok(HttpResponse::InternalServerError().into()),
        })
        .responder()
}
#3

I’ve ran into the same problem, but it looks like you used an extractor in the function arguments.
I want to do it like you at the beginning: let person = Json::<Student>:extract(req); and I run into the same problems. I want to do it this way, because I can’t seem to catch any errors if the data is invalid. I’m not using state or database at the moment, so I can’t let it handle the errors.

For example, if I don’t specify a struct’s field inside my JSON request, I get no response from the server and weirdly also no panic. That doesn’t seem very Rust-like. I should get an error. I should be able to handle it, but it just gets ignored for some reason.

If I do this I get no error:

pub fn add(new_student: Json<Student>) -> Json<AddResponse> 

but doing this:

pub fn add(req: HttpRequest) -> Json<AddResponse> {
    let new_student = Json::<Student>::extract(&req);
    Json(AddResponse{message: "Success!".to_string(), new_student: new_student.into_inner()})
}

leads to this error:

error[E0277]: `dyn futures::future::Future<Item=actix_web::Json<students::Student>, Error=actix_web::Error>` doesn't implement `std::fmt::Debug`
  --> src\students\mod.rs:62:54
   |
62 |     println!("Waiting for extraction of json. {:?}", new_student);
   |                                                      ^^^^^^^^^^^ `dyn futures::future::Future<Item=actix_web::Json<students::Student>, Error=actix_web::Error>` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`

I can’t seem to resolve that future to anything. Should I use an await macro? I tried doing new_student.wait(), but it seems to block the thread forever.

I am trying to use this method of extraction: https://github.com/actix/actix-website/blob/master/content/docs/extractors.md#within-handler-functions (Option 2).

It seems like 400 Bad Request is returned. I’m not super happy with that, but it’s good enough.

#4

@jcubed could you provide me the repository link? maybe running your example I can answer your question

#5

Here you go: https://github.com/JakubKoralewski/dziennik_rust/tree/d6ccb70bdd34165ff3cf440e3081d5702c407288

It’s working alright, I am going to be working on the database part next, so it’s returning hardcoded data, but has all the endpoints I need. What I’d like to be able to do is respond with a JSON to the client and tell it what caused the error, which field was wrong or what condition was not fulfilled. I don’t see how I can do that, because if the JSON extraction fails my handler just doesn’t execute :confused:

Feel free to comment out diesel in the Cargo.toml! It took me a few good minutes to compile the project for the first time! Use cargo run-script dev for auto-reload if you want to play around.

#6

Hello @jcubed looks in this example:

pub fn routes_db(db: Addr<DbExecutor>) -> App<AppState> {
    App::with_state(AppState{ db })
        .middleware(middleware::Logger::default())
        .middleware(LocalLogger)
        .resource("/people", |r| {
            r.method(Method::POST)
                .with_async_config(SendMessage::send_create, |cfg| {
                    cfg.0.limit(4096)
                        .error_handler(|err, _req| {
                            let description = format!("{}", err);
                            error::InternalError::from_response(
                                err, HttpResponse::BadRequest().json(description)).into()
                        });
                });
            r.method(Method::GET).with_async(SendMessage::send_get_all);
        })
        .resource("/person/{name}", |r| {
            r.method(Method::GET).with_async(SendMessage::send_get_person);
            r.method(Method::DELETE).with_async(SendMessage::send_delete);
        })
}

I think it is what you need. In this example response with a error in case that the POST request is wrong. You can see more about error handler in actix-web in this example project: