use std::fmt;
use std::io::Read; use std::env;
use hyper;
use serde;
use serde_json;
pub const API_VERSION: u16 = 3;
#[derive(Default, Clone, Copy, Debug)]
pub struct Pagination {
pub page: u16,
pub per_page: u16,
}
#[derive(Default)]
pub struct GitLab {
scheme: String,
domain: String,
port: u16,
private_token: String,
pagination: Option<Pagination>,
client: hyper::Client,
}
impl fmt::Debug for GitLab {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
pagination: {:?} }}",
self.scheme,
self.domain,
self.port,
self.pagination)
}
}
impl GitLab {
pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
GitLab {
scheme: scheme.to_string(),
domain: domain.to_string(),
port: port,
private_token: private_token.to_string(),
pagination: None,
client: match env::var("HTTP_PROXY") {
Ok(proxy) => {
let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
let hostname = proxy[0].to_string();
let port = proxy[1];
hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
}
Err(_) => hyper::Client::new(),
},
}
}
pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
warn!("Using insecure http:// protocol: Token will be sent in clear!");
GitLab::_new("http", domain, 80, private_token)
}
pub fn new(domain: &str, private_token: &str) -> GitLab {
GitLab::_new("https", domain, 443, private_token)
}
pub fn build_url(&self, query: &str) -> String {
let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
self.scheme,
self.domain,
self.port,
API_VERSION,
query,
params_splitter,
self.private_token);
self.pagination.as_ref().map(|pagination| {
url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
});
url
}
pub fn set_pagination(&mut self, pagination: Pagination) {
self.pagination = Some(pagination);
}
pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
where T: serde::Deserialize
{
let url = self.build_url(query);
info!("url: {:?}", url);
let mut res: hyper::client::Response = self.client
.get(&url)
.header(hyper::header::Connection::close())
.send()
.unwrap();
info!("res.status: {:?}", res.status);
debug!("res.headers: {:?}", res.headers);
debug!("res.url: {:?}", res.url);
let mut body = String::new();
res.read_to_string(&mut body).unwrap();
debug!("body:\n{:?}", body);
assert_eq!(res.status, hyper::status::StatusCode::Ok);
serde_json::from_str(body.as_str())
}
pub fn version(&self) -> ::Version {
self.get("version").unwrap()
}
pub fn projects(&self) -> ::projects::ProjectsLister {
::projects::ProjectsLister::new(self)
}
}