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 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 let Some(ref query) = req.query {
41 let existing: Vec<(String, String)> = url.query_pairs().map(|(a,b)| (a.to_string(), b.to_string())).collect();
43
44 let mut pairs: Vec<(&str, &str)> = Vec::new();
46
47 for pair in &existing {
49 pairs.push((&pair.0, &pair.1));
50 }
51
52 for (key, val) in query.iter() {
54 pairs.push((key, val));
55 }
56
57 url.query_pairs_mut().clear().extend_pairs(
59 pairs.iter().map(|&(k, v)| { (&k[..], &v[..]) })
60 );
61 }
62
63 let mut query = HyperRequest::builder();
65 query.method(method)
66 .uri(url.as_str());
67
68 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}