From 1e0fd059699b2aeda9cd48127b78f7bd1e099756 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 26 Nov 2021 22:36:24 +0100 Subject: [PATCH] Added better uri parsing (inspired by FileServer) --- src/proxy.rs | 58 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/proxy.rs b/src/proxy.rs index c70443e..bfcb0e0 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -6,6 +6,8 @@ use reqwest::{ Method as ReqMethod, }; use rocket::{ + http::uri::Segments, + fs::Options, data::ToByteUnit, http::{Method, Status}, route::{Handler, Outcome}, @@ -19,24 +21,26 @@ pub struct ProxyServer root: String, prefix: PathBuf, rank: isize, + options: Options, } impl ProxyServer { const DEFAULT_RANK: isize = 0; - pub fn new>(root: &str, prefix: P, rank: isize) -> Self + pub fn new>(root: &str, prefix: P, rank: isize, options: Options) -> Self { ProxyServer { root: String::from(root), prefix: prefix.as_ref().into(), rank, + options, } } pub fn from>(root: &str, prefix: P) -> Self { - Self::new(root, prefix, Self::DEFAULT_RANK) + Self::new(root, prefix, Self::DEFAULT_RANK, Options::NormalizeDirs) } } @@ -78,7 +82,37 @@ impl Handler for ProxyServer { async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r> { + use rocket::http::uri::fmt::Path; + // ROCKET REQUEST -> REQWEST REQUEST + // Path + let allow_dotfiles = self.options.contains(Options::DotFiles); + let path = req.segments::>(0..).ok() + .and_then(|segments| segments.to_path_buf(allow_dotfiles).ok()) + .map(|path| self.prefix.join(path)); + + if path.is_none() { + return Outcome::Failure(Status::BadRequest); + } + + let path_val = path.unwrap(); + let path_str = path_val.to_str(); // Unwrap is safe because we check for is_none() beforehand + + if path_str.is_none() { + return Outcome::Failure(Status::BadRequest); + } + + let query_part = req + .uri() + .query() + .map_or(String::from(""), |s| format!("?{}", s)); + + let url = format!( + "{}{}{}", + self.root, + path_str.unwrap(), // Unwrap is safe because we check for is_none() beforehand + query_part + ); // Headers let mut headers = HeaderMap::new(); @@ -106,26 +140,6 @@ impl Handler for ProxyServer _ => todo!(), }; - // URL - // We first extract all URL segments starting from the mountpoint - let segments: PathBuf = match req.segments(0..) { - Ok(val) => val, - Err(_) => return Outcome::Failure(Status::InternalServerError), - }; - - let query_part = req - .uri() - .query() - .map_or(String::from(""), |s| format!("?{}", s)); - - let url = format!( - "{}{}/{}{}", - self.root, - self.prefix.to_str().unwrap_or(""), - segments.to_str().unwrap_or(""), - query_part - ); - // And finally, the data // TODO don't hard-code max request size here static BODY_SIZE: i64 = 2;