Implement Client::request_token

This commit is contained in:
Curtis McEnroe 2015-11-28 15:20:59 -05:00
parent 0592eba8a1
commit 10823a3d81
1 changed files with 68 additions and 1 deletions

View File

@ -1,6 +1,11 @@
use std::io::Read;
use chrono::{UTC, Duration};
use hyper::{self, header, mime};
use rustc_serialize::json;
use url::{Url, form_urlencoded};
use super::Result;
use super::{Error, Result, Token};
/// OAuth 2.0 client.
pub struct Client {
@ -85,4 +90,66 @@ impl Client {
Ok(uri.serialize())
}
/// Requests an access token using an authorization code.
pub fn request_token(&self, client: hyper::Client, code: &str) -> Result<Token> {
let auth_header = header::Authorization(
header::Basic {
username: self.client_id.clone(),
password: Some(self.client_secret.clone()),
}
);
let accept_header = header::Accept(vec![
header::qitem(
mime::Mime(
mime::TopLevel::Application,
mime::SubLevel::Json,
vec![]
)
),
]);
let mut body_pairs = vec![
("grant_type", "authorization_code"),
("code", code),
];
if let Some(ref redirect_uri) = self.redirect_uri {
body_pairs.push(("redirect_uri", redirect_uri));
}
let body_str = form_urlencoded::serialize(body_pairs);
let request = client.post(&self.token_uri)
.header(auth_header)
.header(accept_header)
.header(header::ContentType::form_url_encoded())
.body(&body_str);
let mut response = try!(request.send());
let mut json = String::new();
try!(response.read_to_string(&mut json));
if response.status != hyper::Ok {
return Err(Error::Todo);
}
#[derive(RustcDecodable)]
struct TokenResponse {
access_token: String,
token_type: String,
expires_in: Option<i64>,
refresh_token: Option<String>,
scope: Option<String>,
}
let token: TokenResponse = try!(json::decode(&json));
Ok(Token {
access_token: token.access_token,
token_type: token.token_type,
expires: token.expires_in.map(|s| UTC::now() + Duration::seconds(s)),
refresh_token: token.refresh_token,
scope: token.scope,
})
}
}