Skip to main content

influent/hurl/
hyper.rs

1use hyper::Client as HyperClient;
2use hyper::Method as HyperMethod;
3use hyper::Request as HyperRequest;
4use http::header::AUTHORIZATION;
5use url::Url;
6use base64;
7use futures::{self, Future, Stream};
8
9use super::{Request, Response, Method, HurlResult};
10
11use super::Hurl;
12
13#[derive(Default)]
14pub struct HyperHurl;
15
16impl HyperHurl {
17    pub fn new() -> HyperHurl {
18        HyperHurl::default()
19    }
20}
21
22impl Hurl for HyperHurl {
23    fn request(&self, req: Request) -> HurlResult {
24        let client = HyperClient::default();
25
26        // map request method to the hyper's
27        let method = match req.method {
28            Method::POST => HyperMethod::POST,
29            Method::GET  => HyperMethod::GET,
30        };
31
32        let mut url = match Url::parse(req.url) {
33            Ok(u) => { u }
34            Err(e) => {
35                return Box::new(futures::future::err(format!("could not parse url: {:?}", e)));
36            }
37        };
38
39        // if request has query
40        if let Some(ref query) = req.query {
41            // if any existing pairs
42            let existing: Vec<(String, String)> = url.query_pairs().map(|(a,b)| (a.to_string(), b.to_string())).collect();
43
44            // final pairs
45            let mut pairs: Vec<(&str, &str)> = Vec::new();
46
47            // add first existing
48            for pair in &existing {
49                pairs.push((&pair.0, &pair.1));
50            }
51
52            // add given query to the pairs
53            for (key, val) in query.iter() {
54                pairs.push((key, val));
55            }
56
57            // set new pairs
58            url.query_pairs_mut().clear().extend_pairs(
59                pairs.iter().map(|&(k, v)| { (&k[..], &v[..]) })
60            );
61        }
62
63        // create query
64        let mut query = HyperRequest::builder();
65        query.method(method)
66            .uri(url.as_str());
67
68        // if request need to be authorized
69        if let Some(auth) = req.auth {
70            let auth = base64::encode(&format!("{}:{}", auth.username, auth.password));
71            query.header(AUTHORIZATION, auth);
72        }
73
74        let request = if let Some(body) = req.body {
75            query.body(body.into()).unwrap()
76        } else {
77            query.body("".into()).unwrap()
78        };
79
80        Box::new(client
81            .request(request)
82            .and_then(|resp| {
83                let status = resp.status().as_u16();
84
85                resp.into_body().concat2().and_then(move |body| {
86                    Ok(String::from_utf8(body.to_vec()).unwrap())
87                }).and_then(move |body|
88                    Ok(Response {
89                        status,
90                        body
91                    })
92                )
93            })
94            .map_err(|_| format!(""))
95        )
96    }
97}