♻️ Extract load_templates fn for file server

main
_ 2020-10-31 12:56:36 -05:00
parent bf48eb2dbd
commit 9244953e57
6 changed files with 39 additions and 63 deletions

View File

@ -18,6 +18,11 @@ use hyper::{
StatusCode, StatusCode,
}; };
use ptth::{
http_serde::RequestParts,
server::file_server,
};
struct ServerState <'a> { struct ServerState <'a> {
handlebars: Arc <handlebars::Handlebars <'a>>, handlebars: Arc <handlebars::Handlebars <'a>>,
} }
@ -41,11 +46,6 @@ fn prefix_match <'a> (hay: &'a str, needle: &str) -> Option <&'a str>
async fn handle_all (req: Request <Body>, state: Arc <ServerState <'static>>) async fn handle_all (req: Request <Body>, state: Arc <ServerState <'static>>)
-> Result <Response <Body>, Infallible> -> Result <Response <Body>, Infallible>
{ {
use ptth::{
http_serde::RequestParts,
server::file_server,
};
let path = req.uri ().path (); let path = req.uri ().path ();
//println! ("{}", path); //println! ("{}", path);
@ -90,16 +90,7 @@ async fn handle_all (req: Request <Body>, state: Arc <ServerState <'static>>)
async fn main () -> Result <(), Box <dyn Error>> { async fn main () -> Result <(), Box <dyn Error>> {
let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); let addr = SocketAddr::from(([0, 0, 0, 0], 4000));
let mut handlebars = handlebars::Handlebars::new (); let handlebars = Arc::new (file_server::load_templates ()?);
for (k, v) in vec! [
("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html"),
("file_server_dir", "ptth_handlebars/file_server_dir.html"),
].into_iter () {
handlebars.register_template_file (k, v)?;
}
let handlebars = Arc::new (handlebars);
let state = Arc::new (ServerState { let state = Arc::new (ServerState {
handlebars, handlebars,

View File

@ -44,7 +44,7 @@ mod tests {
spawn (async move { spawn (async move {
let opt = server::Opt { let opt = server::Opt {
relay_url: relay_url_2, relay_url: relay_url_2,
file_server_root: ".".into (), file_server_root: "./".into (),
}; };
server::main (opt).await.unwrap (); server::main (opt).await.unwrap ();
@ -57,7 +57,7 @@ mod tests {
assert_eq! (resp, "Relay is up\n"); assert_eq! (resp, "Relay is up\n");
let resp = client.get (&format! ("{}/http_request/alien_wildlands/COPYING", relay_url)) let resp = client.get (&format! ("{}/servers/alien_wildlands/COPYING", relay_url))
.send ().await.unwrap ().bytes ().await.unwrap (); .send ().await.unwrap ().bytes ().await.unwrap ();
assert_eq! (blake3::hash (&resp), blake3::Hash::from ([ assert_eq! (blake3::hash (&resp), blake3::Hash::from ([

View File

@ -32,7 +32,6 @@ use crate::{
use watcher::*; use watcher::*;
enum Message { enum Message {
Meow,
HttpRequestResponse (http_serde::WrappedRequest), HttpRequestResponse (http_serde::WrappedRequest),
HttpResponseResponseStream ((http_serde::ResponseParts, Body)), HttpResponseResponseStream ((http_serde::ResponseParts, Body)),
} }
@ -48,35 +47,13 @@ fn status_reply <B: Into <Body>> (status: StatusCode, b: B)
Response::builder ().status (status).body (b.into ()).unwrap () Response::builder ().status (status).body (b.into ()).unwrap ()
} }
async fn handle_watch (state: Arc <ServerState>, watcher_code: String)
-> Response <Body>
{
match Watchers::long_poll (state.watchers.clone (), watcher_code).await {
None => status_reply (StatusCode::OK, "no\n"),
Some (_) => status_reply (StatusCode::OK, "actually, yes\n"),
}
}
async fn handle_wake (state: Arc <ServerState>, watcher_code: String)
-> Response <Body>
{
let mut watchers = state.watchers.lock ().await;
if watchers.wake_one (Message::Meow, &watcher_code) {
status_reply (StatusCode::OK, "ok\n")
}
else {
status_reply (StatusCode::BAD_REQUEST, "no\n")
}
}
async fn handle_http_listen (state: Arc <ServerState>, watcher_code: String) async fn handle_http_listen (state: Arc <ServerState>, watcher_code: String)
-> Response <Body> -> Response <Body>
{ {
//println! ("Step 1"); //println! ("Step 1");
match Watchers::long_poll (state.watchers.clone (), watcher_code).await { match Watchers::long_poll (state.watchers.clone (), watcher_code).await {
Some (Message::HttpRequestResponse (parts)) => { Some (Message::HttpRequestResponse (parts)) => {
println! ("Step 3"); //println! ("Step 3");
status_reply (StatusCode::OK, rmp_serde::to_vec (&parts).unwrap ()) status_reply (StatusCode::OK, rmp_serde::to_vec (&parts).unwrap ())
}, },
_ => status_reply (StatusCode::GATEWAY_TIMEOUT, "no\n"), _ => status_reply (StatusCode::GATEWAY_TIMEOUT, "no\n"),
@ -90,21 +67,21 @@ async fn handle_http_response (
) )
-> Response <Body> -> Response <Body>
{ {
println! ("Step 6"); //println! ("Step 6");
let (parts, body) = req.into_parts (); let (parts, body) = req.into_parts ();
let resp_parts: http_serde::ResponseParts = rmp_serde::from_read_ref (&base64::decode (parts.headers.get (crate::PTTH_MAGIC_HEADER).unwrap ()).unwrap ()).unwrap (); let resp_parts: http_serde::ResponseParts = rmp_serde::from_read_ref (&base64::decode (parts.headers.get (crate::PTTH_MAGIC_HEADER).unwrap ()).unwrap ()).unwrap ();
{ {
let mut watchers = state.watchers.lock ().await; let mut watchers = state.watchers.lock ().await;
println! ("Step 7"); //println! ("Step 7");
if ! watchers.wake_one (Message::HttpResponseResponseStream ((resp_parts, body)), &req_id) if ! watchers.wake_one (Message::HttpResponseResponseStream ((resp_parts, body)), &req_id)
{ {
println! ("Step 8 (bad thing)"); println! ("Step 8 (bad thing)");
status_reply (StatusCode::BAD_REQUEST, "A bad thing happened.\n") status_reply (StatusCode::BAD_REQUEST, "A bad thing happened.\n")
} }
else { else {
println! ("Step 8"); //println! ("Step 8");
status_reply (StatusCode::OK, "ok\n") status_reply (StatusCode::OK, "ok\n")
} }
} }
@ -131,7 +108,7 @@ async fn handle_http_request (
} }
}; };
println! ("Step 2 {}", parts.id); //println! ("Step 2 {}", parts.id);
let (s, r) = oneshot::channel (); let (s, r) = oneshot::channel ();
let timeout = Duration::from_secs (5); let timeout = Duration::from_secs (5);
@ -148,7 +125,7 @@ async fn handle_http_request (
{ {
let mut watchers = state.watchers.lock ().await; let mut watchers = state.watchers.lock ().await;
println! ("Step 3"); //println! ("Step 3");
if ! watchers.wake_one (Message::HttpRequestResponse (parts), &watcher_code) { if ! watchers.wake_one (Message::HttpRequestResponse (parts), &watcher_code) {
watchers.remove_watcher (&req_id); watchers.remove_watcher (&req_id);
} }
@ -163,7 +140,7 @@ async fn handle_http_request (
match r.await { match r.await {
Ok (Message::HttpResponseResponseStream ((resp_parts, body))) => { Ok (Message::HttpResponseResponseStream ((resp_parts, body))) => {
println! ("Step 7"); //println! ("Step 7");
let mut resp = Response::builder () let mut resp = Response::builder ()
.status (hyper::StatusCode::from (resp_parts.status_code)); .status (hyper::StatusCode::from (resp_parts.status_code));
@ -200,7 +177,7 @@ async fn handle_all (req: Request <Body>, state: Arc <ServerState>)
// This is stuff the server can use. Clients can't // This is stuff the server can use. Clients can't
// POST right now // POST right now
return Ok (if let Some (request_code) = prefix_match (path, "/http_response/") { return Ok (if let Some (request_code) = prefix_match (path, "/7ZSFUKGV_http_response/") {
let request_code = request_code.into (); let request_code = request_code.into ();
handle_http_response (req, state, request_code).await handle_http_response (req, state, request_code).await
} }
@ -209,16 +186,10 @@ async fn handle_all (req: Request <Body>, state: Arc <ServerState>)
}); });
} }
if let Some (watch_code) = prefix_match (path, "/watch/") { if let Some (listen_code) = prefix_match (path, "/7ZSFUKGV_http_listen/") {
Ok (handle_watch (state, watch_code.into ()).await)
}
else if let Some (watch_code) = prefix_match (path, "/wake/") {
Ok (handle_wake (state, watch_code.into ()).await)
}
else if let Some (listen_code) = prefix_match (path, "/http_listen/") {
Ok (handle_http_listen (state, listen_code.into ()).await) Ok (handle_http_listen (state, listen_code.into ()).await)
} }
else if let Some (rest) = prefix_match (path, "/http_request/") { else if let Some (rest) = prefix_match (path, "/servers/") {
if let Some (idx) = rest.find ('/') { if let Some (idx) = rest.find ('/') {
let listen_code = String::from (&rest [0..idx]); let listen_code = String::from (&rest [0..idx]);
let path = String::from (&rest [idx..]); let path = String::from (&rest [idx..]);

View File

@ -3,6 +3,7 @@
use std::{ use std::{
cmp::{min, max}, cmp::{min, max},
convert::{Infallible, TryInto}, convert::{Infallible, TryInto},
error::Error,
io::SeekFrom, io::SeekFrom,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
@ -283,6 +284,21 @@ pub async fn serve_all (
} }
} }
pub fn load_templates ()
-> Result <handlebars::Handlebars <'static>, Box <dyn Error>>
{
let mut handlebars = handlebars::Handlebars::new ();
for (k, v) in vec! [
("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html"),
("file_server_dir", "ptth_handlebars/file_server_dir.html"),
].into_iter () {
handlebars.register_template_file (k, v)?;
}
Ok (handlebars)
}
#[cfg (test)] #[cfg (test)]
mod tests { mod tests {
#[test] #[test]

View File

@ -45,7 +45,7 @@ async fn handle_req_resp <'a> (
let response = file_server::serve_all (handlebars, &opt.file_server_root, parts).await; let response = file_server::serve_all (handlebars, &opt.file_server_root, parts).await;
let mut resp_req = client let mut resp_req = client
.post (&format! ("{}/http_response/{}", opt.relay_url, req_id)) .post (&format! ("{}/7ZSFUKGV_http_response/{}", opt.relay_url, req_id))
.header (crate::PTTH_MAGIC_HEADER, base64::encode (rmp_serde::to_vec (&response.parts).unwrap ())); .header (crate::PTTH_MAGIC_HEADER, base64::encode (rmp_serde::to_vec (&response.parts).unwrap ()));
if let Some (body) = response.body { if let Some (body) = response.body {
@ -67,11 +67,7 @@ pub async fn main (opt: Opt) -> Result <(), Box <dyn Error>> {
let client = Arc::new (Client::new ()); let client = Arc::new (Client::new ());
let opt = Arc::new (opt); let opt = Arc::new (opt);
let mut handlebars = handlebars::Handlebars::new (); let handlebars = Arc::new (file_server::load_templates ()?);
handlebars.register_template_file ("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html")?;
let handlebars = Arc::new (handlebars);
let mut backoff_delay = 0; let mut backoff_delay = 0;
@ -80,7 +76,7 @@ pub async fn main (opt: Opt) -> Result <(), Box <dyn Error>> {
delay_for (Duration::from_millis (backoff_delay)).await; delay_for (Duration::from_millis (backoff_delay)).await;
} }
let req_req = client.get (&format! ("{}/http_listen/{}", opt.relay_url, SERVER_NAME)); let req_req = client.get (&format! ("{}/7ZSFUKGV_http_listen/{}", opt.relay_url, SERVER_NAME));
let req_resp = match req_req.send ().await { let req_resp = match req_req.send ().await {
Err (e) => { Err (e) => {

View File

@ -8,3 +8,5 @@ impersonate servers
- Prevent directory traversal attacks - Prevent directory traversal attacks
- Fix possible timing gap when refreshing http_listen (Just have client wait a few seconds?) - Fix possible timing gap when refreshing http_listen (Just have client wait a few seconds?)
- Error handling - Error handling
- Reverse proxy to other local servers