Convert an async function's future into v0.1's future

Rust version : 1.39 nightly; Actix-web version : 1.0.7

http_srv.rs :

use futures01::stream::Stream;
use futures01::sync::mpsc;
use futures01::future::{ Future};
use futures::future::{ FutureExt, TryFutureExt};
use futures::compat::{Stream01CompatExt};
use futures::stream::TryStreamExt; // for `try_next`

use actix_web::*;
use bytes::Bytes;
use std::time::Duration;
use futures_timer::Delay;



fn inbound(req: HttpRequest, stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> {

    let fu = async_inbound(&req, &stream);

    fu.unit_error().boxed_local().compat()  // <--- compliation error here.
}

async fn async_inbound(req: &HttpRequest, stream: &web::Payload) -> HttpResponse {
    let mut compatStream = stream.compat();
    loop {
        let result = compatStream.try_next().await;
        if let Err(e) = result {
            warn!("Failed to read stream from {} : {}", req.path(), e);
            break;
        }          

        if let Ok(option) = result {
            match option {
                None => {
                    info!("Request ends");
                    break;
                },
                Some(data) => {
                    println!("{:?}", data);
                },
            }
        }
    } 
    HttpResponse::Ok().content_type("text/html").body("RESP")
}

pub fn start(port : u16){

    info!("Starting HTTP server listening at port {} ...", port);

    let _ = HttpServer::new(|| {
        App::new()
            .wrap(middleware::DefaultHeaders::new().header(http::header::CACHE_CONTROL, "no-cache"))
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/")
                    .route(web::put().to_async(inbound)),
            )
    })
    .bind(format!("0.0.0.0:{}", port))
    .expect(&format!("Unable to bind on port {}", port))
    .run()
    .expect("Failed to start HTTP server");
}

I want to take use of async function to parse inbound stream progressively. But actix-web requires impl Future<Item=HttpResponse, Error=Error> as return value.

How can I convert future returned by async function to what actix-web requires?

cargo.toml :

[dependencies]
log = "0.4.8"
env_logger = "0.6.2"
chrono = "0.4.8"
actix = "0.8.3"
bytes = "0.4.12"
actix-utils = "0.4.5"
futures-timer = "0.3"
futures01 = { package = "futures", version = "0.1", optional = false }

[dependencies.actix-web]
version = "1.0.7"
features = ["ssl"]

# https://rust-lang-nursery.github.io/futures-rs/blog/2019/04/18/compatibility-layer.html
# Rust’s futures ecosystem is currently split in two: 
# On the one hand we have the vibrant ecosystem built around futures@0.1 with its many libraries working on stable Rust 
# and on the other hand there’s std::future ecosystem with support for the ergonomic and powerful async/await language feature. 
# To bridge the gap between these two worlds we have introduced a compatibility layer as part of the futures@0.3 extension to std::future. 
[dependencies.futures-preview]
version = "0.3.0-alpha.18"
default-features = false
features = ["compat", "async-await", "nightly"]

Compliation Error :

error[E0271]: type mismatch resolving `<std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<actix_http::response::Response, ()>>>> as core::future::future::Future>::Output == std::result::Result<_, actix_http::error::Error>`
  --> src/http_server.rs:39:55
   |
39 | fn inbound(req: HttpRequest, stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> {
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `actix_http::error::Error`
   |
   = note: expected type `std::result::Result<actix_http::response::Response, ()>`
              found type `std::result::Result<_, actix_http::error::Error>`
   = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<actix_http::response::Response, ()>>>>`
   = note: the return type of a function must have a statically known size

Best Regards

Basically it's because fu.unit_error().boxed_local().compat() has the error type () but you are trying to return something with the error type Error. Try changing the async function to return a result with that error type to avoid the () error type.

Thanks @alice

Try changing the async function to return a result with that error type to avoid the () error type.

This does not work because error type () is defined in unit_error()

Changing async_inbound to return Result<HttpResponse, Error> would cause another error.

async fn async_inbound(req: &HttpRequest, stream: &web::Payload) -> Result<HttpResponse, Error> {
    let mut compatStream = stream.compat();
    loop {
        let result = compatStream.try_next().await;
        if let Err(e) = result {
            warn!("Failed to read stream from {} : {}", req.path(), e);
            break;
        }          
        
        if let Ok(option) = result {
            match option {
                None => {
                    info!("Request ends");
                    break;
                },
                Some(data) => {
                    println!("{:?}", data);
                },
            }
        }
    } 
    Ok(HttpResponse::Ok().content_type("text/html").body("RESP"))
}
error[E0271]: type mismatch resolving `<std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>>>> as core::future::future::Future>::Output == std::result::Result<actix_http::response::Response, _>`
  --> src/http_server.rs:39:55
   |
39 | fn inbound(req: HttpRequest, stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> {
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `actix_http::response::Response`
   |
   = note: expected type `std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>`
              found type `std::result::Result<actix_http::response::Response, _>`
   = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>>>>`
   = note: the return type of a function must have a statically known size

error[E0271]: type mismatch resolving `<std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>>>> as core::future::future::Future>::Output == std::result::Result<_, actix_http::error::Error>`
  --> src/http_server.rs:39:55
   |
39 | fn inbound(req: HttpRequest, stream: web::Payload) -> impl Future<Item=HttpResponse, Error=Error> {
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `actix_http::error::Error`
   |
   = note: expected type `std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>`
              found type `std::result::Result<_, actix_http::error::Error>`
   = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<std::result::Result<actix_http::response::Response, actix_http::error::Error>, ()>>>>`
   = note: the return type of a function must have a statically known size

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.