♻️ Make the server's inner handlers look more like a regular Hyper server

main
_ 2020-10-30 17:11:35 -05:00
parent 1615f0d075
commit 325f68b566
2 changed files with 42 additions and 54 deletions

View File

@ -1,6 +1,5 @@
use std::{
cmp::{min, max},
collections::*,
convert::{Infallible, TryInto},
error::Error,
io::SeekFrom,
@ -88,10 +87,7 @@ impl <'a> ResponseHandle <'a> {
}
}
async fn serve_dir (
response_handle: ResponseHandle <'_>,
mut dir: ReadDir
) {
async fn serve_dir (mut dir: ReadDir) -> http_serde::Response {
let (tx, rx) = channel (2);
tokio::spawn (async move {
@ -142,25 +138,20 @@ async fn serve_dir (
tx.send (Ok::<_, Infallible> (String::from ("</ul>").into_bytes ())).await.unwrap ();
});
let mut headers: HashMap <String, Vec <u8>> = Default::default ();
let mut response = http_serde::Response::default ();
headers.insert ("content-type".into (), String::from ("text/html").into_bytes ());
response.header ("content-type".into (), String::from ("text/html").into_bytes ());
response.body (Body::wrap_stream (rx));
let resp_parts = http_serde::ResponseParts {
status_code: http_serde::StatusCode::Ok,
headers,
};
response_handle.respond (resp_parts, Some (Body::wrap_stream (rx))).await;
response
}
async fn serve_file (
response_handle: ResponseHandle <'_>,
mut f: File,
should_send_body: bool,
range_start: Option <u64>,
range_end: Option <u64>
) {
) -> http_serde::Response {
let (tx, rx) = channel (2);
let body = if should_send_body {
Some (Body::wrap_stream (rx))
@ -219,40 +210,38 @@ async fn serve_file (
});
}
let mut headers: HashMap <String, Vec <u8>> = Default::default ();
headers.insert (String::from ("accept-ranges"), b"bytes".to_vec ());
let mut response = http_serde::Response::default ();
let status_code;
response.header (String::from ("accept-ranges"), b"bytes".to_vec ());
if range_start.is_none () && range_end.is_none () {
headers.insert (String::from ("content-length"), end.to_string ().into_bytes ());
status_code = http_serde::StatusCode::Ok;
response.status_code (http_serde::StatusCode::Ok);
response.header (String::from ("content-length"), end.to_string ().into_bytes ());
}
else {
headers.insert (String::from ("content-range"), format! ("bytes {}-{}/{}", start, end - 1, end).into_bytes ());
status_code = http_serde::StatusCode::PartialContent;
response.status_code (http_serde::StatusCode::PartialContent);
response.header (String::from ("content-range"), format! ("bytes {}-{}/{}", start, end - 1, end).into_bytes ());
}
let resp_parts = http_serde::ResponseParts {
status_code,
headers,
};
if let Some (body) = body {
response.body (body);
}
response_handle.respond (resp_parts, body).await;
response
}
async fn serve_error (
response_handle: ResponseHandle <'_>,
status_code: http_serde::StatusCode
) {
let headers: HashMap <String, Vec <u8>> = Default::default ();
status_code: http_serde::StatusCode,
msg: String
)
-> http_serde::Response
{
let mut response = http_serde::Response::default ();
let resp_parts = http_serde::ResponseParts {
status_code,
headers,
};
response.status_code (status_code);
response.body (msg.into ());
response_handle.respond (resp_parts, Some ("404 Not Found".into ())).await;
response
}
async fn handle_all (
@ -307,29 +296,27 @@ async fn handle_all (
let mut full_path = PathBuf::from ("/home/user");
full_path.push (&*path);
let response = if let Ok (dir) = read_dir (&full_path).await {
serve_dir (dir).await
}
else if let Ok (file) = File::open (&full_path).await {
serve_file (
file,
should_send_body,
range_start,
range_end
).await
}
else {
serve_error (http_serde::StatusCode::NotFound, "404 Not Found".into ()).await
};
let response_handle = ResponseHandle {
client,
req_id: &req_id,
};
if let Ok (dir) = read_dir (&full_path).await {
serve_dir (response_handle, dir).await;
}
else if let Ok (file) = File::open (&full_path).await {
serve_file (
response_handle,
file,
should_send_body,
range_start,
range_end
).await;
}
else {
serve_error (
response_handle,
http_serde::StatusCode::NotFound
).await;
}
response_handle.respond_2 (response).await;
Ok (())
}

View File

@ -1,3 +1,4 @@
- Add ".." for parent directory
- Set up tokens or something so clients can't trivially
impersonate servers
- Offer list of clients at server root