dhttp/reqres/
body.rs

1use std::io;
2use std::fmt;
3use std::pin::Pin;
4
5use tokio::fs::File;
6
7use crate::core::connection::HttpConnection;
8use crate::util::escape;
9
10/// Http protocol upgrade
11///
12/// Allows to access underlying TCP socket with your handler
13///
14/// Use in [`HttpBody::Upgrade`]. Only applicable to HTTP/1.1
15pub trait HttpUpgrade: Send {
16    /// Handles the upgrade
17    ///
18    /// Equivalent signature:
19    /// `async fn upgrade(&mut self, conn: &mut dyn HttpConnection) -> io::Result<()>`
20    fn upgrade(&mut self, conn: &mut dyn HttpConnection) -> impl Future<Output = io::Result<()>> + Send;
21}
22
23/// Dyn version of [`HttpUpgrade`]
24pub trait HttpUpgradeRaw: Send {
25    /// Handles the upgrade (dyn version)
26    fn upgrade_raw<'a>(&'a mut self, conn: &'a mut dyn HttpConnection) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send + 'a>>;
27}
28
29impl<T: HttpUpgrade> HttpUpgradeRaw for T {
30    fn upgrade_raw<'a>(&'a mut self, conn: &'a mut dyn HttpConnection) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send + 'a>> {
31        Box::pin(self.upgrade(conn))
32    }
33}
34
35/// Body of the response
36#[non_exhaustive]
37pub enum HttpBody {
38    /// No data, **does not have Content-Length**
39    Empty,
40    /// In-memory bytes
41    Bytes(Vec<u8>),
42    /// File handle to read
43    File { file: File, len: u64 },
44    /// Protocol upgrade
45    Upgrade(Box<dyn HttpUpgradeRaw>),
46}
47
48impl fmt::Debug for HttpBody {
49    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            HttpBody::Empty => fmt.write_str("HttpBody::Empty"),
52            HttpBody::Bytes(v) => write!(fmt, r#"HttpBody::Bytes(b"{}")"#, escape::to_utf8(v)),
53            HttpBody::File { file, len } => fmt.debug_struct("HttpBody::File").field("file", file).field("len", len).finish(),
54            HttpBody::Upgrade(_) => fmt.write_str("HttpBody::Upgrade(..)"),
55        }
56    }
57}
58
59impl From<Vec<u8>> for HttpBody {
60    fn from(v: Vec<u8>) -> HttpBody {
61        HttpBody::Bytes(v)
62    }
63}
64
65impl From<String> for HttpBody {
66    fn from(s: String) -> HttpBody {
67        HttpBody::Bytes(s.into_bytes())
68    }
69}
70
71impl From<&str> for HttpBody {
72    fn from(s: &str) -> HttpBody {
73        HttpBody::Bytes(s.to_string().into_bytes())
74    }
75}