2019-06-17 21:39:58 +02:00
|
|
|
// <stream-response>
|
2020-01-21 22:40:37 +01:00
|
|
|
use std::task::Poll;
|
2019-06-24 23:43:31 +02:00
|
|
|
use bytes::Bytes;
|
|
|
|
use futures::stream::poll_fn;
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
use actix_web::http::{ContentEncoding, StatusCode};
|
2020-01-21 22:40:37 +01:00
|
|
|
use actix_web::{web, http, App, Error, HttpRequest, HttpResponse};
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2020-01-21 22:40:37 +01:00
|
|
|
async fn sse(_req: HttpRequest) -> HttpResponse {
|
2019-06-24 23:43:31 +02:00
|
|
|
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]
|
2020-01-21 22:40:37 +01:00
|
|
|
let server_events = poll_fn(move |_cx| -> Poll<Option<Result<Bytes, Error>>> {
|
2019-06-24 23:43:31 +02:00
|
|
|
if counter == 0 {
|
2020-01-21 22:40:37 +01:00
|
|
|
return Poll::Ready(None);
|
2019-06-24 23:43:31 +02:00
|
|
|
}
|
|
|
|
let payload = format!("data: {}\n\n", counter);
|
|
|
|
counter -= 1;
|
2020-01-21 22:40:37 +01:00
|
|
|
Poll::Ready(Some(Ok(Bytes::from(payload))))
|
2019-06-24 23:43:31 +02:00
|
|
|
});
|
2019-06-17 21:39:58 +02:00
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
HttpResponse::build(StatusCode::OK)
|
2020-01-21 22:40:37 +01:00
|
|
|
.set_header(http::header::CONTENT_TYPE, "text/event-stream")
|
|
|
|
.set_header(
|
|
|
|
http::header::CONTENT_ENCODING,
|
|
|
|
ContentEncoding::Identity.as_str(),
|
|
|
|
)
|
2019-06-24 23:43:31 +02:00
|
|
|
.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::*;
|
2020-01-21 22:40:37 +01:00
|
|
|
|
|
|
|
use futures_util::stream::StreamExt;
|
|
|
|
use futures_util::stream::TryStreamExt;
|
|
|
|
|
2019-06-24 23:43:31 +02:00
|
|
|
use actix_web::{test, web, App};
|
|
|
|
|
2020-01-21 22:40:37 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_stream() {
|
|
|
|
let mut app = test::init_service(App::new().route("/", web::get().to(sse))).await;
|
2019-06-24 23:43:31 +02:00
|
|
|
let req = test::TestRequest::get().to_request();
|
2020-01-21 22:40:37 +01:00
|
|
|
|
|
|
|
let mut resp = test::call_service(&mut app, req).await;
|
|
|
|
assert!(resp.status().is_success());
|
|
|
|
|
|
|
|
// first chunk
|
|
|
|
let (bytes, mut resp) = resp.take_body().into_future().await;
|
|
|
|
assert_eq!(bytes.unwrap().unwrap(), Bytes::from_static(b"data: 5\n\n"));
|
|
|
|
|
|
|
|
// second chunk
|
|
|
|
let (bytes, mut resp) = resp.take_body().into_future().await;
|
|
|
|
assert_eq!(bytes.unwrap().unwrap(), Bytes::from_static(b"data: 4\n\n"));
|
|
|
|
|
|
|
|
// remaining part
|
|
|
|
let bytes = test::load_stream(resp.take_body().into_stream()).await;
|
|
|
|
assert_eq!(bytes.unwrap(), Bytes::from_static(b"data: 3\n\ndata: 2\n\ndata: 1\n\n"));
|
2019-06-24 23:43:31 +02:00
|
|
|
}
|
|
|
|
}
|
2019-06-17 21:39:58 +02:00
|
|
|
// </stream-response>
|