Question: How to write more idiomatic Rust and Hyper?


#1

I’m completely new to the Rust language and my first project to help learn Rust is a simple web server.
This web server users the Futures and Hyper crate, to call out to an external JSON api and return a single value from the JSON response.

After a lot of failed attempts, I finally got my program to compile and run, it works beautifully. However, I can’t help but feel like I’m doing things wrong, or non-idiomatically.

My code for my server:

I think particularly, I would like to know how to compose or write futures that don’t need to follow the
.and_then(...).map(|x| {x}) to do some computation and to return a value.

I feel like I’m doing this wrong but don’t understand how Hyper uses futures properly enough to write it better.

Cheers,

Justin


#2

Why do you have those map(|x| x) calls there?

Also, you shouldn’t need a Box in the following:

Box::new(
              futures::future::ok(
                Response::new()
                  .with_status(StatusCode::Ok)
                  .with_body(url))
            )

You can take advantage of the fact that a Result<T, E> has an IntoFuture impl - that means you can replace the above with:

Ok(Response::new()
                  .with_status(StatusCode::Ok)
                  .with_body(url))
      )

#3

I was getting compiler warnings when I was hacking on this last night, and adding the .map() onto the ends was just the first thing that worked. I can’t remember the warnings or how I haved transformed my code since then, but removing .map() worked like you said it would.

Thank you for the sanity check and for the info about Result<T, E>.


#4

It’s important to keep in mind the difference between and_then and map, which might be the source of confusion.

and_then is defined to return something that implements IntoFuture. This is useful if the body does something asynchronous, and returns some type that implements Future (all Futures are also IntoFuture).

map is a simple transformation function - it just yields some type T, and this T is now the return type of the underlying Future that you’re map()’ing over. This is useful when the mapping/transformation doesn’t have any asynchrony.