0

I'm looking to build a basic HTTP(S) server using rust hyper, with the purpose of throughput measurement. Essentially it has two functions

  • on GET request, send an infinite (or arbitrary large) stream of bytes.
  • on POST, discard all incoming bytes, then send a short acknowledgement.

I have this working for HTTP using std::net, but would like to add it to hyper to be able to measure HTTP and HTTPS. Being fairly new to rust, I am wondering how to add it to the hyper HTTPS example server - that is, how I can get the response builder to expose a stream (io::stream?) I can write a static buffer of random bytes to, without building the entire response body in memory.

Essentially, I would like to go

    loop {
        match stream.write(rand_bytes) {
            Ok(_) => {},
            Err(_) => break,
        }
    }

here

async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    let mut response = Response::new(Body::empty());
    match (req.method(), req.uri().path()) {
        // Help route.
        (&Method::GET, "/") => {
            *response.body_mut() = Body::from("I want to be a stream.\n");
        }
...

I see that I could wrap a futures stream using wrap_stream, so maybe my question is how to define a stream iterator that I can use in wrap_stream which returns the same bytes over and over again.

relet
  • 6,819
  • 2
  • 33
  • 41
  • 1
    You can have an infinitely repeating iterator with [`std::iter::repeat`](https://doc.rust-lang.org/stable/std/iter/fn.repeat.html) and turn an iterator into a stream with [`futures::stream::iter`](https://docs.rs/futures/latest/futures/stream/fn.iter.html). I haven't tried, but that should work with `wrap_stream`? – Caesar Feb 14 '22 at 12:56
  • Thank you. This worked: `let infstream: futures::stream::Iter>> = stream::iter(std::iter::repeat(Ok(rand_string)));` and `*response.body_mut() = Body::wrap_stream(infstream);` I'll just leave the question open for a little longer while I confirm the memory requirements. – relet Feb 14 '22 at 13:30

1 Answers1

0

Thanks to the comment from Caesar above, the following snippet worked for me:

let infstream: futures::stream::Iter<std::iter::Repeat<Result<String, String>>> = stream::iter(std::iter::repeat(Ok(rand_string))); 
*response.body_mut() = Body::wrap_stream(infstream);

This does not implement any termination criteria, but it could easily be modified to return a fixed number of bytes.

relet
  • 6,819
  • 2
  • 33
  • 41