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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
use super::{error::Error, r#type::Response};
use crate::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(OK),
headers: HashMap::new(),
body: Vec::new(),
response: Vec::new(),
}
}
/// Sets the HTTP version for the response.
///
/// # Parameters
/// - `version`: The HTTP version to set (e.g., HTTP/1.1).
///
/// # Returns
/// - A mutable reference to the `Response` for chaining.
pub fn version<S: Into<Cow<'static, str>>>(&mut self, version: S) -> &mut Self {
self.version = version.into();
self
}
/// Sets the HTTP status code for the response.
///
/// # Parameters
/// - `code`: The status code to set (e.g., 404).
///
/// # Returns
/// - A mutable reference to the `Response` for chaining.
pub fn status_code(&mut self, code: usize) -> &mut Self {
self.status_code = code;
self.reason_phrase(StatusCode::phrase(code));
self
}
/// Sets the reason phrase for the response.
///
/// # Parameters
/// - `phrase`: The reason phrase to set (e.g., Not Found).
///
/// # Returns
/// - A mutable reference to the `Response` for chaining.
pub fn reason_phrase<S: Into<Cow<'static, str>>>(&mut self, phrase: S) -> &mut Self {
self.reason_phrase = phrase.into();
self
}
/// Adds a header to the response.
///
/// # Parameters
/// - `key`: The name of the header.
/// - `value`: The value of the header.
///
/// # Returns
/// - A mutable reference to the `Response` for chaining.
pub fn 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
}
/// Sets the body of the response.
///
/// # Parameters
/// - `body`: The body content as a byte vector.
///
/// # Returns
/// - A mutable reference to the `Response` for chaining.
pub fn body<B: Into<Vec<u8>>>(&mut self, body: B) -> &mut Self {
self.body = body.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) -> Vec<u8> {
let mut response_str: String = String::new();
response_str.push_str(&format!(
"{}{}{}{}{}{}",
self.version, SPACE, self.status_code, SPACE, self.reason_phrase, HTTP_BR
));
for (key, value) in &self.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.body);
self.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) -> Result<(), Error> {
if self.response.is_empty() {
self.response = self.build();
}
stream
.write_all(&self.response)
.map_err(|err| Error::ResponseError(err.to_string()))
.and_then(|_| Ok(()))
}
}