Невозможно прочитать простую полезную нагрузку, выполняющую HTTP-запрос через hyper :: client :: Client: привязка признака `Body: Future` не выполняется

Я пытаюсь преобразовать Result в Buffer:

let ufc_root: String =
    String::from("https://www.ufc.com/athletes/all?filters%5B0%5D=status%3A23");
// let ufc_root: String = String::from("https://www.google.com");
let https = HttpsConnector::new(4).unwrap();
let client = Client::builder().build::<_, hyper::Body>(https);

client
    .get(ufc_root.parse::<hyper::Uri>().unwrap())
    .and_then(|res| {
        println!("http status code: {}", res.status());
        println!("http response headers:\n{:?}: ", res.headers());
        res.into_body()
    })
    .from_err::<WebScrapeError>()
    .and_then(|body| {
        body.for_each(|chunk| {
            println!("{}", chunk.into_bytes());
        });

        let jon_jones = Subject {
            name: "Jon Jones".to_string(),
            link: "http://www.jonjones.com".to_string(),
        };
        let subjects = vec![jon_jones];
        Ok(subjects)
    })
    .from_err()
error[E0277]: the trait bound `hyper::Body: hyper::rt::Future` is not satisfied
  --> src/scrapper.rs:24:14
   |
24 |             .and_then(|res| {
   |              ^^^^^^^^ the trait `hyper::rt::Future` is not implemented for `hyper::Body`
   |
   = note: required because of the requirements on the impl of `futures::future::IntoFuture` for `hyper::Body`

error[E0599]: no method named `from_err` found for type `futures::future::and_then::AndThen<hyper::client::ResponseFuture, hyper::Body, [closure@src/scrapper.rs:24:23: 28:14]>` in the current scope
  --> src/scrapper.rs:29:14
   |
29 |             .from_err::<WebScrapeError>()
   |              ^^^^^^^^
   |
   = note: the method `from_err` exists but the following trait bounds were not satisfied:
           `&mut futures::future::and_then::AndThen<hyper::client::ResponseFuture, hyper::Body, [closure@src/scrapper.rs:24:23: 28:14]> : hyper::rt::Future`
           `&mut futures::future::and_then::AndThen<hyper::client::ResponseFuture, hyper::Body, [closure@src/scrapper.rs:24:23: 28:14]> : hyper::rt::Stream`
           `futures::future::and_then::AndThen<hyper::client::ResponseFuture, hyper::Body, [closure@src/scrapper.rs:24:23: 28:14]> : hyper::rt::Future`

Почему это не компилируется?


person saxman    schedule 19.03.2019    source источник


Ответы (1)


and_then должен возвращать будущее или что-то, что можно преобразовать в будущее с помощью _ 2_ черта. Вы возвращаете res.into_body(), а это не будущее - это на самом деле поток.

Чтобы это работало, вам нужно преобразовать этот поток в будущее, которое представляет собой полностью прочитанное тело. Здесь вам доступны несколько вариантов:

  • res.into_body().concat2(), который объединяет все прочитанные байты в один буфер
  • res.into_body().collect(), который собирает все блоки байтов в Vec
  • res.into_body().into_future(), который будет преобразован в кортеж, содержащий первый элемент из потока и оставшуюся часть самого потока (т.е. (T, Stream<Item = T>))

Тот факт, что существует несколько различных (и одинаково действенных) способов представления Stream как Future, вероятно, является причиной того, что первый не имеет полной реализации IntoFuture.

Пример использования concat2 показан в Hyper docs.

person Joe Clay    schedule 19.03.2019