use fastwebsockets::{Frame, OpCode, Payload, WebSocketError, handshake, upgrade};
use fastwebsockets_stream::{PayloadType, WebSocketStream};
use futures::SinkExt;
use futures::StreamExt;
use http_body_util::Empty;
use hyper::Request;
use hyper::Response;
use hyper::body::Bytes;
use hyper::body::Incoming;
use hyper::header::CONNECTION;
use hyper::header::UPGRADE;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper_util::rt::TokioIo;
use std::future::Future;
use std::net::Ipv4Addr;
use tokio::net::TcpStream;
use tokio_util::codec::Framed;
use tokio_util::codec::LinesCodec;
struct SpawnExecutor;
impl<F> hyper::rt::Executor<F> for SpawnExecutor
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
fn execute(&self, fut: F) {
tokio::task::spawn(fut);
}
}
#[tokio::test]
async fn framed() {
let listener = tokio::net::TcpListener::bind((Ipv4Addr::LOCALHOST, 0u16))
.await
.unwrap();
let addr = listener.local_addr().unwrap();
tokio::spawn(async move {
loop {
let (stream, _) = listener.accept().await.unwrap();
let io = TokioIo::new(stream);
tokio::spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(io, service_fn(handle))
.with_upgrades()
.await
{
println!("Error serving connection: {:?}", err);
}
});
}
});
let stream = TcpStream::connect(addr).await.unwrap();
let request = Request::builder()
.method("GET")
.uri("ws://localhost")
.header("Host", "localhost")
.header(UPGRADE, "websocket")
.header(CONNECTION, "upgrade")
.header("Sec-WebSocket-Key", handshake::generate_key())
.header("Sec-WebSocket-Version", "13")
.body(Empty::<Bytes>::new())
.unwrap();
let (mut stream, _response) = handshake::client(&SpawnExecutor, request, stream)
.await
.unwrap();
let messages = &["Hello\n", "World\n", "!\n", "\n"];
for &message in messages {
stream
.write_frame(Frame::binary(Payload::Borrowed(message.as_bytes())))
.await
.unwrap();
let response = stream.read_frame().await.unwrap();
assert_eq!(response.opcode, OpCode::Binary);
assert!(response.payload.starts_with(message.as_bytes()));
}
stream
.write_frame(Frame::close_raw(Vec::new().into()))
.await
.unwrap();
}
async fn handle(mut request: Request<Incoming>) -> Result<Response<Empty<Bytes>>, WebSocketError> {
assert!(upgrade::is_upgrade_request(&request));
let (response, ws_fut) = upgrade::upgrade(&mut request)?;
tokio::spawn(async move {
let websocket = ws_fut.await.unwrap();
let mut stream = Framed::new(
WebSocketStream::new(websocket, PayloadType::Binary),
LinesCodec::new(),
);
while let Some(Ok(message)) = stream.next().await {
stream.send(message).await.unwrap();
}
});
Ok(response)
}