refactor http response and headers

This commit is contained in:
MeexReay 2024-06-23 16:23:41 +03:00
parent dcbe75f13c
commit b7cd187c0e
2 changed files with 55 additions and 57 deletions

View File

@ -1,11 +1,13 @@
use futures::executor::block_on; use futures::executor::block_on;
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration; use std::time::Duration;
use std::{ use std::{
boxed::Box, boxed::Box,
error::Error, error::Error,
fmt::{Debug, Display},
future::Future, future::Future,
net::{IpAddr, SocketAddr, ToSocketAddrs}, net::{IpAddr, SocketAddr, ToSocketAddrs},
sync::Arc, sync::Arc,
@ -21,66 +23,74 @@ pub struct Headers {
entries: Vec<(String, String)>, entries: Vec<(String, String)>,
} }
impl Headers { impl Into<HashMap<String, String>> for Headers {
pub fn from_entries(entries: Vec<(String, String)>) -> Self { fn into(self) -> HashMap<String, String> {
Headers { entries } HashMap::from_iter(self.entries().into_iter())
} }
}
pub fn from(entries: Vec<(&str, &str)>) -> Self { impl<T, U> From<Vec<(T, U)>> for Headers
where
T: ToString,
U: ToString,
{
fn from(value: Vec<(T, U)>) -> Self {
Headers { Headers {
entries: entries entries: value
.iter() .into_iter()
.map(|v| (v.0.to_string(), v.1.to_string())) .map(|v| (v.0.to_string(), v.1.to_string()))
.collect(), .collect(),
} }
} }
}
impl Headers {
pub fn new() -> Self { pub fn new() -> Self {
Headers { Headers {
entries: Vec::new(), entries: Vec::new(),
} }
} }
pub fn contains_value(self, value: String) -> bool { pub fn contains_value(self, value: impl ToString) -> bool {
for (_, v) in self.entries { for (_, v) in self.entries {
if v == value { if v == value.to_string() {
return true; return true;
} }
} }
return false; return false;
} }
pub fn contains_key(self, key: String) -> bool { pub fn contains_key(self, key: impl ToString) -> bool {
for (k, _) in self.entries { for (k, _) in self.entries {
if k == key.to_lowercase() { if k.to_lowercase() == key.to_string().to_lowercase() {
return true; return true;
} }
} }
return false; return false;
} }
pub fn get(self, key: String) -> Option<String> { pub fn get(self, key: impl ToString) -> Option<String> {
for (k, v) in self.entries { for (k, v) in self.entries {
if k == key.to_lowercase() { if k.to_lowercase() == key.to_string().to_lowercase() {
return Some(v); return Some(v);
} }
} }
return None; return None;
} }
pub fn put(&mut self, key: String, value: String) { pub fn put(&mut self, key: impl ToString, value: String) {
for t in self.entries.iter_mut() { for t in self.entries.iter_mut() {
if t.0 == key.to_lowercase() { if t.0.to_lowercase() == key.to_string().to_lowercase() {
t.1 = value; t.1 = value;
return; return;
} }
} }
self.entries.push((key.to_lowercase(), value)); self.entries.push((key.to_string(), value));
} }
pub fn remove(&mut self, key: String) { pub fn remove(&mut self, key: impl ToString) {
for (i, t) in self.entries.iter_mut().enumerate() { for (i, t) in self.entries.iter_mut().enumerate() {
if t.0 == key.to_lowercase() { if t.0.to_lowercase() == key.to_string().to_lowercase() {
self.entries.remove(i); self.entries.remove(i);
return; return;
} }
@ -88,19 +98,11 @@ impl Headers {
} }
pub fn keys(self) -> Vec<String> { pub fn keys(self) -> Vec<String> {
let mut keys = Vec::new(); self.entries.iter().map(|e| e.0.clone()).collect()
for (k, _) in self.entries {
keys.push(k.to_lowercase());
}
keys
} }
pub fn values(self) -> Vec<String> { pub fn values(self) -> Vec<String> {
let mut values = Vec::new(); self.entries.iter().map(|e| e.1.clone()).collect()
for (_, v) in self.entries {
values.push(v);
}
values
} }
pub fn entries(self) -> Vec<(String, String)> { pub fn entries(self) -> Vec<(String, String)> {
@ -116,9 +118,9 @@ impl Headers {
} }
} }
impl std::fmt::Display for Headers { impl Display for Headers {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f) Debug::fmt(self, f)
} }
} }
@ -132,9 +134,9 @@ pub struct HttpRequest {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl std::fmt::Display for HttpRequest { impl Display for HttpRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f) Debug::fmt(self, f)
} }
} }
@ -145,9 +147,9 @@ pub struct HttpResponse {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl std::fmt::Display for HttpResponse { impl Display for HttpResponse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f) Debug::fmt(self, f)
} }
} }
@ -173,7 +175,7 @@ impl std::fmt::Display for HttpError {
impl Error for HttpError {} impl Error for HttpError {}
fn read_line(data: &mut TcpStream) -> Result<String, HttpError> { fn read_line(data: &mut impl Read) -> Result<String, HttpError> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for byte in data.bytes() { for byte in data.bytes() {
@ -195,14 +197,14 @@ fn read_line(data: &mut TcpStream) -> Result<String, HttpError> {
} }
} }
fn read_line_crlf(data: &mut TcpStream) -> Result<String, HttpError> { fn read_line_crlf(data: &mut impl Read) -> Result<String, HttpError> {
match read_line(data) { match read_line(data) {
Ok(i) => Ok(i[..i.len() - 2].to_string()), Ok(i) => Ok(i[..i.len() - 2].to_string()),
Err(e) => Err(e), Err(e) => Err(e),
} }
} }
fn read_line_lf(data: &mut TcpStream) -> Result<String, HttpError> { fn read_line_lf(data: &mut impl Read) -> Result<String, HttpError> {
match read_line(data) { match read_line(data) {
Ok(i) => Ok(i[..i.len() - 1].to_string()), Ok(i) => Ok(i[..i.len() - 1].to_string()),
Err(e) => Err(e), Err(e) => Err(e),
@ -250,7 +252,7 @@ impl HttpRequest {
} }
} }
pub fn read(data: &mut TcpStream, addr: &SocketAddr) -> Result<HttpRequest, HttpError> { pub fn read(data: &mut impl Read, addr: &SocketAddr) -> Result<HttpRequest, HttpError> {
let octets = match addr.ip() { let octets = match addr.ip() {
IpAddr::V4(ip) => ip.octets(), IpAddr::V4(ip) => ip.octets(),
_ => [127, 0, 0, 1], _ => [127, 0, 0, 1],
@ -413,7 +415,7 @@ impl HttpRequest {
}) })
} }
pub fn read_with_rrs(data: &mut TcpStream) -> Result<HttpRequest, HttpError> { pub fn read_with_rrs(data: &mut impl Read) -> Result<HttpRequest, HttpError> {
let addr = match read_line_lf(data) { let addr = match read_line_lf(data) {
Ok(i) => i, Ok(i) => i,
Err(e) => { Err(e) => {
@ -448,7 +450,7 @@ impl HttpRequest {
self.page += query.as_str(); self.page += query.as_str();
} }
pub fn write(self, data: &mut TcpStream) -> Result<(), HttpError> { pub fn write(self, data: &mut impl Write) -> Result<(), HttpError> {
let mut head: String = String::new(); let mut head: String = String::new();
head.push_str(&self.method); head.push_str(&self.method);
head.push_str(" "); head.push_str(" ");
@ -482,27 +484,23 @@ impl HttpRequest {
} }
impl HttpResponse { impl HttpResponse {
pub fn new(headers: Headers, status_code: String, data: Vec<u8>) -> Self { pub fn new() -> Self {
Self::from_bytes(Headers::new(), "200 OK", Vec::new())
}
pub fn from_bytes(headers: Headers, status_code: impl ToString, data: Vec<u8>) -> Self {
HttpResponse { HttpResponse {
headers: headers, headers: headers,
data: data, data: data,
status_code: status_code, status_code: status_code.to_string(),
} }
} }
pub fn from_str(headers: Headers, status_code: String, data: &str) -> Self { pub fn from_string(headers: Headers, status_code: impl ToString, data: impl ToString) -> Self {
HttpResponse { HttpResponse {
headers: headers, headers: headers,
data: data.to_string().into_bytes(), data: data.to_string().into_bytes(),
status_code: status_code, status_code: status_code.to_string(),
}
}
pub fn from_string(headers: Headers, status_code: String, data: String) -> Self {
HttpResponse {
headers: headers,
data: data.into_bytes(),
status_code: status_code,
} }
} }
@ -520,7 +518,7 @@ impl HttpResponse {
} }
} }
pub fn read(data: &mut TcpStream) -> Result<HttpResponse, HttpError> { pub fn read(data: &mut impl Read) -> Result<HttpResponse, HttpError> {
let status = match read_line_crlf(data) { let status = match read_line_crlf(data) {
Ok(i) => i, Ok(i) => i,
Err(e) => { Err(e) => {
@ -600,7 +598,7 @@ impl HttpResponse {
}) })
} }
pub fn write(self, data: &mut TcpStream) -> Result<(), &str> { pub fn write(self, data: &mut impl Write) -> Result<(), &str> {
let mut head: String = String::new(); let mut head: String = String::new();
head.push_str("HTTP/1.1 "); head.push_str("HTTP/1.1 ");
head.push_str(&self.status_code); head.push_str(&self.status_code);

View File

@ -1,5 +1,5 @@
use ezhttp::{Headers, HttpRequest, HttpResponse, HttpServer, HttpServerStarter}; use ezhttp::{Headers, HttpRequest, HttpResponse, HttpServer, HttpServerStarter};
use std::time::Duration; use std::{collections::HashMap, time::Duration};
struct EzSite { struct EzSite {
index_page: String, index_page: String,
@ -18,10 +18,10 @@ impl HttpServer for EzSite {
println!("{} > {} {}", req.addr, req.method, req.page); println!("{} > {} {}", req.addr, req.method, req.page);
if req.page == "/" { if req.page == "/" {
Some(HttpResponse::from_str( Some(HttpResponse::from_string(
Headers::from(vec![("Content-Type", "text/html")]), // response headers Headers::from(vec![("Content-Type", "text/html")]), // response headers
"200 OK".to_string(), // response status code "200 OK", // response status code
&self.index_page, // response body self.index_page.clone(), // response body
)) ))
} else { } else {
None // close connection None // close connection