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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
extern crate jsonrpc_client_core;
extern crate tokio_core;
use futures::Stream;
use futures::future::Future;
use hyper::{Client, Request, StatusCode, Uri};
use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector;
use tokio_core::reactor::{Core, Handle};
use jsonrpc_client_core::Transport;
use std::str::FromStr;
error_chain! {
errors {
TransportError
HttpError(http_code: StatusCode) {
description("Http error. Server did not return 200 OK")
display("Http error. Status code {}", http_code)
}
}
foreign_links {
Hyper(hyper::Error);
Uri(hyper::error::UriError);
}
}
pub struct HttpTransport {
core: Core,
client: hyper::Client<HttpsConnector<HttpConnector>, hyper::Body>,
uri: Uri,
}
impl HttpTransport {
pub fn new(uri: &str) -> Result<Self> {
let uri = Uri::from_str(uri)?;
let core = tokio_core::reactor::Core::new()
.chain_err(|| ErrorKind::TransportError)?;
let client = Self::create_client(core.handle())?;
Ok(HttpTransport { core, client, uri })
}
fn create_client(handle: Handle) -> Result<Client<HttpsConnector<HttpConnector>, hyper::Body>> {
let https_connector = HttpsConnector::new(1, &handle)
.chain_err(|| ErrorKind::TransportError)?;
Ok(
Client::configure()
.connector(https_connector)
.build(&handle),
)
}
fn create_request(&self, body: Vec<u8>) -> Request {
let mut request = hyper::Request::new(hyper::Method::Post, self.uri.clone());
request
.headers_mut()
.set(hyper::header::ContentType::json());
request
.headers_mut()
.set(hyper::header::ContentLength(body.len() as u64));
request.set_body(body);
request
}
}
impl Transport<Error> for HttpTransport {
fn send(&mut self, json_data: &[u8]) -> Result<Vec<u8>> {
let request = self.create_request(json_data.to_owned());
let response_future = self.client
.request(request)
.map_err(|e| e.into())
.and_then(|res: hyper::Response| {
let result: Result<hyper::Response> = if res.status() != hyper::StatusCode::Ok {
Err(ErrorKind::HttpError(res.status()).into())
} else {
Ok(res)
};
futures::future::result(result)
})
.and_then(|res: hyper::Response| {
res.body().concat2().map_err(|e| e.into())
});
let json_response = self.core.run(response_future)?;
Ok(json_response.to_vec())
}
}