0

I decided to use the hyper create to build a server that reads the body data of a POST method. How do I synchronously return a value calculated in an asynchronous Future in stable Rust? explains a part of what I am looking for, but I don't want to use tokio::run or future::lazy because according to my understanding hyper uses Tokio and futures and the hyper body returns a stream. What I am trying to accomplish is to find other ways of handling a stream and get more knowledge on hyper Request methods.

In the first approach, I concat2 then call wait. wait blocks the current thread so my code hangs.

if Method::POST == req.method() {
    let body = req.into_body().concat2().wait();
    // convert to json and do something with the data.
    Ok(Response::new(Body::from("OK: data submitted")))
}

In the second approach, I tried using poll and and_then but I always get a NotReady. The result type is futures::poll::Async<hyper::Chunk>.

if Method::POST == req.method() {
    let body = req.into_body().concat2().poll().and_then(|e| {
        // do something
        Ok(e)
    });

    match body {
        Ok(e) => println!("{:#?}", e),
        Err(r) => println!("{:#?}", r),
    };
    Ok(Response::new(Body::from("")))
}
  1. How can I unblock the current thread and return the results?
  2. How can I poll and then return the results, ?

If possible, please explain good practice on how to handle futures::poll::Async and wait(). At the moment, async/await is unstable in Rust so I can't use it.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Silva
  • 625
  • 1
  • 6
  • 25
  • It looks like your question might be answered by the answers of [How do I synchronously return a value calculated in an asynchronous Future in stable Rust?](https://stackoverflow.com/q/52521201/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Oct 07 '19 at 12:56

1 Answers1

1

As I'm sure you've discovered, calling wait() on futures is an anti-pattern and defeats the purpose of async IO overall (as you're blocking your thread - and thus the executor - doing so).

hyper routes accept a return that implements IntoFuture, a type implemented for Option<T> and Result<T, E> in a blanket fashion. As such, what you actually wrote does not need to block at all - you just need to combine futures like so:

if Method::POST == req.method() {
   req.into_body().concat2().map(|_body| {
       Response::new(Body::from("OK: data submitted"))
   })
}

You don't even use the body content in your code, but I'm assuming that's for MCVE purposes. Inside the map() combinator, that value currently surfaces as _body and allows you to do whatever you want with it.

I'm guessing you found yourself in this corner due to the documentation - all the combinators are on the FutureExt trait object; they're not defined on Future and Stream traits themselves. As a result, they will not immediately surface when looking at the 0.2/0.3 doc, and it might have seemed like your only available calls were poll_next() and wait() as a consequence.

Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
  • Thank you, is there a way to return the results without using map but use other combinators ? or use the following in the : [link](https://stackoverflow.com/questions/55237128/cant-read-a-simple-payload-making-http-request-via-hyperclientclient-the-t) – Silva Oct 07 '19 at 09:57
  • @Silva you can use any combinator present on `FutureExt` after `concat2()`, as `concat2` implements `Future`. As such, if you need to do more complex things with it, there's a wide variety of them available. Most of the time, however, `map()` (for when you are not chaining into another future), `or_else()` (when you are attempting to recover from an error result) and `and_then()` (when you are chaining into another future) will be the most commonly used combinators. – Sébastien Renauld Oct 07 '19 at 10:01
  • The key takeaway is, no matter what combinator chain you decide, you need to return. `hyper` will do the rest by actively polling for it the right way. – Sébastien Renauld Oct 07 '19 at 10:01