Search code examples
jsonrustfetch-apirust-rocket

Post Rocket route is forwarded (Rust)


Sorry to ask such a basic question, there's little info about this in Stack Overflow and GitHub. This must be something silly, but I'm not getting it.

I'm trying to send via JavaScript's fetch to a Rust post endpoint with Rocket 0.5 RC1. But I'm getting hit by:

No matching routes for POST /api/favorites application/json.

Here's the complete log:

    POST /api/favorites application/json: 
    Matched: (post_favorites) POST /api/favorites
    `Form < FavoriteInput >` data guard is forwarding.
    Outcome: Forward
    No matching routes for POST /api/favorites application/json.  
    No 404 catcher registered. Using Rocket default.
    Response succeeded.

Here's my main.rs file (Irrelevant parts omitted):

#[rocket::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let cors = CorsOptions::default()
        .allowed_origins(AllowedOrigins::all())
        .allowed_methods(
            vec![Method::Get, Method::Post, Method::Patch]
                .into_iter()
                .map(From::from)
                .collect(),
        )
        .allow_credentials(true)
        .to_cors()?;

    rocket::build()
        .mount("/api", routes![index, upload::upload, post_favorites])
        .attach(cors)
        .launch()
        .await?;

    Ok(())
}

#[post("/favorites", data = "<input>")]
async fn post_favorites(input: Form<FavoriteInput>) -> Json<Favorite> {
    let doc = input.into_inner();
    let fav = Favorite::new(doc.token_id, doc.name);
    let collection = db().await.unwrap().collection::<Favorite>("favorites");
    collection.insert_one(&fav, None).await.unwrap();
    Json(fav)
}

Here's my cargo.toml:


[dependencies]
rocket = {version ="0.5.0-rc.1", features=["json"]}
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
reqwest = {version = "0.11.6", features = ["json"] }
serde= {version = "1.0.117", features= ["derive"]}
mongodb = "2.1.0"
rand = "0.8.4"
uuid = {version = "0.8", features = ["serde", "v4"] }

Here are my structs:

#[path = "./paste.rs"]
mod paste;

#[derive(Serialize, Deserialize, Debug)]
pub struct Favorite {
    pub id: String,
    pub token_id: String,
    pub name: String,
}

impl Favorite {
    pub fn new(token_id: String, name: String) -> Favorite {
        let id = Uuid::new_v4().to_string();
        let fav = Favorite { token_id, name, id };

        fav
    }
}

#[derive(FromForm, Serialize, Deserialize, Debug)]
pub struct FavoriteInput {
    pub token_id: String,
    pub name: String,
}

Here's the token payload:

enter image description here

enter image description here

enter image description here

I've tried with parameter-less get requests and they were successful.

I thought the Form struct was reading and correctly parsing the FavoriteInput as it allows for missing/extra fields.

There must be something silly that I'm doing wrong. Any ideas?


Solution

  • You seem to be sending JSON from JavaScript but are expecting Form parameters on the server.

    You need to change input: Form<FavoriteInput> with input: Json<FavoriteInput>.