diff options
Diffstat (limited to 'corgi/src')
-rw-r--r-- | corgi/src/main.rs | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/corgi/src/main.rs b/corgi/src/main.rs index b8b23de..ba7195b 100644 --- a/corgi/src/main.rs +++ b/corgi/src/main.rs @@ -147,8 +147,8 @@ impl Svc { // Collect things we need from the request before we eat it's body let method = req.method().as_str().to_ascii_uppercase(); let version = req.version(); - let path = req.uri().path().to_owned(); - let query = req.uri().query().unwrap_or_default().to_owned(); + let path = url_decode(req.uri().path().to_owned(), false).unwrap(); + let query = url_decode(req.uri().query().unwrap_or_default().to_owned(), false).unwrap(); let headers = req.headers().clone(); let body = req.into_body().collect().await.unwrap().to_bytes().to_vec(); @@ -280,3 +280,48 @@ impl Svc { ret } } + +// Ripped and modified from gennyble/mavourings query.rs +fn url_decode<S: AsRef<str>>(urlencoded: S, plus_as_space: bool) -> Option<String> { + let urlencoded = urlencoded.as_ref(); + let mut uncoded: Vec<u8> = Vec::with_capacity(urlencoded.len()); + + let mut chars = urlencoded.chars().peekable(); + loop { + let mut utf8_bytes = [0; 4]; + match chars.next() { + Some('+') => match plus_as_space { + true => uncoded.push(b' '), + false => uncoded.push(b'+'), + }, + Some('%') => match chars.peek() { + Some(c) if c.is_ascii_hexdigit() => { + let upper = chars.next().unwrap(); + + if let Some(lower) = chars.peek() { + if lower.is_ascii_hexdigit() { + let upper = upper.to_digit(16).unwrap(); + let lower = chars.next().unwrap().to_digit(16).unwrap(); + + uncoded.push(upper as u8 * 16 + lower as u8); + continue; + } + } + + uncoded.push(b'%'); + uncoded.extend_from_slice(upper.encode_utf8(&mut utf8_bytes).as_bytes()); + } + _ => { + uncoded.push(b'%'); + } + }, + Some(c) => { + uncoded.extend_from_slice(c.encode_utf8(&mut utf8_bytes).as_bytes()); + } + None => { + uncoded.shrink_to_fit(); + return String::from_utf8(uncoded).ok(); + } + } + } +} |