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
use ::Response; use models::container::DataContainer; use models::repository::{RepositorySummary, Repository}; use hyper::{Client as HyperClient, Url}; use hyper::client::Response as HyperResponse; use hyper::header::{Accept, Authorization, Basic, Headers, qitem}; use hyper::mime::{Mime, TopLevel, SubLevel}; use serde::Deserialize; use serde_json; use std::io::{Bytes, Read}; use std::str::FromStr; #[derive(Debug)] pub struct Client { client: HyperClient, headers: Headers, base_url: Url, } impl FromStr for Client { type Err=String; fn from_str(url: &str) -> Result<Self, Self::Err> { let url = Url::parse(url); match url { Ok(url) => Client::from_url(url), Err(_) => Err("Invalid URL".to_string()) } } } impl Client { pub fn from_url(url: Url) -> Result<Self, String> { let mut headers = Headers::new(); headers.set(Authorization(Basic { username: url.username().to_string(), password: url.password().map(|x| x.to_string()), })); headers.set(Accept(vec![qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))])); let hyper_client = HyperClient::new(); match hyper_client.get(url.as_str()).send() { Err(x) => Err(x.to_string()), Ok(x) => { if x.status == ::hyper::Ok { Ok(Client { client: hyper_client, headers: headers, base_url: url, }) } else { Err(String::from("Non-success error code")) } } } } pub fn get_absolute_raw<'a>(&'a self, url: &str) -> Result<Response<'a, HyperResponse>, String> { let url = Url::parse(url).unwrap(); let req = self.client.get(url.clone()).headers(self.headers.clone()); match req.send() { Ok(res) => Ok(Response { client: self, item: res }), Err(x) => { Err(format!("Error fetching {}, ({})", &url.to_string(), x.to_string())) } } } pub fn get_absolute<'a, T: Deserialize>(&'a self, url: &str) -> Result<Response<'a, T>, String> { match self.get_absolute_raw(url) { Ok(res) => match serde_json::from_iter::<Bytes<HyperResponse>, DataContainer<T>>(res.item.bytes()) { Ok(data_container) => Ok(Response { client: self, item: data_container.data }), Err(x) => { Err(format!("Error parsing {}, ({})", &url.to_string(), x.to_string())) } }, Err(x) => Err(x) } } pub fn get_relative_raw<'a>(&'a self, path: &str) -> Result<Response<'a, HyperResponse>, String> { self.get_absolute_raw(self.base_url.join(path).unwrap().as_str()) } pub fn get_relative<'a, T: Deserialize>(&'a self, path: &str) -> Result<Response<'a, T>, String> { self.get_absolute::<T>(self.base_url.join(path).unwrap().as_str()) } pub fn all_repositories<'a>(&'a self) -> Result<Vec<Response<'a, RepositorySummary>>, String> { self.get_relative::<Vec<RepositorySummary>>("service/local/all_repositories").map(|x| x.into()) } pub fn repository(&self, id: &str) -> Result<Response<Repository>, String> { Repository::from_id(self, id) } pub fn with_item<T>(&self, item: T) -> Response<T> { Response { client: self, item: item, } } }