Skip to content

Commit 52cea71

Browse files
committed
Pull github interaction out of http module into a github module
1 parent 6793f4a commit 52cea71

File tree

5 files changed

+107
-105
lines changed

5 files changed

+107
-105
lines changed

src/github.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use curl;
2+
use curl::easy::{Easy, List};
3+
4+
use oauth2::*;
5+
6+
use serde_json;
7+
use serde::Deserialize;
8+
9+
use std::str;
10+
11+
use app::App;
12+
use util::{human, internal, CargoResult, ChainError};
13+
14+
/// Does all the nonsense for sending a GET to Github. Doesn't handle parsing
15+
/// because custom error-code handling may be desirable. Use
16+
/// `parse_github_response` to handle the "common" processing of responses.
17+
pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec<u8>), curl::Error> {
18+
let url = format!("{}://api.github.com{}", app.config.api_protocol, url);
19+
info!("GITHUB HTTP: {}", url);
20+
21+
let mut headers = List::new();
22+
headers
23+
.append("Accept: application/vnd.github.v3+json")
24+
.unwrap();
25+
headers.append("User-Agent: hello!").unwrap();
26+
headers
27+
.append(&format!("Authorization: token {}", auth.access_token))
28+
.unwrap();
29+
30+
let mut handle = app.handle();
31+
handle.url(&url).unwrap();
32+
handle.get(true).unwrap();
33+
handle.http_headers(headers).unwrap();
34+
35+
let mut data = Vec::new();
36+
{
37+
let mut transfer = handle.transfer();
38+
transfer
39+
.write_function(|buf| {
40+
data.extend_from_slice(buf);
41+
Ok(buf.len())
42+
})
43+
.unwrap();
44+
transfer.perform()?;
45+
}
46+
Ok((handle, data))
47+
}
48+
49+
/// Checks for normal responses
50+
pub fn parse_github_response<'de, 'a: 'de, T: Deserialize<'de>>(
51+
mut resp: Easy,
52+
data: &'a [u8],
53+
) -> CargoResult<T> {
54+
match resp.response_code().unwrap() {
55+
200 => {}
56+
// Ok!
57+
403 => {
58+
return Err(human(
59+
"It looks like you don't have permission \
60+
to query a necessary property from Github \
61+
to complete this request. \
62+
You may need to re-authenticate on \
63+
crates.io to grant permission to read \
64+
github org memberships. Just go to \
65+
https://crates.io/login",
66+
));
67+
}
68+
n => {
69+
let resp = String::from_utf8_lossy(data);
70+
return Err(internal(&format_args!(
71+
"didn't get a 200 result from \
72+
github, got {} with: {}",
73+
n,
74+
resp
75+
)));
76+
}
77+
}
78+
79+
let json = str::from_utf8(data)
80+
.ok()
81+
.chain_error(|| internal("github didn't send a utf8-response"))?;
82+
83+
serde_json::from_str(json).chain_error(|| internal("github didn't send a valid json response"))
84+
}
85+
86+
/// Gets a token with the given string as the access token, but all
87+
/// other info null'd out. Generally, just to be fed to the `github` fn.
88+
pub fn token(token: String) -> Token {
89+
Token {
90+
access_token: token,
91+
scopes: Vec::new(),
92+
token_type: String::new(),
93+
}
94+
}

src/http.rs

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,11 @@
11
use conduit::{Request, Response};
22
use conduit_middleware::Middleware;
33

4-
use curl;
5-
use curl::easy::{Easy, List};
6-
7-
use oauth2::*;
8-
9-
use serde_json;
10-
use serde::Deserialize;
11-
12-
use std::str;
134
use std::error::Error;
145
use std::collections::HashMap;
156

16-
use app::App;
17-
use util::{human, internal, CargoResult, ChainError};
187
use Uploader;
198

20-
/// Does all the nonsense for sending a GET to Github. Doesn't handle parsing
21-
/// because custom error-code handling may be desirable. Use
22-
/// `parse_github_response` to handle the "common" processing of responses.
23-
pub fn github(app: &App, url: &str, auth: &Token) -> Result<(Easy, Vec<u8>), curl::Error> {
24-
let url = format!("{}://api.github.com{}", app.config.api_protocol, url);
25-
info!("GITHUB HTTP: {}", url);
26-
27-
let mut headers = List::new();
28-
headers
29-
.append("Accept: application/vnd.github.v3+json")
30-
.unwrap();
31-
headers.append("User-Agent: hello!").unwrap();
32-
headers
33-
.append(&format!("Authorization: token {}", auth.access_token))
34-
.unwrap();
35-
36-
let mut handle = app.handle();
37-
handle.url(&url).unwrap();
38-
handle.get(true).unwrap();
39-
handle.http_headers(headers).unwrap();
40-
41-
let mut data = Vec::new();
42-
{
43-
let mut transfer = handle.transfer();
44-
transfer
45-
.write_function(|buf| {
46-
data.extend_from_slice(buf);
47-
Ok(buf.len())
48-
})
49-
.unwrap();
50-
transfer.perform()?;
51-
}
52-
Ok((handle, data))
53-
}
54-
55-
/// Checks for normal responses
56-
pub fn parse_github_response<'de, 'a: 'de, T: Deserialize<'de>>(
57-
mut resp: Easy,
58-
data: &'a [u8],
59-
) -> CargoResult<T> {
60-
match resp.response_code().unwrap() {
61-
200 => {}
62-
// Ok!
63-
403 => {
64-
return Err(human(
65-
"It looks like you don't have permission \
66-
to query a necessary property from Github \
67-
to complete this request. \
68-
You may need to re-authenticate on \
69-
crates.io to grant permission to read \
70-
github org memberships. Just go to \
71-
https://crates.io/login",
72-
));
73-
}
74-
n => {
75-
let resp = String::from_utf8_lossy(data);
76-
return Err(internal(&format_args!(
77-
"didn't get a 200 result from \
78-
github, got {} with: {}",
79-
n,
80-
resp
81-
)));
82-
}
83-
}
84-
85-
let json = str::from_utf8(data)
86-
.ok()
87-
.chain_error(|| internal("github didn't send a utf8-response"))?;
88-
89-
serde_json::from_str(json).chain_error(|| internal("github didn't send a valid json response"))
90-
}
91-
92-
/// Gets a token with the given string as the access token, but all
93-
/// other info null'd out. Generally, just to be fed to the `github` fn.
94-
pub fn token(token: String) -> Token {
95-
Token {
96-
access_token: token,
97-
scopes: Vec::new(),
98-
token_type: String::new(),
99-
}
100-
}
101-
1029
#[derive(Clone, Debug)]
10310
pub struct SecurityHeadersMiddleware {
10411
headers: HashMap<String, Vec<String>>,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub mod dependency;
8484
pub mod dist;
8585
pub mod download;
8686
pub mod git;
87+
pub mod github;
8788
pub mod http;
8889
pub mod keyword;
8990
pub mod krate;

src/owner.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use diesel::prelude::*;
22

33
use app::App;
4-
use http;
4+
use github;
55
use schema::*;
66
use util::{human, CargoResult};
77
use {Crate, User};
@@ -184,9 +184,9 @@ impl Team {
184184
// FIXME: we just set per_page=100 and don't bother chasing pagination
185185
// links. A hundred teams should be enough for any org, right?
186186
let url = format!("/orgs/{}/teams?per_page=100", org_name);
187-
let token = http::token(req_user.gh_access_token.clone());
188-
let (handle, data) = http::github(app, &url, &token)?;
189-
let teams: Vec<GithubTeam> = http::parse_github_response(handle, &data)?;
187+
let token = github::token(req_user.gh_access_token.clone());
188+
let (handle, data) = github::github(app, &url, &token)?;
189+
let teams: Vec<GithubTeam> = github::parse_github_response(handle, &data)?;
190190

191191
let team = teams
192192
.into_iter()
@@ -209,8 +209,8 @@ impl Team {
209209
}
210210

211211
let url = format!("/orgs/{}", org_name);
212-
let (handle, resp) = http::github(app, &url, &token)?;
213-
let org: Org = http::parse_github_response(handle, &resp)?;
212+
let (handle, resp) = github::github(app, &url, &token)?;
213+
let org: Org = github::parse_github_response(handle, &resp)?;
214214

215215
NewTeam::new(login, team.id, team.name, org.avatar_url).create_or_update(conn)
216216
}
@@ -276,15 +276,15 @@ fn team_with_gh_id_contains_user(app: &App, github_id: i32, user: &User) -> Carg
276276
}
277277

278278
let url = format!("/teams/{}/memberships/{}", &github_id, &user.gh_login);
279-
let token = http::token(user.gh_access_token.clone());
280-
let (mut handle, resp) = http::github(app, &url, &token)?;
279+
let token = github::token(user.gh_access_token.clone());
280+
let (mut handle, resp) = github::github(app, &url, &token)?;
281281

282282
// Officially how `false` is returned
283283
if handle.response_code().unwrap() == 404 {
284284
return Ok(false);
285285
}
286286

287-
let membership: Membership = http::parse_github_response(handle, &resp)?;
287+
let membership: Membership = github::parse_github_response(handle, &resp)?;
288288

289289
// There is also `state: pending` for which we could possibly give
290290
// some feedback, but it's not obvious how that should work.

src/user/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use pagination::Paginate;
1414
use schema::*;
1515
use util::{bad_request, human, CargoResult, RequestUtils};
1616
use version::EncodableVersion;
17-
use {http, Version};
17+
use {github, Version};
1818
use owner::{CrateOwner, Owner, OwnerKind};
1919
use krate::Crate;
2020
use email;
@@ -375,8 +375,8 @@ pub fn github_access_token(req: &mut Request) -> CargoResult<Response> {
375375
.exchange(code.clone())
376376
.map_err(|s| human(&s))?;
377377

378-
let (handle, resp) = http::github(req.app(), "/user", &token)?;
379-
let ghuser: GithubUser = http::parse_github_response(handle, &resp)?;
378+
let (handle, resp) = github::github(req.app(), "/user", &token)?;
379+
let ghuser: GithubUser = github::parse_github_response(handle, &resp)?;
380380

381381
let user = NewUser::new(
382382
ghuser.id,

0 commit comments

Comments
 (0)