Skip to content
This repository has been archived by the owner on Nov 14, 2023. It is now read-only.

Commit

Permalink
feat(Headers): implements response headers
Browse files Browse the repository at this point in the history
Closes #12
  • Loading branch information
kbknapp committed Jun 2, 2015
1 parent dc412cf commit 556db47
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/request/builder/images.rs
Expand Up @@ -29,6 +29,13 @@ impl<'t> RequestBuilder<'t, response::Image> {
resp_t: PhantomData
}
}
pub fn action(mut self, id: &str) -> RequestBuilder<'t, response::Action> {
// GET: https://api.digitalocean.com/v2/images/$IMG_ID/actions/$ID
self.url.push_str("/actions/");
self.url.push_str(id);
RequestBuilder::new(self.auth, self.url)
}

pub fn update(mut self, name: &str) -> RequestBuilder<'t, response::Image> {
// PUT: https://api.digitalocean.com/v2/images/$NAME
self.url.push('/');
Expand All @@ -38,8 +45,14 @@ impl<'t> RequestBuilder<'t, response::Image> {
.. self
}
}
pub fn delete(&self) -> RequestBuilder<'t, response::Image> {
unimplemented!()
pub fn delete(self) -> RequestBuilder<'t, response::Image> {
// PUT: https://api.digitalocean.com/v2/images/$NAME
RequestBuilder {
method: Method::Delete,
auth: self.auth,
url: self.url,
resp_t: PhantomData
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/request/builder/request.rs
Expand Up @@ -4,6 +4,7 @@ use std::fmt;

use serde::{json, Deserialize};
use hyper::method::Method;
use hyper::client::response::Response;

use response::{self, RawPagedResponse, NamedResponse};
use request::{BaseRequest, DoRequest};
Expand Down Expand Up @@ -149,3 +150,9 @@ impl<'t, I> DoRequest<Vec<I>> for RequestBuilder<'t, Vec<I>>
}
}
}

impl<'t> DoRequest<response::HeaderOnly> for RequestBuilder<'t, response::HeaderOnly> {
fn retrieve(&self) -> Result<response::HeaderOnly, String> {
self.retrieve_header()
}
}
34 changes: 34 additions & 0 deletions src/request/dorequest.rs
Expand Up @@ -57,6 +57,40 @@ pub trait DoRequest<T> : BaseRequest
Ok(s)
}

fn retrieve_raw_response(&self) -> hyper::Result<client::response::Response> {
let url = match Url::parse(&self.url()) {
Ok(url) => url,
Err(e) => return Err(Error::Uri(e)),
};
let mut fresh_req = match client::Request::new(Method::Get, url) {
Ok(req) => req,
Err(e) => return Err(e)
};
let mut auth_s = String::new();
auth_s.push_str("Bearer ");
auth_s.push_str(self.auth());
fresh_req.headers_mut().set(ContentType("application/json".parse().unwrap()));
fresh_req.headers_mut().set(Authorization(auth_s));
let streaming_req = try!(fresh_req.start());
let response = try!(streaming_req.send());
Ok(response)
}

fn retrieve_header(&self) -> Result<response::HeaderOnly, String> {
debug!("Inside retrieve_header()");
debug!("Getting raw response...");
match self.retrieve_raw_response() {
Ok(resp) => {
let header = try!(response::HeaderOnly::from_response(resp));
Ok(header)
},
Err(e) => {
debug!("Error getting json: {}", e.to_string());
Err(e.to_string())
}
}
}

fn retrieve_obj(&self, obj: String) -> Result<T, String> {
match self.retrieve_json() {
Ok(ref s) => {
Expand Down
107 changes: 107 additions & 0 deletions src/response/header.rs
@@ -0,0 +1,107 @@
// content-type: application/octet-stream
// status: 204 No Content
// ratelimit-limit: 1200
// ratelimit-remaining: 771
// ratelimit-reset: 1415984218

use std::borrow::Cow;
use std::fmt;

use hyper::client::response::Response;
use hyper::header;

use response::NamedResponse;

#[derive(Deserialize)]
pub struct HeaderOnly {
#[serde(rename="content-type")]
pub content_type: String,
pub status: String,
#[serde(rename="ratelimit-limit")]
pub ratelimit_limit: f64,
#[serde(rename="ratelimit-remaining")]
pub ratelimit_remaining: f64,
#[serde(rename="ratelimit-reset")]
pub ratelimit_reset: f64
}

impl HeaderOnly {
pub fn from_response(r: Response) -> Result<HeaderOnly, String> {
let c_type = match r.headers.get::<header::ContentType>() {
Some(c) => c,
None => return Err("No content-type provided".to_owned())
};
let raw_status = r.status_raw();
let status = format!("{} {}", raw_status.0, raw_status.1);
let rl_limit_raw = match r.headers.get_raw("ratelimit-limit") {
Some(c) => c,
None => return Err("No ratelimit-limit provided".to_owned())
};
let rl_remain_raw = match r.headers.get_raw("ratelimit-remaining") {
Some(c) => c,
None => return Err("No ratelimit-remaining provided".to_owned())
};
let rl_reset_raw = match r.headers.get_raw("ratelimit-reset") {
Some(c) => c,
None => return Err("No ratelimit-reset provided".to_owned())
};
let rl_limit_str = String::from_utf8_lossy(&rl_limit_raw[0][..]);
let rl_remain_str = String::from_utf8_lossy(&rl_remain_raw[0][..]);
let rl_reset_str = String::from_utf8_lossy(&rl_reset_raw[0][..]);
let rl_limit = match rl_limit_str.as_ref().parse::<f64>() {
Ok(n) => n,
Err(e) => return Err(e.to_string())
};
let rl_remain = match rl_remain_str.as_ref().parse::<f64>() {
Ok(n) => n,
Err(e) => return Err(e.to_string())
};
let rl_reset = match rl_reset_str.as_ref().parse::<f64>() {
Ok(n) => n,
Err(e) => return Err(e.to_string())
};
Ok(HeaderOnly {
content_type: c_type.to_string(),
status: status,
ratelimit_limit: rl_limit,
ratelimit_remaining: rl_remain,
ratelimit_reset: rl_reset
})
}
}

impl NamedResponse for HeaderOnly {
fn name<'a>() -> Cow<'a, str> {
"header".into()
}
}

impl fmt::Display for HeaderOnly {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Status: {}\n\
Request Limit: {:.0}\n\
Requests Remaining: {:.0}\n\
Time to Reset: {:.0}\n",
self.status,
self.ratelimit_limit,
self.ratelimit_remaining,
self.ratelimit_reset
)
}
}

impl fmt::Debug for HeaderOnly {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "content-type: {:?}\n\
status: {:?}\n\
ratelimit-limit: {:.0}\n\
ratelimit-remaining: {:.0}\n\
ratelimit_reset: {:.0}\n",
self.content_type,
self.status,
self.ratelimit_limit,
self.ratelimit_remaining,
self.ratelimit_reset
)
}
}
2 changes: 2 additions & 0 deletions src/response/mod.rs
Expand Up @@ -16,8 +16,10 @@ pub use self::image::{Image, Images};
pub use self::dns::{DnsRecord, DnsRecords};
pub use self::namedresponse::NamedResponse;
pub use self::snapshot::{Snapshot, Snapshots};
pub use self::header::HeaderOnly;

mod account;
mod header;
mod network;
mod kernel;
mod backup;
Expand Down

0 comments on commit 556db47

Please sign in to comment.