0

I have a warp server running, and for every request I need to compute a string and then return that string with a particular status code.

use warp::{http::StatusCode, reply, Filter};

let creator = warp::post()
    .and(warp::path("mypath"))
    .and(warp::body::bytes())
    .and(warp::header("myheader"))
    .map(move |buf: warp::hyper::body::Bytes, header: String| {
        if (is_request_invalid()) {
            reply::with_status("Request parameter xyz is invalid", StatusCode::BAD_REQUEST);
        }

        let computed_string: String = compute_from(buf, header);
        return reply::with_status(
            computed_string,
            StatusCode::CREATED,
        );
    });

However, this doesn't work because reply::with_status requires a type of &str.

error[E0308]: mismatched types
  --> lib.rs:54:33
   |
54 | ...                   computed_string,
   |                       ^^^^^^^^^^^^^^^
   |                       |
   |                       expected `&str`, found struct `std::string::String`
   |                       help: consider borrowing here: `&computed_string`

So I tried:

// -- SNIP --
return reply::with_status(
    &computed_string,
    StatusCode::CREATED,
);
// -- SNIP --

(since &String derefs to &str) -- but this doesn't work either, as you can't return a reference to a variable owned by the current scope (will be dropped)

error[E0597]: `computed_string` does not live long enough
  --> lib.rs:54:33
   |
53 |                               return reply::with_status(
   |  ____________________________________-
54 | |                                 &computed_string,
   | |                                 ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
55 | |                                 StatusCode::CREATED,
56 | |                             );
   | |_____________________________- argument requires that `computed_string` is borrowed for `'static`
57 |                           }
   |                           - `computed_string` dropped here while still borrowed

How do I return a String as a response when using warp?

Lumin
  • 373
  • 6
  • 21
  • 2
    [`warp::reply::with_status`](https://docs.rs/warp/0.3.1/warp/reply/fn.with_status.html) requires a type that implements [`warp::reply::Reply`](https://docs.rs/warp/0.3.1/warp/reply/trait.Reply.html), which is [implemented for `String`](https://docs.rs/warp/0.3.1/warp/reply/trait.Reply.html#impl-Reply-for-String). – eggyal Apr 12 '21 at 13:36
  • @eggyal It doesn't seem to work for me, I've updated the question to include the error – Lumin Apr 12 '21 at 13:41
  • Is that the entirety of that error, or does it include some further info explaining from whence the `&str` expectation originated? – eggyal Apr 12 '21 at 13:43
  • That's the entire error, but line 54 mentioned there is the corresponding line in the question – Lumin Apr 12 '21 at 13:43
  • 1
    I just created a new fresh project (`cargo new q67059208 && cd q67059208 && cargo add warp`), placed the code from your question inside `fn main()` and added a `fn compute_from(buf: warp::hyper::body::Bytes, header: String) -> String { todo!() }`. `cargo build` built with unused code warnings, but no errors. Your problem, whatever it is, does not originate from the code you've shown in your question. – eggyal Apr 12 '21 at 13:50
  • I see. I created a minimal example too and achieved the same result as you. I'll update the question once I figure out the problem – Lumin Apr 12 '21 at 13:52

1 Answers1

1

The question didn't originally include the complete code, however it turns out there was a previous early-return which included an &str, which resulted in reply::with_status returning a WithStatus<&str>, which caused a mismatch when trying to return a WithStatus<String> in the same scope.

use warp::{http::StatusCode, reply, Filter};

let creator = warp::post()
    .and(warp::path("mypath"))
    .and(warp::body::bytes())
    .and(warp::header("myheader"))
    .map(move |buf: warp::hyper::body::Bytes, header: String| {
        if (is_request_invalid()) {
            return reply::with_status("Request parameter xyz is invalid", StatusCode::BAD_REQUEST);
//                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type &str
        }

        let computed_string: String = compute_from(buf, header);
        return reply::with_status(
            computed_string,
//          ^^^^^^^^^^^^^^^ type String
            StatusCode::CREATED,
        );
    });
Lumin
  • 373
  • 6
  • 21
  • You're missing the `return` keyword for the `&'static str` case... but yeah, that definitely explains it. E0308 could definitely be improved here to indicate the origin of the `&str` constraint. Will file an issue. – eggyal Apr 12 '21 at 14:23
  • "You're missing the return keyword for the &'static str case" -- Oh yeah, I didn't notice that (this isn't actually my code) – Lumin Apr 12 '21 at 14:57