LINUX.ORG.RU

Вернуть Result вместо Actix::futures::AndThen

 


1

3

Как привести тип результата запрса awc: actix::futures::and_then<AndThen…, MapErr…, closure> к Result<String, Error>?

Примерный код

client::get("http://localhost/")
        .header("User-Agent", "Actix-web")
        .send()
        .map_err(...)
        })
        .and_then(|mut response| {
         let x = response.body().wait() match  ...
         futures::ok(x)
        })
        .and_then(|body_raw| {
        let y = String::from_ ... body_raw
        Ok(y)
      })
});


Последнее исправление: robotron5 (всего исправлений: 2)

Вероятно, никак. Но ты можешь сделать poll.

quantum-troll ★★★★★
()

Нельзя просто конвертировать тип, который в данном случае имплементация Futur. В Rust так не работает.

Все что ты создал - просто пассивная структура в памяти, даже запрос не отправился. Ее надо «выполнить»

https://docs.rs/actix/0.8.2/actix/fn.run.html

Вот к тому что ты сформировал нужно присобачить еще один and_then и сделать с результатом что ты хочешь, например println!. А потом «выполнить»

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

Спасибо, у меня формируется строка, а вот про System.block_on который ее выполняет упустил.

robotron5
() автор топика
  let x = response.body().wait() match  ...
         futures::ok(x)

Вот кстати тут подозрительное место.

https://docs.rs/futures/0.1.27/futures/future/trait.Future.html#method.wait

Это же блокирующее ожидание. Код надо писать асинхронно.

А то ждешь, а потом заново заворачиваешь futures::ok. Так никто не делает. Сделай какой-то body().map(... match ... ) и не надо ничего в ok() заворачивать. А то и вообще весь этот and_then() замени на map()

Вообще надо бы уже async/await использовать, если есть возможность

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 3)
Ответ на: комментарий от vertexua

Можешь подсказать? Я понимаю что нужно указать время жизни но как это сделать непойму.

fn proxy(_: HttpRequest, payload: web::Payload, client: web::Data<Client>) -> impl IntoFuture<Item = HttpResponse, Error = Error> {

    payload
        .map_err(Error::from)
        .fold(web::BytesMut::new(), move |mut raw, chunk| {
            raw.extend_from_slice(&chunk);
            Ok::<_, Error>(raw)
        })
        .and_then(|data| {
            Ok(String::from_utf8_lossy(data.as_ref()).to_string())
        })
        .and_then(|data| {

            client.post("http://127.0.0.1:8080")
                .content_type("text/html")
                .timeout(Duration::from_millis(50))
                .send_body(data)
                .map_err(Error::from)
                .and_then(|mut response| {

                    response.body().from_err().and_then(|raw| {
                        let body = String::from_utf8_lossy(raw.as_ref()).to_string();

                        future::ok(
                            HttpResponse::Ok().content_type("text/html").body(body)
                        )
                    })
                })
        })
}
error[E0373]: closure may outlive the current function, but it borrows `client`, which is owned by the current function
  --> src/main.rs:35:19
   |
35 |         .and_then(|data| {
   |                   ^^^^^^ may outlive borrowed value `client`
36 | 
37 |             client.post("http://127.0.0.1:8080")
   |             ------ `client` is borrowed here
robotron5
() автор топика
Ответ на: комментарий от robotron5

«move |data|» для той лямбды которая хочет завладеть client. Если это то что ты хочешь. Ну как минимум вся твоя функция забирает себе client, то раз так, то почему бы уже не передать ее в Future.

Иначе или клонировать или Arc, тут уже зависит от внутренностей клиента, что разрабы рекомендуют. Вдруг там внутри Arc, а ты будешь в ещё один оборачивать

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

Как сказать компилятору что это одно и тоже?

f1 дубликат f2 c типом:

fn f2(client: web::Data<Client>, text: String) -> impl IntoFuture<Item = HttpResponse, Error = Error>
error[E0308]: if and else have incompatible types
   --> src/main.rs:182:17
    |
179 | /             if text == "100" {
180 | |                 f1(client, text)
    | |                 ------------------- expected because of this
181 | |             } else {
182 | |                 f2(client, text)
    | |                 ^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
183 | |             }
    | |_____________- if and else have incompatible types
    |
    = note: expected type `impl futures::future::IntoFuture` (opaque type)
               found type `impl futures::future::IntoFuture` (opaque type)

Скажи хоть кошель, для благодарности…

robotron5
() автор топика
Ответ на: комментарий от vertexua

«move |data|» для той лямбды которая хочет завладеть client. Если это то что ты хочешь. Ну как минимум вся твоя функция забирает себе client, то раз так, то почему бы уже не передать ее в Future.

Упустил этот момент, за растом меньше недели

robotron5
() автор топика
Ответ на: комментарий от robotron5

На всякий случай уточнил. Короче, с точки зрения раста impl Trait<...>, возвращаемые функциями - это разные типы, поэтому и ошибка. Согласен, текст ошибки не очевидный.

Решение - завернуть в Box:

fn f1(...) -> Box<dyn IntoFuture<...>>

hippi90 ★★★★★
()
Ответ на: комментарий от hippi90
error[E0191]: the value of the associated type `Future` (from the trait `futures::future::IntoFuture`) must be specified
  --> src/main.rs:83:63
   |
83 | fn f1(client: web::Data<Client>, text: String) -> Box<dyn IntoFuture<Item = HttpResponse, Error = Error>> {
   |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Future` must be specified

error[E0191]: the value of the associated type `Future` (from the trait `futures::future::IntoFuture`) must be specified
   --> src/main.rs:147:63
    |
147 | fn f2(client: web::Data<Client>, text: String) -> Box<dyn IntoFuture<Item = HttpResponse, Error = Error>> {
    |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Future` must be specified
robotron5
() автор топика
Ответ на: комментарий от hippi90

без Box:

          if text == "100" {
                let x: IntoFuture<Item = HttpResponse, Error = Error> = f1(client, text);
                x
            } else {
                let y: IntoFuture<Item = HttpResponse, Error = Error> = f2(client, text);
                y
            }
error[E0191]: the value of the associated type `Future` (from the trait `futures::future::IntoFuture`) must be specified
   --> src/main.rs:180:24
    |
180 |                 let x: IntoFuture<Item = HttpResponse, Error = Error> = f1(client, text);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Future` must be specified

error[E0191]: the value of the associated type `Future` (from the trait `futures::future::IntoFuture`) must be specified
   --> src/main.rs:183:24
    |
183 |                 let y: IntoFuture<Item = HttpResponse, Error = Error> = f2(client, text);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Future` must be specified

error[E0308]: mismatched types
   --> src/main.rs:180:73
    |
180 |                 let x: IntoFuture<Item = HttpResponse, Error = Error> = f1(client, text);
    |                                                                         ^^^^^^^^^^^^^^^^^^^ expected trait futures::future::IntoFuture, found opaque type
    |
    = note: expected type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
               found type `impl futures::future::IntoFuture`

error[E0277]: the size for values of type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>` cannot be known at compilation time
   --> src/main.rs:180:21
    |
180 |                 let x: IntoFuture<Item = HttpResponse, Error = Error> = f1(client, text);
    |                     ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature

error[E0308]: mismatched types
   --> src/main.rs:183:73
    |
183 |                 let y: IntoFuture<Item = HttpResponse, Error = Error> = f2(client, text);
    |                                                                         ^^^^^^^^^^^^^^^^^^^ expected trait futures::future::IntoFuture, found opaque type
    |
    = note: expected type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
               found type `impl futures::future::IntoFuture`

error[E0277]: the size for values of type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>` cannot be known at compilation time
   --> src/main.rs:176:10
    |
176 |         .and_then(move |data| {
    |          ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error[E0277]: the size for values of type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>` cannot be known at compilation time
   --> src/main.rs:183:21
    |
183 |                 let y: IntoFuture<Item = HttpResponse, Error = Error> = f2(client, text);
    |                     ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature

error[E0277]: the size for values of type `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>` cannot be known at compilation time
   --> src/main.rs:165:79
    |
165 | fn proxy(_: HttpRequest, payload: web::Payload, client: web::Data<Client>) -> impl IntoFuture<Item = HttpResponse, Error = Error> {
    |                                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because of the requirements on the impl of `futures::future::Future` for `futures::future::and_then::AndThen<futures::future::and_then::AndThen<futures::stream::fold::Fold<futures::stream::map_err::MapErr<actix_web::web::Payload, fn(actix_web::error::PayloadError) -> actix_web::Error {<actix_web::Error as std::convert::From<actix_web::error::PayloadError>>::from}>, [closure@src/main.rs:169:37: 172:10], std::result::Result<actix_web::web::BytesMut, actix_web::Error>, actix_web::web::BytesMut>, std::result::Result<std::string::String, actix_web::Error>, [closure@src/main.rs:173:19: 175:10]>, dyn futures::future::IntoFuture<Error=actix_web::Error, Item=actix_web::HttpResponse>, [closure@src/main.rs:176:19: 186:10 client:_]>`
    = note: the return type of a function must have a statically known size

robotron5
() автор топика
Ответ на: комментарий от robotron5

Этот код выполняется в контексте этой функции

fn proxy(_: HttpRequest, payload: web::Payload, client: web::Data<Client>) -> impl IntoFuture<Item = HttpResponse, Error = Error>

и фактически является ее результатом

robotron5
() автор топика
Ответ на: комментарий от robotron5

Я с future не работал, поэтому могу ошибаться, но то, что я вижу в документации, говорит, что у IntoFuture три ассоциированных типа, ты указал только два, о чем компилятор тебе и сообщает.

https://docs.rs/futures/0.2.0/futures/future/trait.IntoFuture.html

hippi90 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.