use tokio::io::{AsyncRead, AsyncWrite};
use tokio_tungstenite::tungstenite::handshake::server;
use tokio_tungstenite::tungstenite::http::HeaderValue;
use tokio_tungstenite::{WebSocketStream, tungstenite};
pub(crate) const SUBPROTOCOL: &str = "foxglove.sdk.v1";
pub(crate) async fn do_handshake<S: AsyncRead + AsyncWrite + Unpin>(
stream: S,
) -> Result<WebSocketStream<S>, tungstenite::Error> {
tokio_tungstenite::accept_hdr_async(
stream,
#[allow(clippy::result_large_err)]
|req: &server::Request, mut res: server::Response| {
let protocol_headers = req.headers().get_all("sec-websocket-protocol");
for header in &protocol_headers {
if header
.to_str()
.unwrap_or_default()
.split(',')
.any(|v| v.trim() == SUBPROTOCOL)
{
res.headers_mut().insert(
"sec-websocket-protocol",
HeaderValue::from_static(SUBPROTOCOL),
);
return Ok(res);
}
}
Err(server::Response::builder()
.status(400)
.body(Some(
"Missing expected sec-websocket-protocol header".into(),
))
.unwrap())
},
)
.await
}