diff --git a/Cargo.lock b/Cargo.lock index d9e651e..16e0f71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1362,6 +1362,7 @@ dependencies = [ "clap", "futures-core", "linked-hash-map", + "percent-encoding", "reqwest", "rust_util", "serde", diff --git a/Cargo.toml b/Cargo.toml index 8f956a0..22b5b16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ actix-rt = "1" bytes = "0.5" futures-core = "0.3" linked-hash-map = "0.5" +percent-encoding = "2.1" diff --git a/src/main.rs b/src/main.rs index 0c73e4b..ad700b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,11 +36,22 @@ impl futures_core::Stream for ProxyStream { } async fn get_file(req: HttpRequest) -> HttpResponse { - println!("{:?}", req); let query_string = req.query_string(); - println!("Q: {}", query_string); - // TODO parse url - let resp = reqwest::get("http://example.com/").await.unwrap(); + let parsed_query_string = parse_query_string(query_string); + information!("Parsed query string: {:?}", parsed_query_string); + + let url = match parsed_query_string.get("url") { + None => None, + Some(v) => v.iter().next().clone(), + }; + let url = match url { + Some(u) => u, None => { + return HttpResponse::BadRequest().content_type("text/plain").body("No url!"); + }, + }; + + let resp = reqwest::get(url.as_str()).await.unwrap(); + // TODO ... HttpResponse::Ok() .content_type("text/plain") .streaming(ProxyStream{ inner: Box::new(resp.bytes_stream()) }) @@ -71,7 +82,38 @@ async fn main() -> std::io::Result<()> { } fn parse_query_string(query_string: &str) -> LinkedHashMap> { - let map = LinkedHashMap::new(); - // TODO ... + let mut map = LinkedHashMap::new(); + query_string.split('&').for_each(|kv| { + let mut meet_equal = false; + let mut k = String::new(); + let mut v = String::new(); + kv.chars().for_each(|c| { + if meet_equal { + v.push(c); + } else if c == '=' { + meet_equal = true; + } else { + k.push(c); + } + }); + let k = percent_encoding::percent_decode_str(&k).decode_utf8_lossy().into_owned(); + let v = percent_encoding::percent_decode_str(&v).decode_utf8_lossy().into_owned(); + match map.get_mut(&k) { + None => { map.insert(k, vec![v]); }, + Some(values) => { values.push(v); }, + } + }); map } + +#[test] +fn test_parse_query_string() { + let mut e = LinkedHashMap::new(); + e.insert("a".to_string(), vec!["b".to_string()]); + let m = parse_query_string("a=b"); + assert_eq!(e, m); + let mut e = LinkedHashMap::new(); + e.insert("a".to_string(), vec!["b".to_string(), "c".to_string()]); + let m = parse_query_string("a=b&a=c"); + assert_eq!(e, m); +}