Skip to main content

trillium/
upgrade.rs

1use crate::{Headers, HttpContext, Method, Transport, TypeSet, Version};
2use futures_lite::{AsyncRead, AsyncWrite};
3use std::{net::IpAddr, sync::Arc};
4use trillium_http::Swansong;
5use trillium_macros::{AsyncRead, AsyncWrite};
6
7/// # A HTTP protocol upgrade
8#[derive(Debug, AsyncWrite, AsyncRead)]
9pub struct Upgrade(trillium_http::Upgrade<Box<dyn Transport>>);
10
11impl<T: Transport + 'static> From<trillium_http::Upgrade<T>> for Upgrade {
12    fn from(value: trillium_http::Upgrade<T>) -> Self {
13        Self(value.map_transport(|t| Box::new(t) as Box<dyn Transport>))
14    }
15}
16
17impl<T: Transport + 'static> From<trillium_http::Conn<T>> for Upgrade {
18    fn from(value: trillium_http::Conn<T>) -> Self {
19        trillium_http::Upgrade::from(value).into()
20    }
21}
22
23impl From<crate::Conn> for Upgrade {
24    fn from(value: crate::Conn) -> Self {
25        Self(value.inner.into())
26    }
27}
28
29impl Upgrade {
30    /// Borrows the HTTP request headers
31    pub fn request_headers(&self) -> &Headers {
32        self.0.request_headers()
33    }
34
35    /// Take the HTTP request headers
36    pub fn take_request_headers(&mut self) -> Headers {
37        std::mem::take(self.0.request_headers_mut())
38    }
39
40    /// Returns a copy of the HTTP request method
41    pub fn method(&self) -> Method {
42        self.0.method()
43    }
44
45    /// Borrows the state accumulated on the Conn before negotiating the upgrade
46    pub fn state(&self) -> &TypeSet {
47        self.0.state()
48    }
49
50    /// Takes the [`TypeSet`] accumulated on the Conn before negotiating the upgrade
51    pub fn take_state(&mut self) -> TypeSet {
52        std::mem::take(self.0.state_mut())
53    }
54
55    /// Mutably borrow the [`TypeSet`] accumulated on the Conn before negotiating the upgrade
56    pub fn state_mut(&mut self) -> &mut TypeSet {
57        self.0.state_mut()
58    }
59
60    /// Borrows the underlying transport
61    pub fn transport(&self) -> &dyn Transport {
62        self.0.transport().as_ref()
63    }
64
65    /// Mutably borrow the underlying transport
66    ///
67    /// This returns a tuple of (buffered bytes, transport) in order to make salient the requirement
68    /// to handle any buffered bytes before using the transport directly.
69    pub fn transport_mut(&mut self) -> (&[u8], &mut dyn Transport) {
70        let (buffer, transport) = self.0.buffer_and_transport_mut();
71        (&*buffer, &mut **transport)
72    }
73
74    /// Consumes self, returning the underlying transport
75    ///
76    /// This returns a tuple of (buffered bytes, transport) in order to make salient the requirement
77    /// to handle any buffered bytes before using the transport directly.
78    pub fn into_transport(mut self) -> (Vec<u8>, Box<dyn Transport>) {
79        let buffer = self.0.take_buffer();
80        (buffer, self.0.into_transport())
81    }
82
83    /// Returns a copy of the peer IP address of the connection, if available
84    pub fn peer_ip(&self) -> Option<IpAddr> {
85        self.0.peer_ip()
86    }
87
88    /// Borrows the :authority HTTP/3 pseudo-header
89    pub fn authority(&self) -> Option<&str> {
90        self.0.authority()
91    }
92
93    /// Borrows the :scheme HTTP/3 pseudo-header
94    pub fn scheme(&self) -> Option<&str> {
95        self.0.scheme()
96    }
97
98    /// Borrows the :protocol HTTP/3 pseudo-header
99    pub fn protocol(&self) -> Option<&str> {
100        self.0.protocol()
101    }
102
103    /// Borrows the HTTP version
104    pub fn http_version(&self) -> &Version {
105        self.0.http_version()
106    }
107
108    /// Returns a copy of whether this connection was deemed secure by the handler stack
109    pub fn is_secure(&self) -> bool {
110        self.0.is_secure()
111    }
112
113    /// Borrows the shared state [`TypeSet`] for this application
114    pub fn shared_state(&self) -> &TypeSet {
115        self.0.shared_state()
116    }
117
118    /// Returns the HTTP request path up to but excluding any query component
119    pub fn path(&self) -> &str {
120        self.0.path()
121    }
122
123    /// Retrieves the query component of the path
124    pub fn querystring(&self) -> &str {
125        self.0.querystring()
126    }
127
128    /// Retrieves a cloned [`Swansong`] graceful shutdown controller
129    pub fn swansong(&self) -> Swansong {
130        self.0.context().swansong().clone()
131    }
132
133    /// Retrieves a clone of the [`HttpContext`] for this upgrade
134    pub fn context(&self) -> Arc<HttpContext> {
135        self.0.context().clone()
136    }
137
138    /// Returns a clone of the H3 connection, if any
139    pub fn h3_connection(&self) -> Option<Arc<trillium_http::h3::H3Connection>> {
140        self.0.h3_connection().cloned()
141    }
142}