1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
extern crate iron; extern crate url; use std::io::Read; use std::sync::Arc; use iron::prelude::*; use std::collections::HashMap; use std::collections::hash_map::Entry::*; use url::form_urlencoded; use std::str::FromStr; pub trait RequestExt { fn params<'c, 'd>(&'c self, name: &'d str) -> Option<&'c Vec<String>>; fn param<'c, 'd, F: FromStr>(&'c self, name: &'d str) -> Option<F>; fn body<'c, 'd>(&'c self) -> Option<&'c String>; } impl<'a, 'b> RequestExt for Request<'a, 'b> { fn params<'c, 'd>(&'c self, name: &'d str) -> Option<&'c Vec<String>> { if let Some(map) = self.extensions.get::<Params>() { return map.get(name); } None } fn param<'c, 'd, F: FromStr>(&'c self, name: &'d str) -> Option<F> { match self.params(name) { Some(vec) if vec.len() > 0 => vec[0].clone().parse().ok(), _ => None, } } fn body<'c, 'd>(&'c self) -> Option<&'c String> { use std::borrow::Borrow; self.extensions.get::<Body>().map(|v| v.borrow()) } } pub struct Params; impl iron::typemap::Key for Params { type Value = Arc<HashMap<String, Vec<String>>>; } pub struct Body; impl iron::typemap::Key for Body { type Value = Arc<String>; } impl iron::BeforeMiddleware for Params { fn before(&self, req: &mut Request) -> IronResult<()> { let (body, map) = combine(req); req.extensions.insert::<Params>(Arc::new(map)); req.extensions.insert::<Body>(Arc::new(body)); Ok(()) } } fn combine(req: &mut Request) -> (String, HashMap<String, Vec<String>>) { let mut map = HashMap::<String, Vec<String>>::new(); let url = req.url.clone(); let query = url.query(); if let Some(query) = query { combine_duplicates(form_urlencoded::parse(&String::from(query).into_bytes()), &mut map); } let mut reader = &mut req.body; let mut buf = vec![0;300]; let mut vec: Vec<u8> = Vec::new(); while let Ok(n) = reader.read(&mut buf) { if n <= 0 { break; } vec.extend_from_slice(&buf[0..n]); } let body = String::from_utf8(vec.clone()).unwrap_or("".into()); combine_duplicates(form_urlencoded::parse(&vec), &mut map); (body, map) } fn combine_duplicates(q: url::form_urlencoded::Parse, map: &mut HashMap<String, Vec<String>>) { for (k, v) in q.into_iter() { let (k, v) = (k.into_owned(), v.into_owned()); match map.entry(k) { Occupied(entry) => { entry.into_mut().push(v); } Vacant(entry) => { entry.insert(vec![v]); } }; } }