From bbd9be32e463dcae05fc20267b30a2ed048d025a Mon Sep 17 00:00:00 2001 From: Alberto Ruiz <17555470+Az107@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:07:33 +0200 Subject: [PATCH 1/2] initial solution proposal --- hteapot.toml | 2 +- src/brew.rs | 9 ++++++--- src/main.rs | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/hteapot.toml b/hteapot.toml index 73549a3..7c6189a 100644 --- a/hteapot.toml +++ b/hteapot.toml @@ -6,5 +6,5 @@ threads = 5 cache = true cache_ttl = 3600 [proxy] -"/test" = "https://example.com" +"/test" = "http://example.com" "/google" = "http://google.com" \ No newline at end of file diff --git a/src/brew.rs b/src/brew.rs index 486bfb7..1999d62 100644 --- a/src/brew.rs +++ b/src/brew.rs @@ -3,10 +3,11 @@ use std::{io::{Read, Write}, net::TcpStream}; - +#[derive(Debug)] struct Url { scheme: String, domain: String, + path: String, port: String } @@ -14,7 +15,7 @@ struct Url { fn parse_url(url: &str) -> Result { let url_parts = url.split(":").collect::>(); let prefix = url_parts[0]; - let domain = url_parts[1].trim_start_matches("//"); + let domain_path = url_parts[1].trim_start_matches("//"); let port = if url_parts.len() == 3 { url_parts[2] } else { @@ -24,9 +25,11 @@ fn parse_url(url: &str) -> Result { _ => "80" } }; + let (domain,path) = domain_path.split_once('/').unwrap(); Ok(Url { scheme: prefix.to_string(), domain: domain.to_string(), + path: path.to_string(), port: port.to_string() }) } @@ -43,7 +46,7 @@ pub fn fetch(url: &str) -> Result { return Err("Error fetching"); } let mut client = client.unwrap(); - let http_request = format!("GET / HTTP/1.1\r\nHost: {}\r\n\r\n", url.domain); + let http_request = format!("GET /{} HTTP/1.1\r\nHost: {}\r\n\r\n",url.path, url.domain); client.write(http_request.as_bytes()).unwrap(); let mut response = String::new(); let mut buffer = [0; 1024]; diff --git a/src/main.rs b/src/main.rs index d2775f6..7ca37ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,10 +42,19 @@ fn main() { } else { req.path.clone() }; - if config.proxy_rules.contains_key(&req.path) { - logger.lock().expect("this doesnt work :C").msg(format!("Proxying to: {}", config.proxy_rules.get(&req.path).unwrap())); - let url = config.proxy_rules.get(&req.path).unwrap(); - return match fetch(url) { + let path_clone = req.path.clone(); + let divided_path: Vec<&str> = path_clone.split('/').skip(1).collect(); + if divided_path.is_empty() { + return Hteapot::response_maker(HttpStatus::BadRequest, b"Invalid path", None); + } + + let first_one = format!("/{}",divided_path[0]); + let rest_path = divided_path[1..].join("/"); + if config.proxy_rules.contains_key(&first_one) { + let url = config.proxy_rules.get(&first_one).unwrap(); + let url = format!("{}/{}",url,rest_path); + logger.lock().expect("this doesnt work :C").msg(format!("Proxying to: {}", url)); + return match fetch(&url) { Ok(response) => { response.into() }, From 4cdd98eefbafedc316bb5c28d4f1e630af68fe79 Mon Sep 17 00:00:00 2001 From: Alberto Ruiz <17555470+Az107@users.noreply.github.com> Date: Sun, 4 Aug 2024 23:05:11 +0200 Subject: [PATCH 2/2] Fixed --- hteapot.toml | 5 +++-- src/brew.rs | 16 +++++++++------- src/main.rs | 24 ++++++++++++++++++++---- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/hteapot.toml b/hteapot.toml index 7c6189a..2da0d86 100644 --- a/hteapot.toml +++ b/hteapot.toml @@ -1,10 +1,11 @@ [HTEAPOT] port = 8081 -host = "0.0.0.0" #test de comentario +host = "0.0.0.0" root = "public" threads = 5 cache = true cache_ttl = 3600 [proxy] "/test" = "http://example.com" -"/google" = "http://google.com" \ No newline at end of file +"/google" = "http://google.com" +# "/" = "http://ifconfig.co" # this will override all the proxys and local request \ No newline at end of file diff --git a/src/brew.rs b/src/brew.rs index 1999d62..f5f7e0f 100644 --- a/src/brew.rs +++ b/src/brew.rs @@ -1,9 +1,9 @@ // Written by Alberto Ruiz 2024-04-08 // This is the HTTP client module, it will handle the requests and responses -use std::{io::{Read, Write}, net::TcpStream}; +use std::{io::{Read, Write}, net::TcpStream, vec}; + -#[derive(Debug)] struct Url { scheme: String, domain: String, @@ -34,13 +34,14 @@ fn parse_url(url: &str) -> Result { }) } -pub fn fetch(url: &str) -> Result { +pub fn fetch(url: &str) -> Result,&str> { let url = parse_url(url); if url.is_err() { return Err("Error parsing url")} let url = url.unwrap(); if url.scheme == "https" { return Err("not supported yet"); } + let client = TcpStream::connect(format!("{}:{}",url.domain,url.port)); if client.is_err() { return Err("Error fetching"); @@ -49,19 +50,20 @@ pub fn fetch(url: &str) -> Result { let http_request = format!("GET /{} HTTP/1.1\r\nHost: {}\r\n\r\n",url.path, url.domain); client.write(http_request.as_bytes()).unwrap(); let mut response = String::new(); + let mut full_buffer: Vec = Vec::new(); let mut buffer = [0; 1024]; loop { match client.read(&mut buffer) { Ok(0) => break, Ok(n) => { - response.push_str(std::str::from_utf8(&buffer[..n]).unwrap()); - if response.ends_with("\n") {break} //TODO: break when size == header - + if n == 0 {break;} + full_buffer.extend(buffer.iter().cloned()); + if buffer.last().unwrap() == &0 {break;} }, Err(_) => break } } - Ok(response) + Ok(full_buffer) } diff --git a/src/main.rs b/src/main.rs index 7ca37ea..98cf005 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ fn main() { } else { config::Config::new_default() }; + let proxy_only = config.proxy_rules.get("/").is_some(); let logger = Mutex::new(Logger::new(io::stdout())); let cache: Mutex, u64)>> = Mutex::new(HashMap::new()); let server = Hteapot::new_threaded(config.host.as_str(), config.port,config.threads); @@ -31,6 +32,10 @@ fn main() { if config.cache { logger.lock().expect("this doesnt work :C").msg("Cache Enabled".to_string()); } + if proxy_only { + logger.lock().expect("this doesnt work :C").msg("WARNING: All requests are proxied to /. Local paths won’t be used.".to_string()); + } + server.listen( move |req| { //let mut logger = Logger::new(io::stdout()); @@ -50,13 +55,24 @@ fn main() { let first_one = format!("/{}",divided_path[0]); let rest_path = divided_path[1..].join("/"); - if config.proxy_rules.contains_key(&first_one) { - let url = config.proxy_rules.get(&first_one).unwrap(); - let url = format!("{}/{}",url,rest_path); + + if proxy_only || config.proxy_rules.contains_key(&first_one) { + let url = if proxy_only { + let url = config.proxy_rules.get("/").unwrap(); + if rest_path.len() != 0 { + format!("{}{}/{}",url,first_one,rest_path) + + } else { + format!("{}{}",url,first_one) + } + } else { + let url = config.proxy_rules.get(&first_one).unwrap(); + format!("{}/{}",url,rest_path) + }; logger.lock().expect("this doesnt work :C").msg(format!("Proxying to: {}", url)); return match fetch(&url) { Ok(response) => { - response.into() + response }, Err(err) => { Hteapot::response_maker(HttpStatus::InternalServerError, err.as_bytes(), None)