Skip to content

Instantly share code, notes, and snippets.

@moorage
Created May 27, 2018 20:11
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/005aa094f924c89ab0892a5163cd94e5 to your computer and use it in GitHub Desktop.
Save moorage/005aa094f924c89ab0892a5163cd94e5 to your computer and use it in GitHub Desktop.
Easy function to call GitHub's GraphQL server in Rust.
// Example usage:
// let github_details = github_graphql_query(
// &"some_oauth_access_token",
// &"query { viewer { email name login id location websiteUrl } }",
// )?;
//
// Cargo.toml:
// ..
// [dependencies]
// rocket = "0.3.11"
// curl = "0.4"
// ..
extern crate curl;
use curl::easy::{Easy, List};
const CONTENT_TYPE_JSON: &str = "application/json";
const GITHUB_GRAPHQL_API: &str = "https://api.github.com/graphql";
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_graphql_query(access_token: &str, graphql_query: &str) -> Result<String, Status> {
let mut easy = Easy::new();
match easy.url(GITHUB_GRAPHQL_API) {
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: bearer {}", access_token)));
error_to_500!(headers.append(&format!("Accept: {}", CONTENT_TYPE_JSON)));
error_to_500!(easy.http_headers(headers));
error_to_500!(easy.post(true));
let query_json_str = format!("{{ \"query\": \"{}\" }}", graphql_query);
let mut query_json = query_json_str.as_bytes();
error_to_500!(easy.post_field_size(query_json.len() as u64));
let mut data = Vec::new();
{
let mut transfer = easy.transfer();
error_to_500!(transfer.read_function(|buf| Ok(query_json.read(buf).unwrap_or(0))));
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 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())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment