clone-shim/examples/tls/http.rs

86 lines
2.1 KiB
Rust
Raw Permalink Normal View History

2022-05-24 12:47:20 +01:00
use std::fs::OpenOptions;
use std::io::{self, ErrorKind, Read, Write};
2022-05-23 18:26:55 +01:00
use std::os::unix::net::UnixStream;
2022-05-21 17:18:28 +01:00
use std::path::PathBuf;
2022-05-23 18:26:55 +01:00
pub(super) fn handler(mut stream: UnixStream) -> i32 {
2022-05-21 17:18:28 +01:00
println!("entered http handler");
let mut buf = Vec::new();
2022-05-24 12:48:29 +01:00
let mut buf_len = 0;
2022-05-21 17:18:28 +01:00
loop {
2022-05-24 12:48:29 +01:00
buf.resize_with(buf_len + 4096, Default::default);
let read_bytes = stream.read(&mut buf[buf_len..]).unwrap();
buf_len += read_bytes;
2022-05-21 17:18:28 +01:00
2022-05-24 12:48:29 +01:00
if read_bytes == 0 {
2022-05-21 17:18:28 +01:00
break;
}
let mut headers = [httparse::EMPTY_HEADER; 64];
let mut req = httparse::Request::new(&mut headers);
let result = req.parse(&buf).unwrap();
if result.is_partial() {
continue;
}
let filename = if req.method != Some("GET") {
None
} else {
req.path
};
2022-05-24 12:47:20 +01:00
if let Some(filename) = filename {
if try_serve_file(&mut stream, filename).unwrap() {
return exitcode::OK;
}
}
2022-05-21 17:18:28 +01:00
2022-05-24 12:47:20 +01:00
let status_line = "HTTP/1.1 404 NOT FOUND";
let contents = "file not found\n";
2022-05-21 17:18:28 +01:00
2022-05-24 12:47:20 +01:00
let response = format!(
"{}\r\nContent-Length: {}\r\n\r\n{}",
2022-05-21 17:18:28 +01:00
status_line,
contents.len(),
2022-05-24 12:47:20 +01:00
contents
2022-05-21 17:18:28 +01:00
);
2022-05-24 12:47:20 +01:00
stream.write_all(response.as_bytes()).unwrap();
2022-05-21 17:18:28 +01:00
break;
}
exitcode::OK
}
2022-05-24 12:47:20 +01:00
fn try_serve_file(stream: &mut impl io::Write, filename: &str) -> io::Result<bool> {
let mut fd = match OpenOptions::new()
.read(true)
.open(PathBuf::from("/var/www/html/").join(filename.strip_prefix('/').unwrap_or(filename)))
{
Ok(fd) => fd,
Err(e) => {
if e.kind() == ErrorKind::NotFound {
return Ok(false);
}
return Err(e);
}
};
let status_line = "HTTP/1.1 200 OK";
let response_header = format!(
"{}\r\nContent-Length: {}\r\n\r\n",
status_line,
fd.metadata()?.len(),
);
stream.write_all(response_header.as_bytes())?;
io::copy(&mut fd, stream)?;
Ok(true)
}