tokio_websockets/
server.rs1use std::{future::poll_fn, io, pin::Pin};
9
10use futures_core::Stream;
11use http::{HeaderMap, HeaderName, HeaderValue, header};
12use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
13use tokio_util::codec::FramedRead;
14
15use crate::{
16 Error, WebSocketStream,
17 proto::{Config, Limits, Role},
18 upgrade::client_request,
19};
20
21const BAD_REQUEST: &[u8] = b"HTTP/1.1 400 Bad Request\r\n\r\n";
23
24pub const DISALLOWED_HEADERS: &[HeaderName] = &[
32 header::UPGRADE,
33 header::CONNECTION,
34 header::SEC_WEBSOCKET_ACCEPT,
35];
36
37pub struct Builder {
39 config: Config,
41 limits: Limits,
43 headers: HeaderMap,
45}
46
47impl Default for Builder {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl Builder {
54 #[must_use]
57 pub fn new() -> Self {
58 Self {
59 config: Config::default(),
60 limits: Limits::default(),
61 headers: HeaderMap::new(),
62 }
63 }
64
65 #[must_use]
67 pub fn config(mut self, config: Config) -> Self {
68 self.config = config;
69
70 self
71 }
72
73 #[must_use]
75 pub fn limits(mut self, limits: Limits) -> Self {
76 self.limits = limits;
77
78 self
79 }
80
81 pub fn add_header(mut self, name: HeaderName, value: HeaderValue) -> Result<Self, Error> {
88 if DISALLOWED_HEADERS.contains(&name) {
89 return Err(Error::DisallowedHeader);
90 }
91 self.headers.insert(name, value);
92
93 Ok(self)
94 }
95
96 pub async fn accept<S: AsyncRead + AsyncWrite + Unpin>(
103 &self,
104 stream: S,
105 ) -> Result<(http::Request<()>, WebSocketStream<S>), Error> {
106 let mut framed = FramedRead::new(
107 stream,
108 client_request::Codec {
109 response_headers: &self.headers,
110 },
111 );
112 let reply = poll_fn(|cx| Pin::new(&mut framed).poll_next(cx)).await;
113
114 match reply {
115 Some(Ok((request, response))) => {
116 framed.get_mut().write_all(&response).await?;
117 Ok((
118 request,
119 WebSocketStream::from_framed(framed, Role::Server, self.config, self.limits),
120 ))
121 }
122 Some(Err(e)) => {
123 framed.get_mut().write_all(BAD_REQUEST).await?;
124
125 Err(e)
126 }
127 None => Err(Error::Io(io::ErrorKind::UnexpectedEof.into())),
128 }
129 }
130
131 pub fn serve<S: AsyncRead + AsyncWrite + Unpin>(&self, stream: S) -> WebSocketStream<S> {
136 WebSocketStream::from_raw_stream(stream, Role::Server, self.config, self.limits)
137 }
138}