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
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>; } 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> { if let Some(vec) = self.params(name) { if vec.len() > 0 { let s: String = vec[0].clone(); return s.parse().ok(); } } None } } pub struct Params; impl iron::typemap::Key for Params { type Value = Arc<HashMap<String, Vec<String>>>; } impl iron::BeforeMiddleware for Params { fn before(&self, req: &mut Request) -> IronResult<()> { let map = Arc::new(combine(req)); req.extensions.insert::<Params>(map); Ok(()) } } fn combine(req: &mut Request) -> 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]); } combine_duplicates(form_urlencoded::parse(&vec), &mut map); map } fn combine_duplicates(q: url::form_urlencoded::Parse, map: &mut HashMap<String, Vec<String>>) { for (k, v) in q.into_iter() { let k = k.into_owned(); let v = v.into_owned(); match map.entry(k) { Occupied(entry) => { entry.into_mut().push(v); } Vacant(entry) => { entry.insert(vec![v]); } }; } }