4

I am building a little webapp in Actix-web, but I can't find any example of getting parameters out of a POST request in Actix-web anywhere.

Searching their excellent examples repo only gives a couple of (to me) meaningful examples, but they both deal with JSON and not form data.

I also found this page, which I suspect holds the answer; but to a beginner this isn't much help.

I imagine it should look something like:

<form method="POST">
    <input type="password" name="password">
    <button type="submit">Login</button>
</form>

and

fn main() {
    // ...
    App::with_state(AppState { db: pool.clone() })
        .middleware(IdentityService::new(
            CookieIdentityPolicy::new(&[0; 32])
                .name("auth-cookie")
                .secure(true),
        ))
        .resource("/login", |r| {
            r.method(http::Method::GET).with(login);
            r.method(http::Method::POST).with(perform_login) // help!
        })
}

struct LoginParams {
    password: String,
}    

fn perform_login(mut req: HttpRequest<AppState>, params: LoginParams) -> HttpResponse {
    if params.password == "abc123" {
        req.remember("logged-in".to_owned());
        // redirect to home
    };
    // show "wrong password" error
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366

2 Answers2

3

You can use an extractor by:

  • Defining a struct that can be deserialized from raw data.
  • Defining a handler that accepts an extractor. In your case, use Form as Nikolay said, with the type parameter of your struct.
  • Register this handler.

If you take a look at simple example in linked documentation you'll see how describe such handler.

Here is a bit more complete one:

Define struct

#[derive(Deserialize)]
struct AddHook {
    id: u64,
    title: String,
    version: Option<String>,
    code: Option<String>
}

Define handler

fn remove_hook_del((query, state): (Form<AddHook>, State<AppState>)) -> FutureHttpResponse {
    let query = query.into_inner();
    let AddHook {id, title, version, code} = query;

    //Do something with your data
}

Register handler

App::with_state(AppState::new()).resource("/remove_hook", |res| {
    res.method(Method::GET).with(remove_hook_get);
    res.method(Method::DELETE).with(remove_hook_del);
    res.route().f(not_allowed);
})

This is more or less a complete example for the current master branch of actix-web. I also made it with state to show how you can use multiple arguments in your handler

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Douman Ashiya
  • 91
  • 1
  • 2
0

You need Form extractor. params: Form<LoginParams>

Nikolay Kim
  • 144
  • 1
  • 1
    This may answer the question, but would be more helpful with [evidence](//meta.stackexchange.com/a/7693/206345) to support it. – Tim Diekmann Jul 03 '18 at 14:24
  • I am reading through it, and it seems like it is indeed the answer, and I *almost* understand the example there. I just don't get how it's supposed to access the `req` parameter (like in my example above) when it only gets a `Form` –  Jul 03 '18 at 14:30
  • I give up for now and work on something else until https://github.com/actix/examples/issues/24 is resolved –  Jul 04 '18 at 08:05