3

I want to parse a HTTP POST in Rocket using a struct. Upon submitting the form it fails.

I read the body data example and have this code.

#[derive(FromForm)]
struct ConvertFile {
    name: String,
    filename: String
}

#[post("/submit", format = "multipart/form-data", data = "<form>")]
fn submit(form: Form<ConvertFile>) {
    println!("form field: {}", form.get().name);
}

I submit using curl:

curl -H "Content-Type: multipart/form-data" -F "name=Claus" -F "filename=claus.jpg" http://localhost:8000/submit

and the Rocket console responds with

multipart/form-data; boundary=------------------------8495649d6ed34d20:
    => Matched: POST /submit multipart/form-data
    => Warning: Form data does not have form content type.
    => Outcome: Forward
    => Error: No matching routes for POST /submit multipart/form-data; boundary=------------------------8495649d6ed34d2.
    => Warning: Responding with 404 Not Found catcher.
    => Response succeeded.

I want to submit a file hence the multipart/form-data. When trying to find the reason, I used a String in the struct to make it simpler. So first it responds with a Matched: and then no matching routes.

This simpler POST works:

#[post("/convert", format = "text/plain", data = "<file>")]
fn convert_file(file: String) {
    println!("file: {}", file);
}

I am using the latest nightly Rust with rustup.

What am I doing wrong?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
kometen
  • 6,536
  • 6
  • 41
  • 51
  • I'm not sure, but have you tried with matching form fields in your `curl` command? You have `file` and `filename` in that `ConvertFile`, not `name` and `filename`. – E_net4 Jul 25 '17 at 22:22
  • The fields in the struct was from an earlier draft auto-saved in SO. So I forgot to modify it with the current curl command when I submitted the question. Thank you for noticing this, I have modified it so it is correct. – kometen Jul 26 '17 at 06:52

1 Answers1

3

Rocket does not yet support multipart forms.

You can see the tracking issue here: https://github.com/SergioBenitez/Rocket/issues/106

A possible workaround is given in this answer: How to parse multipart forms using abonander/multipart with Rocket?

belst
  • 2,285
  • 2
  • 20
  • 22
  • Thank you. But then the example at https://rocket.rs/guide/requests/#forms must be inaccurate? – kometen Jul 26 '17 at 09:30
  • no, forms do work, just not the multipart Content-type. – belst Jul 26 '17 at 09:36
  • Hmm, http form post using curl is what I have problems sending. `curl -X POST -f name=claus filename=claus.jpg`. – kometen Jul 26 '17 at 09:47
  • 1
    this works fine for me: `curl -X POST --data "name=clause&filename=claus.jpg" http://localhost:8000`: https://gist.github.com/belst/21a6759f183cd031a2cac5846bd4bfbb – belst Jul 26 '17 at 10:00
  • It looks like Rocket tries to match `multipart/form-data` to `multipart/form-data; boundary=....` which obviously fails. So as said in the answer, you need to use FromData and not FromForm and parse the body yourself. – belst Jul 26 '17 at 10:10
  • I'm able to upload and save a file using rocket::Data.stream_to_file(). But if I want to sent the filename as part of the form post it seems support for multipart/form-data must be added before that is possible I guess. – kometen Jul 26 '17 at 10:21