xml_rpc/
client.rs

1use super::error::{Result, ResultExt};
2use super::xmlfmt::{from_params, into_params, parse, Call, Fault, Params, Response};
3use hyper::{self, Client as HyperClient};
4use serde::{Deserialize, Serialize};
5use std;
6use Url;
7
8use hyper::header::Headers;
9header! { (ContentType, "ContentType") => [String] }
10
11pub fn call_value<Tkey>(uri: &Url, name: Tkey, params: Params) -> Result<Response>
12where
13    Tkey: Into<String>,
14{
15    Client::new()?.call_value(uri, name, params)
16}
17
18pub fn call<'a, Tkey, Treq, Tres>(
19    uri: &Url,
20    name: Tkey,
21    req: Treq,
22) -> Result<std::result::Result<Tres, Fault>>
23where
24    Tkey: Into<String>,
25    Treq: Serialize,
26    Tres: Deserialize<'a>,
27{
28    Client::new()?.call(uri, name, req)
29}
30
31pub struct Client {
32    client: HyperClient,
33}
34
35impl Client {
36    pub fn new() -> Result<Client> {
37        let client = HyperClient::new();
38        Ok(Client { client })
39    }
40
41    pub fn call_value<Tkey>(&mut self, uri: &Url, name: Tkey, params: Params) -> Result<Response>
42    where
43        Tkey: Into<String>,
44    {
45        use super::xmlfmt::value::ToXml;
46        let body_str = Call {
47            name: name.into(),
48            params,
49        }
50        .to_xml();
51        let bytes: &[u8] = body_str.as_bytes();
52        let body = hyper::client::Body::BufBody(bytes, bytes.len());
53
54        let mut headers = Headers::new();
55        headers.set(ContentType("xml".to_owned()));
56
57        let response = self
58            .client
59            .post(uri.as_ref())
60            .headers(headers)
61            .body(body)
62            .send()
63            .chain_err(|| "Failed to run the HTTP request within hyper.")?;
64
65        parse::response(response).map_err(Into::into)
66    }
67
68    pub fn call<'a, Tkey, Treq, Tres>(
69        &mut self,
70        uri: &Url,
71        name: Tkey,
72        req: Treq,
73    ) -> Result<std::result::Result<Tres, Fault>>
74    where
75        Tkey: Into<String>,
76        Treq: Serialize,
77        Tres: Deserialize<'a>,
78    {
79        match self.call_value(uri, name, into_params(&req)?) {
80            Ok(Ok(v)) => from_params(v).map(Ok).map_err(Into::into),
81            Ok(Err(v)) => Ok(Err(v)),
82            Err(v) => Err(v),
83        }
84    }
85}