Files
fluffle/src/server.rs
2024-11-14 20:37:26 -08:00

103 lines
3.3 KiB
Rust

use std::{
collections::HashMap,
io::{Read, Write},
net::TcpListener,
str::from_utf8,
sync::{Arc, Mutex},
thread,
};
use crate::{
http::{request::RequestLine, Request, Response},
Client,
};
pub struct Server {
listener: TcpListener,
on_request: Arc<Mutex<Option<Box<dyn Fn(Request) -> Response + Send + 'static>>>>,
}
impl Server {
pub fn new(ip: &str, port: i32) -> Self {
let addr = format!("{}:{}", ip, port);
let listener = TcpListener::bind(addr).unwrap();
Server {
listener,
on_request: Arc::new(Mutex::new(None)),
}
}
pub fn run(&mut self) {
for stream in self.listener.incoming() {
let stream = stream.unwrap();
let on_request = Arc::clone(&self.on_request);
thread::spawn(move || {
let mut client = Client::new(stream);
let mut buffer = vec![0; 1024];
let bytes_read = client.read(&mut buffer).unwrap();
if bytes_read > 0 {
if let Ok(request_str) = from_utf8(&buffer[..bytes_read]) {
if let Some(on_request) = &*on_request.lock().unwrap() {
let request;
{
let mut lines = request_str.lines();
let request_line = RequestLine::from_str(lines.next().unwrap());
let mut headers = HashMap::new();
for line in lines {
if let Some((k, v)) = line.split_once(": ") {
headers.insert(k, v);
}
}
request = Request {
request_line,
headers,
};
}
let response = on_request(request);
{
let response_line = response.response_line.to_string();
client.write_string(response_line).unwrap();
if let Some(headers) = response.headers {
for (k, v) in headers {
client.write_string(format!("{}: {}", k, v)).unwrap();
}
} else {
client.write(b"\r\n").unwrap();
}
if let Some(content) = response.content {
client.write(b"\r\n").unwrap();
client.write(&content).unwrap();
} else {
client.write(b"\r\n").unwrap();
}
}
client.flush().unwrap();
}
}
}
});
}
}
pub fn on_request<F>(&mut self, f: F)
where
F: Fn(Request) -> Response + Send + 'static,
{
*self.on_request.lock().unwrap() = Some(Box::new(f))
}
}