codealong_github/
client.rs

1use reqwest;
2use reqwest::Response;
3use std::env;
4
5use crate::error::{ErrorKind, ErrorPayload, Result};
6
7pub struct Client {
8    token: Option<String>,
9}
10
11/// Very basic wrapper around reqwest to interact with the github api
12impl Client {
13    pub fn new(token: String) -> Client {
14        Client { token: Some(token) }
15    }
16
17    pub fn public() -> Client {
18        Client { token: None }
19    }
20
21    pub fn from_env() -> Client {
22        Client {
23            token: env::var_os("GITHUB_TOKEN").and_then(|s| s.into_string().ok()),
24        }
25    }
26
27    pub fn get(&self, url: &str) -> Result<Response> {
28        self.get_with_content_type(url, "application/vnd.github+json")
29    }
30
31    pub fn get_with_content_type(&self, url: &str, content_type: &str) -> Result<Response> {
32        let client = reqwest::Client::new();
33        let mut builder = client.get(url).header("Accept", content_type);
34        if let Some(ref token) = self.token {
35            builder = builder.header("Authorization", format!("token {}", token));
36        }
37        let mut res = builder.send()?;
38        if res.status().is_success() {
39            Ok(res)
40        } else {
41            Err(self.get_error_kind(&mut res).into())
42        }
43    }
44
45    fn get_error_kind(&self, res: &mut reqwest::Response) -> ErrorKind {
46        let payload = res.json::<ErrorPayload>().unwrap();
47        if payload
48            .message
49            .contains("have triggered an abuse detection mechanism")
50        {
51            ErrorKind::RateLimitted
52        } else {
53            ErrorKind::Unknown
54        }
55    }
56}