http_handle/response.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
use crate::error::ServerError;
use serde::{Deserialize, Serialize};
use std::io::Write;
use std::net::TcpStream;
/// Represents an HTTP response, including the status code, status text, headers, and body.
#[derive(
Clone, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize,
)]
pub struct Response {
/// The HTTP status code (e.g., 200 for OK, 404 for Not Found).
pub status_code: u16,
/// The HTTP status text associated with the status code (e.g., "OK", "Not Found").
pub status_text: String,
/// A list of headers in the response, each represented as a tuple containing the header
/// name and its corresponding value.
pub headers: Vec<(String, String)>,
/// The body of the response, represented as a vector of bytes.
pub body: Vec<u8>,
}
impl Response {
/// Creates a new `Response` with the given status code, status text, and body.
///
/// The headers are initialized as an empty list and can be added later using the `add_header` method.
///
/// # Arguments
///
/// * `status_code` - The HTTP status code for the response.
/// * `status_text` - The status text corresponding to the status code.
/// * `body` - The body of the response, represented as a vector of bytes.
///
/// # Returns
///
/// A new `Response` instance with the specified status code, status text, and body.
pub fn new(
status_code: u16,
status_text: &str,
body: Vec<u8>,
) -> Self {
Response {
status_code,
status_text: status_text.to_string(),
headers: Vec::new(),
body,
}
}
/// Adds a header to the response.
///
/// This method allows you to add custom headers to the response, which will be included
/// in the HTTP response when it is sent to the client.
///
/// # Arguments
///
/// * `name` - The name of the header (e.g., "Content-Type").
/// * `value` - The value of the header (e.g., "text/html").
pub fn add_header(&mut self, name: &str, value: &str) {
self.headers.push((name.to_string(), value.to_string()));
}
/// Sends the response over the provided `TcpStream`.
///
/// This method writes the HTTP status line, headers, and body to the stream, ensuring
/// the client receives the complete response. It uses the `write!` macro and the `TcpStream`
/// to communicate with the client.
///
/// # Arguments
///
/// * `stream` - A mutable reference to the `TcpStream` over which the response will be sent.
///
/// # Returns
///
/// * `Ok(())` - If the response is successfully sent.
/// * `Err(ServerError)` - If an error occurs while sending the response.
///
/// # Errors
///
/// This function returns a `ServerError` if there is any issue writing to the stream or
/// sending the response data.
pub fn send(
&self,
stream: &mut TcpStream,
) -> Result<(), ServerError> {
write!(
stream,
"HTTP/1.1 {} {}\r\n",
self.status_code, self.status_text
)?;
for (name, value) in &self.headers {
write!(stream, "{}: {}\r\n", name, value)?;
}
write!(stream, "\r\n")?;
stream.write_all(&self.body)?;
stream.flush()?;
Ok(())
}
}