httplz/crates/uhttp/examples/echo.rs
2024-10-14 15:04:36 -04:00

83 lines
2 KiB
Rust

//! A simple echo server that listens on 127.0.0.1:8089
use std::{error::Error, io::Write, net::TcpListener};
use uhttp::Lift;
fn main() -> Result<(), Box<dyn Error>> {
let listener = TcpListener::bind("127.0.0.1:8089")?;
loop {
let (mut stream, _) = listener.accept()?;
let mut conn = uhttp::Connection::new(uhttp::Role::Server);
let mut body: Vec<u8> = Vec::new();
let mut buf = vec![0; 1024].into_boxed_slice();
let mut buf = uhttp_ext::Buf::new(&mut buf);
let mut method_not_allowed = false;
loop {
let data = buf.filled();
let (remaining, r) = conn.handle_recv(data).lift();
match r.map_err(|e| e.kind) {
Err(uhttp::ErrorKind::NeedMoreData) => {
buf.read_from(&mut stream)?;
continue;
},
Err(e) => panic!("{e:?}"),
Ok(event) => {
match event {
uhttp::Event::RequestLine(r) => {
if !r.method.eq_ignore_ascii_case("post") {
method_not_allowed = true;
}
},
uhttp::Event::RecvDone => break,
uhttp::Event::BodyChunk(b) => body.extend_from_slice(b),
_ => (),
};
},
};
let len = data.len() - remaining.len();
buf.pop_front(len);
}
let parts: &[uhttp::Event] = if method_not_allowed {
&[
uhttp::Event::StatusLine(uhttp::StatusLine {
version: uhttp::Version::HTTP1_1,
status_code: 405,
status_text: "Method not allowed",
}),
uhttp::Event::HeadersEnd,
uhttp::Event::SendDone,
]
} else {
&[
uhttp::Event::StatusLine(uhttp::StatusLine {
version: uhttp::Version::HTTP1_1,
status_code: 200,
status_text: "OK",
}),
uhttp::Event::Header(uhttp::Header::Special(
uhttp::HeaderSpecial::ContentLength(body.len()),
)),
uhttp::Event::HeadersEnd,
uhttp::Event::BodyChunk(body.as_slice()),
uhttp::Event::SendDone,
]
};
let buf = vec![0; 1024];
let mut cursor = uhttp::WriteCursor::new(buf);
for p in parts {
if let Err(e) = conn.handle_send(p, &mut cursor) {
panic!("{e:?}")
};
stream.write_all(cursor.written())?;
cursor.reset();
}
}
}