simple-http: Add scaffolding for thread pool implementation
[learn-rust.git] / simple-http / src / bin / main.rs
1 use std::io::prelude::*;
2
3 use std::net::TcpListener;
4 use std::net::TcpStream;
5 use std::time::Duration;
6 use std::{fs, str, thread};
7
8 use simple_http::ThreadPool;
9
10 fn handle_connection(mut stream: TcpStream) {
11      let mut buffer = [0; 1024];
12
13     stream.read(&mut buffer).unwrap();
14
15     let buffer = match str::from_utf8(&buffer[..]) {
16         Ok(s) => s,
17         Err(e) => {
18             eprintln!("Invalid non-UTF8 request: {}\n{}", e, String::from_utf8_lossy(&buffer[..]));
19             return;
20         }
21     };
22     println!("Request: {}", buffer);
23
24     let path;
25
26     // simple web server, just interested in first line
27     if let Some(line) = buffer.lines().next() {
28         let request: Vec<_> = line.split_whitespace().collect();
29         if request.len() != 3 || request[0] != "GET" || request[2] != "HTTP/1.1" {
30             stream.write(b"HTTP/1.1 501 NOT IMPLEMENTED\r\n").unwrap();
31             stream.flush().unwrap();
32             return;
33         }
34
35         path = request[1];
36     } else {
37         eprintln!("Ignoring empty request: {}", buffer);
38         return;
39     }
40
41     let (code, file) = if path == "/" || path == "/index.html" {
42         ("200 OK", "index.html")
43     } else if path == "/slow" {
44         thread::sleep(Duration::from_secs(5));
45         ("200 OK", "index.html")
46     } else {
47         ("404 NOT FOUND", "404.html")
48     };
49
50     let text = fs::read_to_string(file).unwrap();
51
52     let response = format!(
53         "HTTP/1.1 {}\r\n\
54          Content-Type: text/html\r\n\
55          Content-Length: {}\r\n\r\n{}",
56         code,
57         text.len(),
58         text);
59
60     stream.write(response.as_bytes()).unwrap();
61     stream.flush().unwrap();
62 }
63
64 fn main() {
65     let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
66     let pool = ThreadPool::new(4);
67
68     for stream in listener.incoming() {
69         let stream = stream.unwrap();
70         pool.execute(|| handle_connection(stream));
71     }
72 }