seanmonstar/warp

Reply with a stream

sorin-davidoi opened this issue ยท 7 comments

Looking over the list of implementations for Reply, there doesn't seem to be a way to reply with a Stream.

I am basically trying to port the following code from using hyper to warp:

fn main () {
    let addr = ([127, 0, 0, 1], 8000).into();
    let server = Server::bind(&addr)
        .serve(|| hyper::service::service_fn(handler))
        .map(|r| {
            println!("Response: {:?}", r);
        }).map_err(|e| {
            println!("Error: {}", e);
        });

    hyper::rt::run(server);
}

type BoxedFuture = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send>;

fn handler(_request: Request<Body>) -> BoxedFuture {
    let mut response = Response::new(Body::empty());

    *response.body_mut() =
        Body::wrap_stream(<something that implements Stream>);

    Box::new(future::ok(response))
}

My original concern was that I didn't want to expose exactly how streaming responses works, in case adding compression filters needed to adjust them, and thus create a breaking change. However, I think warp can also implement Reply for response with a hyper::Body, and if the internal type needs to change, that specific impl can simply map it...

Master now has changes to allow any Response<impl Into<hyper::Body>>!

That was quick, thank you!

tp commented

@seanmonstar Was this reverted? The following code doesn't work for me, even though I explicitly create a hyper::Body:

async fn get_x() -> Result<impl warp::Reply, std::convert::Infallible> {
    let response_stream = reqwest::get("....").await.unwrap().bytes_stream();
    let body: hyper::Body = hyper::Body::wrap_stream(response_stream);
    Ok(body)
}

errs with

the trait `warp::reply::Reply` is not implemented for `hyper::body::body::Body`

Of course if there is a better way to forward the reqwest response, a hint would be much appreciated :)

@tp I don't think this was reverted... a guess, do the versions match? If the version of hyper you're using doesn't match the version warp is, then the trait won't be implemented. (If it doesn't work, let's open a new issue to track, as it'd be a new bug.)

Of course if there is a better way to forward the reqwest response, a hint would be much appreciated :)

This seems to work for me:

async fn proxy(_unused: String) -> Result<impl warp::Reply, Infallible> {
    let response_stream =
        reqwest::get("http://build/builds/file.tar.bz2").await.unwrap().bytes_stream();
    let body= hyper::Body::wrap_stream(response_stream);
    Ok(warp::reply::Response::new(body))
}

@darkprokoba I have a similar requirement. Could you please help?

I want to create a similar proxy kind of setup.
But before the get request, I want to add header information to it.

Also, want to work on post reqwest, how to pass the received post request json body to the external url?