http_type/response/impl.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
use super::{error::Error, r#type::Response};
use crate::{ResponseData, ResponseResult, StatusCode};
use http_constant::*;
use std::{borrow::Cow, collections::HashMap, io::Write, net::TcpStream};
impl Default for Response {
fn default() -> Self {
Self::new()
}
}
impl Response {
/// Creates a new instance of `Response`.
///
/// # Returns
/// - An initialized `Response` with default values.
pub fn new() -> Self {
Response {
version: Cow::Borrowed(HTTP_VERSION_1_1),
status_code: 200,
reason_phrase: Cow::Borrowed(EMPTY_STR),
headers: HashMap::new(),
body: Vec::new(),
response: Vec::new(),
}
}
/// Adds a header to the response.
///
/// This function inserts a key-value pair into the response headers.
/// The key and value are converted into `Cow<'a, str>`, allowing for efficient handling of both owned and borrowed string data.
///
/// # Parameters
/// - `key`: The header key, which will be converted into a `Cow<'a, str>`.
/// - `value`: The value of the header, which will be converted into a `Cow<'a, str>`.
///
/// # Returns
/// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: Into<Cow<'static, str>>,
V: Into<Cow<'static, str>>,
{
self.headers.insert(key.into(), value.into());
self
}
/// Builds the full HTTP response as a byte vector.
///
/// # Returns
/// - The serialized HTTP response including headers and body.
pub fn build(&mut self) -> ResponseData {
if self.reason_phrase.is_empty() {
self.set_reason_phrase(StatusCode::phrase(*self.get_status_code()).into());
}
let mut response_str: String = String::new();
response_str.push_str(&format!(
"{}{}{}{}{}{}",
self.get_version(),
SPACE,
self.get_status_code(),
SPACE,
self.get_reason_phrase(),
HTTP_BR
));
for (key, value) in self.get_headers() {
response_str.push_str(&format!("{}{}{}{}", key, COLON_SPACE, value, HTTP_BR));
}
response_str.push_str(HTTP_BR);
let mut response_bytes: Vec<u8> = response_str.into_bytes();
response_bytes.extend_from_slice(self.get_body());
self.set_response(response_bytes.clone());
response_bytes
}
/// Sends the HTTP response over a TCP stream.
///
/// # Parameters
/// - `stream`: A mutable reference to the `TcpStream` to send the response.
///
/// # Returns
/// - `Ok`: If the response is successfully sent.
/// - `Err`: If an error occurs during sending.
pub fn send(&mut self, mut stream: &TcpStream) -> ResponseResult {
if self.response.is_empty() {
let response: ResponseData = self.build();
self.set_response(response);
}
let send_res: ResponseResult = stream
.write_all(&self.response)
.map_err(|err| Error::ResponseError(err.to_string()))
.and_then(|_| Ok(self.get_response()))
.cloned();
send_res
}
}