iron_params/
lib.rs

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