Hyper and sending buffered data


#1

I’m writing a Hyper simple example, where I send data to a client every minute:

fn home_handler(req: Request, res: Response) {
log_request(&req);

let ten_millis = time::Duration::from_millis(1000);
let now = time::Instant::now();

thread::sleep(ten_millis);
res.send(b"new stuff").unwrap();
thread::sleep(ten_millis);
res.send(b"new stuff").unwrap();
thread::sleep(ten_millis);
res.send(b"new stuff").unwrap();
thread::sleep(ten_millis);
res.send(b"new stuff").unwrap();

}

Unfortunately, Rust doesn’t like that at all, it complains about:

“value used here after move”
= note: move occurs because res has type hyper::server::Response<'_>, which does not implement the Copy trait

Why does “send()” ing to Response moves res?
doesn’t send() work like old ASP’s Response.write?
What is the equivalent of Response.write or php’s echo+flush in the context of Hyper?


#2

send starts sending the response, including headers and then proceeds to sending the body. That’s why it is moving the body: you can only start that process once. If you look and the signature, you see that it takes a stream. So you can give it a handle to a body that you will later provide.

It works like this:

let (sender, body) = hyper::Body::pair();
res.send(body);

thread::spawn(move || {
    thread::sleep(ten_millis);
    res.send(b"new stuff").unwrap();
    thread::sleep(ten_millis);
    res.send(b"new stuff").unwrap();
    thread::sleep(ten_millis);
    res.send(b"new stuff").unwrap();
    thread::sleep(ten_millis);
    res.send(b"new stuff").unwrap();
}

Ok(res)

Note that the thread spawn here is necessary, otherwise, you’d be pushing everything onto the stream before starting the response.


#3

I think you meant Body::pair


#4

Yes, broke it while fixing. Next hyper version will use Body::channel(), by the way.