Parsing and Routing

A Request struct, header parsing, and a match-based router.

Part 2 of 3Updated
struct Request {
    method: String,
    path: String,
    headers: Vec<(String, String)>,
}

fn route(req: &Request) -> (u16, &'static str) {
    match (req.method.as_str(), req.path.as_str()) {
        ("GET", "/") => (200, "home"),
        ("GET", "/health") => (200, "ok"),
        ("GET", _) => (404, "not found"),
        _ => (405, "method not allowed"),
    }
}

Matching on a tuple of method and path is the cleanest router you can write without a crate.

Two things to get right: header names are case-insensitive, and you must not read past the blank line unless Content-Length says there’s a body — otherwise you’ll block forever waiting for bytes that aren’t coming.