clone-shim/examples/tls/http.rs
Jake Hillion 29fec1466e
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
http input reading correction
2022-05-24 12:48:29 +01:00

86 lines
2.1 KiB
Rust

use std::fs::OpenOptions;
use std::io::{self, ErrorKind, Read, Write};
use std::os::unix::net::UnixStream;
use std::path::PathBuf;
pub(super) fn handler(mut stream: UnixStream) -> i32 {
println!("entered http handler");
let mut buf = Vec::new();
let mut buf_len = 0;
loop {
buf.resize_with(buf_len + 4096, Default::default);
let read_bytes = stream.read(&mut buf[buf_len..]).unwrap();
buf_len += read_bytes;
if read_bytes == 0 {
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
};
if let Some(filename) = filename {
if try_serve_file(&mut stream, filename).unwrap() {
return exitcode::OK;
}
}
let status_line = "HTTP/1.1 404 NOT FOUND";
let contents = "file not found\n";
let response = format!(
"{}\r\nContent-Length: {}\r\n\r\n{}",
status_line,
contents.len(),
contents
);
stream.write_all(response.as_bytes()).unwrap();
break;
}
exitcode::OK
}
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)
}