seanmonstar/warp

Post Request Not Working - Not Sure Why

peterweyand62 opened this issue · 3 comments

I have the following code and error message. As far as I can tell this should work for a post request, but no matter what I do I can't get around the error. I've asked a bunch of LLM networks but they haven't been of any help.

 let return_html_page = warp::path!("return_html_page" / String)
        .and(warp::body::json())
        .map(|name: String, mut employee: Employee| {
            employee.name = name;
            warp::reply::json(&employee)
        });

    let routes = warp::get().and(
        home_page
        .or(hi)
        .or(html)
        .or(editor)
        .or(img)
        .or(vue_img)
        .or(about)
        .or(get_doc_list)
        .or(return_html_page)
    );

    warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;

and the error message


error[E0277]: the trait bound `impl Future<Output = Json>: Reply` is not satisfied
   --> src/main.rs:364:17
    |
364 |     warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
    |     ----------- ^^^^^^ the trait `Reply` is not implemented for `impl Future<Output = Json>`
    |     |
    |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Reply`:
              &'static [u8]
              &'static str
              (T,)
              Box<T>
              Cow<'static, str>
              Html<T>
              Infallible
              Json
            and 14 others
    = note: required for `(impl Future<Output = Json>,)` to implement `Reply`
    = note: 4 redundant requirements hidden
    = note: required for `(Either<(Either<(Either<(Either<(Either<(Either<(Either<(Either<(File,), (&str,)>,), (File,)>,), (File,)>,), (File,)>,), (File,)>,), (File,)>,), (impl Future<Output = ...>,)>,), ...>,)` to implement `Reply`
    = note: the full type name has been written to '/Users/peterweyand/Web_Page/target/debug/deps/warp_page-3df9429c122312bf.long-type-5615294556152411012.txt'
note: required by a bound in `serve`
   --> /Users/peterweyand/.cargo/registry/src/index.crates.io-6f17d22bba15001f/warp-0.3.3/src/server.rs:26:17
    |
23  | pub fn serve<F>(filter: F) -> Server<F>
    |        ----- required by a bound in this function
...
26  |     F::Extract: Reply,
    |                 ^^^^^ required by this bound in `serve`


In principle I understand that the warp server is expecting a return type other than what I'm giving it, but it looks right to me. It should just be taking in a string and outputting a json response. If you fix this could you possibly put in an example in the repo showing how to use a post request? I'm just getting hung up on the function signature or something stupid.

Oh and I have

#[derive(Deserialize, Serialize)]
struct Employee {
    name: String,
}

That should work as far as I can tell. I don't have to put it in a struct for all I care - I just need to be able to take in strings or json and then output json. I think I cribbed this from someone else that had a post request question.

Dumb question I know, but for some reason I'm stuck on this. I'm wondering if there's just not a good way to make a post request for some reason because none of the function signatures seem to line up. Unless I'm doing something incredibly dumb.

It was a dumb mistake on my part - here's the corrected code in case it will help anyone in the future


    read_files();
    
    let paths_html = fs::read_dir("./src/obsidian_html").unwrap();
    let paths_img = fs::read_dir("./src/obsidian_img").unwrap();

    let mut html_vec: Vec<String> = vec![];
    let mut img_vec:  Vec<String> = vec![];

    for path in paths_html {
        html_vec.append(&mut vec![path.unwrap().path().display().to_string()]);
    }

    for path in paths_img {
        img_vec.append(&mut vec![path.unwrap().path().display().to_string()]);
    }

    println!("value of html_vec {:?}", html_vec.clone());
    println!("value of img_vec  {:?}", img_vec.clone());

    let hi = warp::path("hi").map(|| "Hello, World!");
    let home_page = warp::get().and(warp::fs::dir("src/vue/home"));
    let about = warp::path("about").and(warp::fs::dir("src/vue/about"));
    let html = warp::path("html").and(warp::fs::dir("src/obsidian_html/"));
    let img = warp::path("img").and(warp::fs::dir("src/obsidian_img/"));
    let vue_img = warp::path("vue_img").and(warp::fs::dir("src/vue/assets/images"));
    let editor = warp::path("editor").and(warp::fs::dir("src/vue/editor"));
    let get_doc_list = warp::path("get_doc_list").map(|| get_doc_list());
    let return_html_page = warp::path!("return_html_page")
        .and(warp::post())
        .and(warp::body::json())
        .map(|data: Value| {
            let response_json = json!({
                "data": data["name"]
            });
            warp::reply::json(&response_json)
        });

    let cors = warp::cors()
        .allow_any_origin()
        .allow_methods(vec!["GET", "POST", "DELETE"]);

    let routes = warp::any().and(
        home_page
        .or(hi)
        .or(html)
        .or(editor)
        .or(img)    
        .or(vue_img)
        .or(about)
        .or(get_doc_list)
        .or(return_html_page)
        .with(cors)
    );

    warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;