1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-24 00:50:36 +00:00
actix-web/actix-http/tests/test_ws.rs

197 lines
5.3 KiB
Rust
Raw Normal View History

2021-05-13 11:24:32 +00:00
use std::{
cell::Cell,
2021-06-17 16:57:58 +00:00
convert::Infallible,
2021-05-13 11:24:32 +00:00
task::{Context, Poll},
};
use actix_codec::{AsyncRead, AsyncWrite, Framed};
2021-05-13 11:24:32 +00:00
use actix_http::{
2021-06-17 16:57:58 +00:00
body::{AnyBody, BodySize},
2021-05-13 11:24:32 +00:00
h1,
ws::{self, CloseCode, Frame, Item, Message},
Error, HttpService, Request, Response,
};
2019-12-12 17:08:38 +00:00
use actix_http_test::test_server;
use actix_service::{fn_factory, Service};
use bytes::Bytes;
2021-06-17 16:57:58 +00:00
use derive_more::{Display, Error, From};
2021-05-13 11:24:32 +00:00
use futures_core::future::LocalBoxFuture;
2021-03-11 03:48:38 +00:00
use futures_util::{SinkExt as _, StreamExt as _};
2021-05-13 11:24:32 +00:00
#[derive(Clone)]
struct WsService(Cell<bool>);
2021-04-01 14:26:13 +00:00
2021-05-13 11:24:32 +00:00
impl WsService {
fn new() -> Self {
2021-05-13 11:24:32 +00:00
WsService(Cell::new(false))
}
2019-11-19 12:54:19 +00:00
fn set_polled(&self) {
2021-05-13 11:24:32 +00:00
self.0.set(true);
}
fn was_polled(&self) -> bool {
2021-05-13 11:24:32 +00:00
self.0.get()
}
}
2021-06-17 16:57:58 +00:00
#[derive(Debug, Display, Error, From)]
enum WsServiceError {
#[display(fmt = "http error")]
Http(actix_http::Error),
#[display(fmt = "ws handshake error")]
Ws(actix_http::ws::HandshakeError),
#[display(fmt = "io error")]
Io(std::io::Error),
#[display(fmt = "dispatcher error")]
Dispatcher,
}
impl From<WsServiceError> for Response<AnyBody> {
fn from(err: WsServiceError) -> Self {
match err {
WsServiceError::Http(err) => err.into(),
WsServiceError::Ws(err) => err.into(),
WsServiceError::Io(_err) => unreachable!(),
WsServiceError::Dispatcher => Response::internal_server_error()
.set_body(AnyBody::from(format!("{}", err))),
}
}
}
2021-05-13 11:24:32 +00:00
impl<T> Service<(Request, Framed<T, h1::Codec>)> for WsService
where
T: AsyncRead + AsyncWrite + Unpin + 'static,
{
type Response = ();
2021-06-17 16:57:58 +00:00
type Error = WsServiceError;
2021-05-13 11:24:32 +00:00
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
2021-05-13 11:24:32 +00:00
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.set_polled();
Poll::Ready(Ok(()))
}
fn call(&self, (req, mut framed): (Request, Framed<T, h1::Codec>)) -> Self::Future {
2021-05-13 11:24:32 +00:00
assert!(self.was_polled());
Box::pin(async move {
let res = ws::handshake(req.head())?.message_body(())?;
framed.send((res, BodySize::None).into()).await?;
2021-05-13 11:24:32 +00:00
let framed = framed.replace_codec(ws::Codec::new());
2021-06-17 16:57:58 +00:00
ws::Dispatcher::with(framed, service)
.await
.map_err(|_| WsServiceError::Dispatcher)?;
2021-05-13 11:24:32 +00:00
Ok(())
})
}
}
2021-05-13 11:24:32 +00:00
async fn service(msg: Frame) -> Result<Message, Error> {
let msg = match msg {
2021-05-13 11:24:32 +00:00
Frame::Ping(msg) => Message::Pong(msg),
Frame::Text(text) => {
Message::Text(String::from_utf8_lossy(&text).into_owned().into())
}
2021-05-13 11:24:32 +00:00
Frame::Binary(bin) => Message::Binary(bin),
Frame::Continuation(item) => Message::Continuation(item),
Frame::Close(reason) => Message::Close(reason),
2021-06-17 16:57:58 +00:00
_ => return Err(ws::ProtocolError::BadOpCode.into()),
};
2021-05-13 11:24:32 +00:00
2019-11-19 12:54:19 +00:00
Ok(msg)
}
2019-11-26 05:25:50 +00:00
#[actix_rt::test]
async fn test_simple() {
2021-05-13 11:24:32 +00:00
let mut srv = test_server(|| {
HttpService::build()
2021-06-17 16:57:58 +00:00
.upgrade(fn_factory(|| async {
Ok::<_, Infallible>(WsService::new())
}))
.finish(|_| async { Ok::<_, Infallible>(Response::not_found()) })
2021-05-13 11:24:32 +00:00
.tcp()
2020-03-08 07:42:45 +00:00
})
.await;
2019-11-26 05:25:50 +00:00
// client service
let mut framed = srv.ws().await.unwrap();
2021-05-13 11:24:32 +00:00
framed.send(Message::Text("text".into())).await.unwrap();
2021-05-13 11:24:32 +00:00
let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, Frame::Text(Bytes::from_static(b"text")));
2021-05-13 11:24:32 +00:00
framed.send(Message::Binary("text".into())).await.unwrap();
let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, Frame::Binary(Bytes::from_static(&b"text"[..])));
framed.send(Message::Ping("text".into())).await.unwrap();
let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, Frame::Pong("text".to_string().into()));
framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::FirstText("text".into())))
.await
.unwrap();
2021-05-13 11:24:32 +00:00
let item = framed.next().await.unwrap().unwrap();
assert_eq!(
2021-05-13 11:24:32 +00:00
item,
Frame::Continuation(Item::FirstText(Bytes::from_static(b"text")))
);
assert!(framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::FirstText("text".into())))
.await
.is_err());
assert!(framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::FirstBinary("text".into())))
.await
.is_err());
framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::Continue("text".into())))
.await
.unwrap();
2021-05-13 11:24:32 +00:00
let item = framed.next().await.unwrap().unwrap();
assert_eq!(
2021-05-13 11:24:32 +00:00
item,
Frame::Continuation(Item::Continue(Bytes::from_static(b"text")))
);
framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::Last("text".into())))
.await
.unwrap();
2021-05-13 11:24:32 +00:00
let item = framed.next().await.unwrap().unwrap();
assert_eq!(
2021-05-13 11:24:32 +00:00
item,
Frame::Continuation(Item::Last(Bytes::from_static(b"text")))
);
assert!(framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::Continue("text".into())))
.await
.is_err());
assert!(framed
2021-05-13 11:24:32 +00:00
.send(Message::Continuation(Item::Last("text".into())))
.await
.is_err());
2019-11-26 05:25:50 +00:00
framed
2021-05-13 11:24:32 +00:00
.send(Message::Close(Some(CloseCode::Normal.into())))
2019-11-26 05:25:50 +00:00
.await
.unwrap();
2021-05-13 11:24:32 +00:00
let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, Frame::Close(Some(CloseCode::Normal.into())));
}