Skip to content

Instantly share code, notes, and snippets.

@moorage
Last active May 28, 2018 19:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moorage/a5c18ec546373a25b1be405bf10b8a10 to your computer and use it in GitHub Desktop.
Save moorage/a5c18ec546373a25b1be405bf10b8a10 to your computer and use it in GitHub Desktop.
Easy function to call to fetch the primary email address of a user in Rust.
// Example usage:
// let github_email = fetch_github_primary_email(&some_access_token)?;
//
// Cargo.toml:
// ..
// [dependencies]
// rocket = "0.3.11"
// curl = "0.4"
// serde = "1.0"
// serde_json = "1.0"
// ..
extern crate curl;
extern crate serde;
extern crate serde_json;
use curl::easy::{Easy, List};
const GITHUB_V3_API: &str = "https://api.github.com";
const CONTENT_TYPE_JSON: &str = "application/json";
const GITHUB_APP_NAME: &str = "Example-App";
// handles any Error Result and converts to a 500 error in Rocket (for use within a Rocket Web Application).
// CHANGEME to return any other type of useful error
macro_rules! error_to_500 {
($x:expr) => {
match $x {
Err(err) => {
eprintln!("{}", err.to_string());
return Err(rocket::http::Status::InternalServerError);
}
Ok(_) => (),
}
};
}
fn github_v3_query(access_token: &str, endpoint: &str) -> Result<String, Status> {
let mut easy = Easy::new();
match easy.url(&format!("{}{}", GITHUB_V3_API, endpoint)) {
Err(err) => {
eprintln!("{}", err.to_string());
return Err(rocket::http::Status::InternalServerError);
}
Ok(_) => (),
};
let mut headers = List::new();
error_to_500!(headers.append(&format!("User-Agent: {}", GITHUB_APP_NAME)));
error_to_500!(headers.append(&format!("Authorization: token {}", access_token)));
error_to_500!(headers.append(&format!("Accept: {}", CONTENT_TYPE_JSON)));
error_to_500!(easy.http_headers(headers));
let mut data = Vec::new();
{
let mut transfer = easy.transfer();
error_to_500!(transfer.write_function(|new_data| {
data.extend_from_slice(new_data);
Ok(new_data.len())
}));
error_to_500!(transfer.perform());
}
let http_status_response = easy.response_code();
error_to_500!(http_status_response);
let response_code = http_status_response.unwrap();
if response_code != 200 {
eprintln!(
"Github V3 API returned {} : {}",
response_code,
String::from_utf8_lossy(data.as_slice())
);
return Err(rocket::http::Status::InternalServerError);
}
Ok(String::from_utf8_lossy(data.as_slice()).to_string())
}
fn fetch_github_primary_email(access_token: &str) -> Result<String, Status> {
let github_emails_str = github_v3_query(access_token, &"/user/emails")?;
let email_parse_result = serde_json::from_str(&github_emails_str);
error_to_500!(email_parse_result);
let github_emails: Vec<serde_json::Value> = email_parse_result.unwrap();
let mut github_primary_email = String::from("");
for x in github_emails {
if x["primary"].is_boolean() && x["primary"].as_bool().unwrap() {
let parsed_email = x["email"].as_str();
github_primary_email = match parsed_email {
None => {
eprintln!("Did not find a string during json decoding email from GitHub");
return Err(rocket::http::Status::InternalServerError);
}
Some(t) => t.to_string(),
};
break;
}
}
Ok(github_primary_email)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment