rustlavel_http/upgrade.rs
1//! Handing a connection over to another protocol.
2//!
3//! HTTP/1.1 lets a client ask to stop speaking HTTP and start speaking
4//! something else — that is how WebSocket begins. A handler answers `101` and
5//! attaches an [`Upgrade`]; the server then stops managing the socket and hands
6//! it over.
7
8use crate::handler::BoxFuture;
9use std::sync::Arc;
10use tokio::io::{AsyncRead, AsyncWrite};
11
12/// The socket, after HTTP is finished with it.
13///
14/// Boxed so the upgraded protocol does not have to name the concrete stream
15/// type, which differs between a plain and (later) a TLS connection.
16pub struct Upgraded {
17 pub reader: Box<dyn AsyncRead + Send + Unpin>,
18 pub writer: Box<dyn AsyncWrite + Send + Unpin>,
19 /// Bytes the client sent after the request but before the upgrade
20 /// completed. Dropping these loses the first frame.
21 pub buffered: Vec<u8>,
22}
23
24/// What takes over the connection.
25pub trait Upgrade: Send + Sync + 'static {
26 fn run(&self, connection: Upgraded) -> BoxFuture<()>;
27}
28
29impl<F, Fut> Upgrade for F
30where
31 F: Fn(Upgraded) -> Fut + Send + Sync + 'static,
32 Fut: Future<Output = ()> + Send + 'static,
33{
34 fn run(&self, connection: Upgraded) -> BoxFuture<()> {
35 Box::pin(self(connection))
36 }
37}
38
39/// An upgrade attached to a response, shared so the response stays cloneable.
40pub type Upgrader = Arc<dyn Upgrade>;