feather_runtime/http/
response.rs

1use bytes::Bytes;
2use http::{HeaderMap, HeaderName, HeaderValue, StatusCode};
3use serde::Serialize;
4use std::{fmt::Display, fs::File, io::Read, str::FromStr};
5
6#[derive(Debug, Clone, Default)]
7pub struct Response {
8    /// The HTTP status code of the response.
9    /// This is a 3-digit integer that indicates the result of the request.
10    pub status: StatusCode,
11    /// The headers of the HTTP response.
12    /// Headers are key-value pairs that provide additional information about the response.
13    pub headers: HeaderMap,
14    /// The body of the HTTP response.
15    /// This is the content that is sent back to the client.
16    /// The body is represented as a `Bytes` object for efficient handling of binary data.
17    pub body: Option<Bytes>,
18    /// The HTTP version of the response.
19    pub version: http::Version,
20}
21
22impl Response {
23    /// Sets the StatusCode of the response and Returns a Muteable Reference to the Response so you can things like
24    /// ```rust,ignore
25    /// res.status(200).send_text("eyo");
26    /// ```
27    /// The StatusCode is a 3-digit integer that indicates the result of the request.    
28    pub fn set_status(&mut self, status: u16) -> &mut Response {
29        self.status = StatusCode::from_u16(status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
30        self
31    }
32    /// Adds a header to the response.
33    /// The header is a key-value pair that provides additional information about the response.
34    pub fn add_header(&mut self, key: &str, value: &str) -> Option<()> {
35        if let Ok(val) = HeaderValue::from_str(value) {
36            if let Ok(key) = HeaderName::from_str(key) {
37                self.headers.insert(key, val);
38            }
39            return None;
40        }
41        None
42    }
43    /// Converts the `HttpResponse` into a raw HTTP response as Bytes.
44    pub fn to_raw(&self) -> Bytes {
45        let mut response = format!("HTTP/1.1 {} {}\r\n", self.status.as_u16(), self.status.canonical_reason().unwrap_or("Unknown")).into_bytes();
46
47        for (key, value) in &self.headers {
48            response.extend_from_slice(format!("{}: {}\r\n", key, value.to_str().unwrap()).as_bytes());
49        }
50
51        response.extend_from_slice(b"\r\n");
52
53        if let Some(ref body) = self.body {
54            response.extend_from_slice(body);
55        }
56
57        Bytes::from(response)
58    }
59
60    /// Converts the `HttpResponse` into a raw HTTP response as bytes.
61    pub fn to_bytes(&self) -> Bytes {
62        let mut response = self.to_string().into_bytes();
63        if let Some(ref body) = self.body {
64            response.extend_from_slice(body);
65        }
66
67        Bytes::from(response)
68    }
69    /// Sends given String as given text
70    pub fn send_text(&mut self, data: impl Into<String>) {
71        let body = data.into();
72        self.body = Some(Bytes::from(body));
73        self.headers.insert("Content-Type", "text/plain;charset=utf-8".parse().unwrap());
74        self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
75        self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
76    }
77    /// Sends Given Bytes as plain text
78    pub fn send_bytes(&mut self, data: impl Into<Vec<u8>>) {
79        let body = data.into();
80        self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
81        self.body = Some(Bytes::from(body));
82        self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
83    }
84    ///Takes a String(Should be valid HTML) and sends it's as Html
85    pub fn send_html(&mut self, data: impl Into<String>) {
86        let body = data.into();
87        self.body = Some(Bytes::from(body));
88        self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
89        self.headers.insert("Content-Type", "text/html".parse().unwrap());
90        self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
91    }
92
93    /// Takes a Serializeable object and sends it as json.
94    #[cfg(feature = "json")]
95    pub fn send_json<T: Serialize>(&mut self, data: T) {
96        match serde_json::to_string(&data) {
97            Ok(json) => {
98                self.body = Some(Bytes::from(json));
99                self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
100                self.headers.insert("Content-Type", HeaderValue::from_static("application/json"));
101                self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
102            }
103            Err(_) => {
104                self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
105                self.status = StatusCode::INTERNAL_SERVER_ERROR;
106                self.body = Some(Bytes::from("Internal Server Error"));
107                self.headers.insert("Content-Type", HeaderValue::from_static("text/plain"));
108                self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
109            }
110        }
111    }
112    /// Take a [File] Struct and sends it as a file
113    pub fn send_file(&mut self, mut file: File) {
114        let mut buffer = Vec::new();
115        match file.read_to_end(&mut buffer) {
116            Ok(_) => {
117                self.body = Some(Bytes::from(buffer));
118                self.headers.insert("Date", chrono::Utc::now().to_string().parse().unwrap());
119                self.headers.insert("Content-Length", self.body.as_ref().unwrap().len().to_string().parse().unwrap());
120            }
121            Err(_) => {
122                self.status = StatusCode::INTERNAL_SERVER_ERROR;
123                self.body = Some(Bytes::from("Internal Server Error"));
124            }
125        }
126    }
127}
128
129impl Display for Response {
130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131        write!(f, "{}", self.to_string())
132    }
133}