lazy_sock/
response.rs

1/* src/response.rs */
2
3use std::collections::HashMap;
4
5/// Represents an HTTP-like response.
6#[derive(Debug, Clone)]
7pub struct Response {
8    status_code: u16,
9    headers: HashMap<String, String>,
10    body: Vec<u8>,
11}
12
13impl Response {
14    /// Creates a new response with a given status code.
15    pub fn new(status_code: u16) -> Self {
16        Self {
17            status_code,
18            headers: HashMap::new(),
19            body: Vec::new(),
20        }
21    }
22
23    /// Creates a 200 OK response.
24    pub fn ok() -> Self {
25        Self::new(200)
26    }
27
28    /// Creates a 404 Not Found response.
29    pub fn not_found(message: &str) -> Self {
30        Self::new(404).with_text(message)
31    }
32
33    /// Creates a 500 Internal Server Error response.
34    pub fn internal_error(message: &str) -> Self {
35        Self::new(500).with_text(message)
36    }
37
38    /// Adds a header to the response.
39    pub fn with_header(mut self, name: &str, value: &str) -> Self {
40        self.headers.insert(name.to_string(), value.to_string());
41        self
42    }
43
44    /// Sets a plain text body for the response.
45    pub fn with_text(mut self, text: &str) -> Self {
46        self.body = text.as_bytes().to_vec();
47        self.headers.insert(
48            "Content-Type".to_string(),
49            "text/plain; charset=utf-8".to_string(),
50        );
51        self.headers
52            .insert("Content-Length".to_string(), self.body.len().to_string());
53        self
54    }
55
56    /// Sets a JSON body for the response.
57    pub fn with_json(mut self, json_str: &str) -> Self {
58        self.body = json_str.as_bytes().to_vec();
59        self.headers
60            .insert("Content-Type".to_string(), "application/json".to_string());
61        self.headers
62            .insert("Content-Length".to_string(), self.body.len().to_string());
63        self
64    }
65
66    /// Sets an HTML body for the response.
67    pub fn with_html(mut self, html: &str) -> Self {
68        self.body = html.as_bytes().to_vec();
69        self.headers.insert(
70            "Content-Type".to_string(),
71            "text/html; charset=utf-8".to_string(),
72        );
73        self.headers
74            .insert("Content-Length".to_string(), self.body.len().to_string());
75        self
76    }
77
78    /// Sets a binary body for the response.
79    pub fn with_binary(mut self, data: Vec<u8>, content_type: &str) -> Self {
80        self.body = data;
81        self.headers
82            .insert("Content-Type".to_string(), content_type.to_string());
83        self.headers
84            .insert("Content-Length".to_string(), self.body.len().to_string());
85        self
86    }
87
88    /// Gets the status code.
89    pub fn status_code(&self) -> u16 {
90        self.status_code
91    }
92
93    /// Gets the response headers.
94    pub fn headers(&self) -> &HashMap<String, String> {
95        &self.headers
96    }
97
98    /// Gets the response body.
99    pub fn body(&self) -> &[u8] {
100        &self.body
101    }
102
103    /// Converts the Response struct into a raw HTTP response string.
104    pub fn to_http_response(&self) -> String {
105        let status_line = format!("HTTP/1.1 {} {}", self.status_code, self.status_text());
106        let mut headers_string = String::new();
107        for (key, value) in &self.headers {
108            headers_string.push_str(&format!("{}: {}\r\n", key, value));
109        }
110        let body_string = String::from_utf8_lossy(&self.body);
111
112        format!("{}\r\n{}\r\n{}", status_line, headers_string, body_string)
113    }
114
115    /// Returns the standard reason phrase for a status code.
116    fn status_text(&self) -> &'static str {
117        match self.status_code {
118            200 => "OK",
119            201 => "Created",
120            204 => "No Content",
121            400 => "Bad Request",
122            401 => "Unauthorized",
123            403 => "Forbidden",
124            404 => "Not Found",
125            500 => "Internal Server Error",
126            _ => "Unknown",
127        }
128    }
129}
130
131// Convenience functions for creating common response types.
132impl Response {
133    /// Creates a 200 OK response with a JSON body.
134    pub fn json(data: &str) -> Self {
135        Self::ok().with_json(data)
136    }
137
138    /// Creates a 200 OK response with a plain text body.
139    pub fn text(text: &str) -> Self {
140        Self::ok().with_text(text)
141    }
142
143    /// Creates a 200 OK response with an HTML body.
144    pub fn html(html: &str) -> Self {
145        Self::ok().with_html(html)
146    }
147}