Hyper: Hyper client guide does not compile

Created on 25 Aug 2017  路  4Comments  路  Source: hyperium/hyper

[dependencies]
hyper = "0.11"
futures = "0.1"
tokio-core = "0.1"
tokio-io = "0.1"
extern crate futures;
extern crate hyper;
extern crate tokio_core;

use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;

fn main(){
let mut core = Core::new()?;
let client = Client::new(&core.handle());

let uri = "http://httpbin.org/ip".parse()?;
let work = client.get(uri).and_then(|res| {
    println!("Response: {}", res.status());

    res.body().for_each(|chunk| {
        io::stdout()
            .write_all(&chunk)
            .map_err(From::from)
    })
});
core.run(work)?;
}
error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
  --> src/main.rs:11:16
   |
11 | let mut core = Core::new()?;
   |                ------------
   |                |
   |                the trait `std::ops::Try` is not implemented for `()`
   |                in this macro invocation
   |
   = note: required by `std::ops::Try::from_error`

error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
  --> src/main.rs:14:11
   |
14 | let uri = "http://httpbin.org/ip".parse()?;
   |           --------------------------------
   |           |
   |           the trait `std::ops::Try` is not implemented for `()`
   |           in this macro invocation
   |
   = note: required by `std::ops::Try::from_error`

error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
  --> src/main.rs:24:1
   |
24 | core.run(work)?;
   | ---------------
   | |
   | the trait `std::ops::Try` is not implemented for `()`
   | in this macro invocation
   |
   = note: required by `std::ops::Try::from_error`

error: aborting due to previous error(s)

I had to wrap the code between fn main() {} don't know if it's a documentation typo or not. It seems to not compile, what am I missing?

Most helpful comment

A simple fix is to unwrap() in each of these places. Failure to run an example is a valid reason for a panic; something has gone terribly wrong! (It is also for this reason examples should be self-contained, by having main()).

The working example should be:

extern crate futures;
extern crate hyper;
extern crate tokio_core;

use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;

fn main() {
  let mut core = Core::new().unwrap();
  let client = Client::new(&core.handle());

  let uri = "http://httpbin.org/ip".parse().unwrap();
  let work = client.get(uri).and_then(|res| {
    println!("Response: {}", res.status());

    res.body().for_each(|chunk| {
      io::stdout()
        .write_all(&chunk)
        .map_err(From::from)
      })
    });
    core.run(work).unwrap();
}

The Rust Programming Language book has a section on the subject of panics

When you鈥檙e writing an example to illustrate some concept, having robust error handling code in the example as well can make the example less clear. In examples, it鈥檚 understood that a call to a method like unwrap that could panic! is meant as a placeholder for the way that you鈥檇 actually like your application to handle errors, which can differ based on what the rest of your code is doing.

? is a way of simply ignoring the exceptions rather than addressing them with a handler or a panic. In my experience it is best to handle exceptions as soon in the call stack as there is information sufficient to respond. Propagating exceptions makes the code messy unless there's a good reason not to handle them immediately.

Http exceptions can usually be responded to by retrying a few times and then informing the user to check if that particular website is down and troubleshoot their internet connection. In many cases, an http client will not have access to network troubleshooting/control, or can simply be run a second time by the user.

All 4 comments

It is not possible to use ? inside the main function. You can place the code in another function can does have a Result return type.

I changed the client guide example to:

extern crate futures;
extern crate hyper;
extern crate tokio_core;

use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;

fn main(){
    run();
}

fn run() -> Result<(), hyper::Error> {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());

    let uri = "http://httpbin.org/ip".parse().unwrap();
    let work = client.get(uri).and_then(|res| {
        println!("Response: {}", res.status());

        println!("Response: {}", res.headers());


        res.body().for_each(|chunk| {
            io::stdout()
                .write_all(&chunk)
                .map_err(From::from)
        })
    });
    core.run(work).unwrap();
    Ok(())
}

To make it compile but was not able to find the OK result type, any help?

(Once I got this I will submit a PR to fix the guide since I'm sure I was not the only one with this issue :))

The following link describes a workaround
https://doc.rust-lang.org/std/process/fn.exit.html

The following link describes a proposal for a language change that would allow users to use ? in main
https://github.com/rust-lang/rfcs/pull/1937

A simple fix is to unwrap() in each of these places. Failure to run an example is a valid reason for a panic; something has gone terribly wrong! (It is also for this reason examples should be self-contained, by having main()).

The working example should be:

extern crate futures;
extern crate hyper;
extern crate tokio_core;

use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;

fn main() {
  let mut core = Core::new().unwrap();
  let client = Client::new(&core.handle());

  let uri = "http://httpbin.org/ip".parse().unwrap();
  let work = client.get(uri).and_then(|res| {
    println!("Response: {}", res.status());

    res.body().for_each(|chunk| {
      io::stdout()
        .write_all(&chunk)
        .map_err(From::from)
      })
    });
    core.run(work).unwrap();
}

The Rust Programming Language book has a section on the subject of panics

When you鈥檙e writing an example to illustrate some concept, having robust error handling code in the example as well can make the example less clear. In examples, it鈥檚 understood that a call to a method like unwrap that could panic! is meant as a placeholder for the way that you鈥檇 actually like your application to handle errors, which can differ based on what the rest of your code is doing.

? is a way of simply ignoring the exceptions rather than addressing them with a handler or a panic. In my experience it is best to handle exceptions as soon in the call stack as there is information sufficient to respond. Propagating exceptions makes the code messy unless there's a good reason not to handle them immediately.

Http exceptions can usually be responded to by retrying a few times and then informing the user to check if that particular website is down and troubleshoot their internet connection. In many cases, an http client will not have access to network troubleshooting/control, or can simply be run a second time by the user.

Was this page helpful?
0 / 5 - 0 ratings