use std::{collections::HashMap, net::{SocketAddr, TcpListener}}; use inferium::{ h1::{ProtocolVariant, Request, ResponseHead, ServerSendError, SyncServer}, HeaderKey, Method, Status, StdInet }; fn main() { let listener = TcpListener::bind("localhost:8080").unwrap(); loop { let (conn, addr) = listener.accept().unwrap(); println!("connection from {addr:?}"); let mut server_handler = SyncServer::::new(StdInet::new(conn)); // We'll serve the client as long as it sends valid requests. // Note that this will effectively block other clients. while let Ok(request) = server_handler.receive_request() { // This matching is here to provide a way of controlling the while loop. match handle_request(request, addr) { Ok((h, b)) => if let Err(_) = send_response(h, b, &mut server_handler) { break; }, Err(()) => break, } }; println!("ended connection for {addr:?}"); } } fn handle_request( req: Request, addr: SocketAddr ) -> Result<(ResponseHead, &'static [u8]), ()> { let Request::HeadersOnly(headers) = req else { // We will not handle POST requests with bodies - so let's tell the client to f*ck off. return Err(()); }; println!("req from {addr:?}: {headers}"); const OK_RESPONSE: &[u8] = b"

Hello, world!

Hello from inferium.

"; const NOT_FOUND_RESPONSE: &[u8] = b"

Not found

This page was not found

"; // The URI can contain both path and parameters - so we're just getting the path here. Ok(match (headers.method(), headers.uri().path()) { // The ok response with our index page (&Method::GET, "/") => (ResponseHead::new( Status::Ok, ProtocolVariant::HTTP1_0, HashMap::from([ (HeaderKey::SERVER, "inferium".parse().unwrap()), (HeaderKey::CONTENT_LENGTH, OK_RESPONSE.len().into()), ]) ), OK_RESPONSE), // The not found response with an example not found page _ => (ResponseHead::new( Status::NotFound, ProtocolVariant::HTTP1_0, HashMap::from([ (HeaderKey::SERVER, "inferium".parse().unwrap()), (HeaderKey::CONTENT_LENGTH, NOT_FOUND_RESPONSE.len().into()), ]) ), NOT_FOUND_RESPONSE), }) } fn send_response( response: ResponseHead, body: &[u8], conn: &mut SyncServer )-> Result<(), ServerSendError> { conn.send_response(&response)?; // The send body can fail on an I/O error or if the content-length header does not match the // actual sent length in this scenario. But we know that we have the correct length so with // `.try_into().unwrap()` we tell inferium to convert the error and panic on (not so much) // possible body length discrepancy. conn.send_body_bytes(body).map_err(|e| e.try_into().unwrap()) }