1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::{io, net, time::Instant};
mod cfg;
pub use cfg::Config;
mod http;
use http::*;
#[derive(Debug)]
pub enum HttpservFail {
Io(io::Error),
Request(ReqFail),
}
impl From<io::Error> for HttpservFail {
fn from(ioe: io::Error) -> Self {
Self::Io(ioe)
}
}
impl From<ReqFail> for HttpservFail {
fn from(rf: ReqFail) -> Self {
Self::Request(rf)
}
}
type Result<T> = std::result::Result<T, HttpservFail>;
pub struct Httpserv {
cfg: Config,
listener: net::TcpListener,
}
impl Httpserv {
pub fn new(cfg: Config) -> Result<Httpserv> {
let listener = net::TcpListener::bind(&cfg.hostname)?;
Ok(Httpserv { cfg, listener })
}
pub fn config(&self) -> &Config {
&self.cfg
}
fn respond_one(&self, conn: io::Result<net::TcpStream>) -> Result<()> {
let begin = Instant::now();
let mut conn = match conn {
Ok(s) => s,
Err(e) => return Err(e.into()),
};
let request = http::Request::load(&mut conn)?;
if self.cfg.log {
print!("Serving /{}", request.path)
}
let response = http::Response::to(request, &self.cfg)?;
if self.cfg.log {
print!(" with {}", response.code());
}
response.write(conn)?;
if self.cfg.log {
println!(" in {}us", (Instant::now() - begin).as_micros());
}
Ok(())
}
pub fn run(&mut self) {
for conn in self.listener.incoming() {
let _ = self.respond_one(conn);
}
}
pub fn run_to_fail(&mut self) -> Result<()> {
for conn in self.listener.incoming() {
self.respond_one(conn)?;
}
Ok(())
}
}