You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kchan/src/http.rs

96 lines
1.8 KiB
Rust

use std::fmt;
use std::str::FromStr;
const HTTP_VERSION: &str = "HTTP/1.1";
// TODO use &str
#[derive(Debug)]
pub struct Request {
pub method: String,
pub uri: String,
pub headers: Vec<(String, String)>,
pub body: String,
}
#[derive(Debug)]
pub struct Response {
pub status: Status,
pub headers: Vec<(String, String)>,
pub body: String,
}
#[derive(Debug, Clone, Copy)]
pub enum Status {
OK = 200,
NOTFOUND = 404,
}
impl Status {
pub fn get_message(&self) -> &'static str {
match self {
Self::OK => "OK",
Self::NOTFOUND => "NOT FOUND",
}
}
}
// TODO implement this with display and enums
// TODO proper errors
impl FromStr for Request {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut iter = dbg!(s).lines();
let mut first = iter.nth(0).unwrap().split_whitespace();
let method = first.next().unwrap().to_string();
let uri = first.next().unwrap().to_string();
let mut headers: Vec<(String, String)> = vec![];
for line in &mut iter {
if line.is_empty() {
break;
}
let line: Vec<&str> = line.split(":").take(2).collect();
headers.push((line[0].into(), line[1].into()));
}
let body: String = iter.fold(String::new(), |a, b| format!("{}{}", a, b));
Ok(Self {
method,
uri,
headers,
body,
})
}
}
impl Response {
pub fn new(status: Status, headers: Vec<(String, String)>, body: String) -> Self {
Self {
status,
headers,
body,
}
}
}
impl fmt::Display for Response {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let headers: String = self
.headers
.iter()
.map(|x| format!("{}:{}", x.0, x.1))
.fold(String::from(""), |a, b| format!("{}\n{}", a, b)); // possibly slow
write!(
f,
"{} {} {}\n{}\n\n{}",
HTTP_VERSION,
self.status as i32,
self.status.get_message(),
headers,
self.body,
)
}
}