Commit c0cdb29e authored by Chris's avatar Chris
Browse files

[single-threaded-web-server] created a functioning single-threaded web server

parent d0739a91
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4

[[package]]
name = "single-threaded-web-server"
version = "0.1.0"
+6 −0
Original line number Diff line number Diff line
[package]
name = "single-threaded-web-server"
version = "0.1.0"
edition = "2024"

[dependencies]
+58 −0
Original line number Diff line number Diff line
use std::{
    fs,
    io::{BufReader, prelude::*},
    net::{TcpListener, TcpStream},
};
use std::process::exit;

fn main() {
    println!("[single-threaded-web-service] application started");

    let listener = TcpListener::bind("127.0.0.1:7878").unwrap_or_else(|error| {
        eprintln!("error when binding to port 7878: {}", error);
        exit(1);
    });

    for stream in listener.incoming() {
        let stream = stream.unwrap_or_else(|error| {
            eprintln!("error when calling stream.unwrap_or_else(): {}", error);
            exit(1);
        });

        println!("[single-threaded-web-service] connection established");
        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    let buf_reader = BufReader::new(&stream);

    // note: the book suggests only reading the request line, but I want to be able to log the whole request
    let http_request: Vec<_> = buf_reader
        .lines()
        .map(|result| result.unwrap())
        .take_while(|line| !line.is_empty())
        .collect();
    println!("Received request: {http_request:#?}");
    let request_verb_type_version = http_request.get(0).unwrap();

    let (status_line, html_file_name) = if request_verb_type_version == "GET / HTTP/1.1" {
        ("HTTP/1.1 200 OK", "hello.html")
    } else {
        ("HTTP/1.1 404 NOT FOUND", "404.html")
    };

    let response_body = fs::read_to_string(html_file_name).unwrap_or_else(|error| {
        eprintln!("error when reading {}: {}", html_file_name, error);
        exit(1);
    });
    let response_body_length = response_body.len();

    let response =
        format!("{}\r\nContent-Length:{}\r\n\r\n{}",
                status_line,
                response_body_length,
                response_body);
    println!("response is {response}");
    stream.write_all(response.as_bytes()).unwrap();
}