2019-06-17 21:39:58 +02:00
|
|
|
// <stream-response>
|
2019-06-24 23:43:31 +02:00
|
|
|
use bytes::Bytes;
|
|
|
|
use futures::stream::poll_fn;
|
|
|
|
use futures::{Async, Poll};
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
use actix_web::http::{ContentEncoding, StatusCode};
|
|
|
|
use actix_web::{middleware::BodyEncoding, web, App, Error, HttpRequest, HttpResponse};
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
fn sse(_req: HttpRequest) -> HttpResponse {
|
|
|
|
let mut counter: usize = 5;
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
// yields `data: N` where N in [5; 1]
|
|
|
|
let server_events = poll_fn(move || -> Poll<Option<Bytes>, Error> {
|
|
|
|
if counter == 0 {
|
|
|
|
return Ok(Async::Ready(None));
|
|
|
|
}
|
|
|
|
let payload = format!("data: {}\n\n", counter);
|
|
|
|
counter -= 1;
|
|
|
|
Ok(Async::Ready(Some(Bytes::from(payload))))
|
|
|
|
});
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
HttpResponse::build(StatusCode::OK)
|
|
|
|
.encoding(ContentEncoding::Identity)
|
|
|
|
.content_type("text/event-stream")
|
|
|
|
.streaming(server_events)
|
|
|
|
}
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
pub fn main() {
|
|
|
|
App::new().route("/", web::get().to(sse));
|
|
|
|
}
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use actix_web::{test, web, App};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_stream() {
|
|
|
|
let mut app = test::init_service(App::new().route("/", web::get().to(sse)));
|
|
|
|
let req = test::TestRequest::get().to_request();
|
|
|
|
let resp = test::read_response(&mut app, req);
|
|
|
|
assert!(
|
|
|
|
resp == Bytes::from_static(
|
|
|
|
b"data: 5\n\ndata: 4\n\ndata: 3\n\ndata: 2\n\ndata: 1\n\n"
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-06-17 21:39:58 +02:00
|
|
|
// </stream-response>
|