So, the problem is that my server needs to handle connections of two types: basic HTTP requests or WebSocket handshakes. I'm using tokio-tungstenite library for performing WS handshakes. It takes ownership of the entire TcpStream and converts it to WebSocketStream. But I also need the ability to handle normal HTTP request and in order to do that I want to read just HTTP header from TcpStream and if it looks like the start of WS handshake then just pass TcpStream (without any mutation) to tungstenite library. Otherwise, handle HTTP requests as normal.
Just a sample of code to give some clarity:
async fn handle_connection(mut stream: TcpStream, state: Arc<State>) {
// TODO: read without mutation somehow
let mut buffer = /* */;
if let Ok(size) = stream.read(&mut buffer).await {
/* handle */
}
// TODO: only in case when it looks like WebSocket handshake
let mut ws = match accept_async(stream).await {
Ok(websocket) => /* handle WS connection */,
Err(error) => {
Logger::warning(format!("Failed to accept WebSocket connection: {}", error));
return
}
};
Is it possible? Or I need to find a way to pass just buffer with header to the WS library somehow?
use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::{Arc, atomic};
use std::path::{PathBuf, Path};
use tokio::runtime::Runtime;
use hyper::server::conn::AddrStream;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Server, Request, Response, Body, StatusCode};
use hyper::header::{HeaderValue, SEC_WEBSOCKET_KEY, CONTENT_TYPE, CONTENT_LENGTH};
use tokio_tungstenite::WebSocketStream;
use crate::websocket::websocket_handle_events;
use crate::{BoxError, Settings, Shared};
use crate::state::Command;
use tokio::sync::mpsc::channel;
use std::sync::atomic::AtomicU64;