extern crate hyper;
extern crate rustc_serialize;
use rustc_serialize::{json, Encodable, Decodable};
pub use hyper::method::Method;
use hyper::Client;
use hyper::header;
use hyper::status::StatusClass;
use std::io::{Read, self};
use std::error::Error as StdError;
#[derive(Debug)]
pub enum Error {
HttpClient(hyper::Error),
JsonEncoder(json::EncoderError),
JsonDecoder(json::DecoderError),
IoError(io::Error),
}
impl From<hyper::Error> for Error {
fn from(err: hyper::Error) -> Error {
Error::HttpClient(err)
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IoError(err)
}
}
impl From<json::EncoderError> for Error {
fn from(err: json::EncoderError) -> Error {
Error::JsonEncoder(err)
}
}
impl From<json::DecoderError> for Error {
fn from(err: json::DecoderError) -> Error {
Error::JsonDecoder(err)
}
}
pub type Result<T> = std::result::Result<T, Error>;
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&::std::error::Error> {
match *self {
Error::HttpClient(ref err) => Some(err),
Error::JsonDecoder(ref err) => Some(err),
Error::JsonEncoder(ref err) => Some(err),
Error::IoError(ref err) => Some(err),
}
}
fn description(&self) -> &str {
match *self {
Error::HttpClient(ref err) => err.description(),
Error::JsonDecoder(ref err) => err.description(),
Error::JsonEncoder(ref err) => err.description(),
Error::IoError(ref err) => err.description(),
}
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.write_str(self.description())
}
}
pub fn request<S, D>(method: Method, url: &str, data: Option<S>) -> Result<Option<D>>
where S: Encodable, D: Decodable {
let mut body = String::new();
let client = Client::new();
println!("url: {}", url);
let mut res = match data {
Some(inner) => {
let payload = try!(json::encode(&inner));
let builder = client.request(method, url)
.header(header::Connection::close())
.body(&payload[..]);
try!(builder.send())
},
None => {
let builder = client.request(method, url)
.header(header::Connection::close());
try!(builder.send())
}
};
Ok(match res.status.class() {
StatusClass::Success => {
try!(res.read_to_string(&mut body));
Some(try!(json::decode::<D>(&body[..])))
},
_ => None
})
}