11use anyhow:: { anyhow, Context } ;
22use async_trait:: async_trait;
3+ use bytes:: Bytes ;
34use chrono:: { DateTime , FixedOffset , Utc } ;
45use futures:: { future:: BoxFuture , FutureExt } ;
56use hyper:: header:: HeaderValue ;
@@ -21,9 +22,9 @@ pub struct User {
2122}
2223
2324impl GithubClient {
24- async fn _send_req ( & self , req : RequestBuilder ) -> anyhow:: Result < ( Response , String ) > {
25+ async fn send_req ( & self , req : RequestBuilder ) -> anyhow:: Result < ( Bytes , String ) > {
2526 const MAX_ATTEMPTS : usize = 2 ;
26- log:: debug!( "_send_req with {:?}" , req) ;
27+ log:: debug!( "send_req with {:?}" , req) ;
2728 let req_dbg = format ! ( "{:?}" , req) ;
2829 let req = req
2930 . build ( )
@@ -33,10 +34,17 @@ impl GithubClient {
3334 if let Some ( sleep) = Self :: needs_retry ( & resp) . await {
3435 resp = self . retry ( req, sleep, MAX_ATTEMPTS ) . await ?;
3536 }
37+ let maybe_err = resp. error_for_status_ref ( ) . err ( ) ;
38+ let body = resp
39+ . bytes ( )
40+ . await
41+ . with_context ( || format ! ( "failed to read response body {req_dbg}" ) ) ?;
42+ if let Some ( e) = maybe_err {
43+ return Err ( anyhow:: Error :: new ( e) )
44+ . with_context ( || format ! ( "response: {}" , String :: from_utf8_lossy( & body) ) ) ;
45+ }
3646
37- resp. error_for_status_ref ( ) ?;
38-
39- Ok ( ( resp, req_dbg) )
47+ Ok ( ( body, req_dbg) )
4048 }
4149
4250 async fn needs_retry ( resp : & Response ) -> Option < Duration > {
@@ -151,27 +159,12 @@ impl GithubClient {
151159 . boxed ( )
152160 }
153161
154- async fn send_req ( & self , req : RequestBuilder ) -> anyhow:: Result < Vec < u8 > > {
155- let ( mut resp, req_dbg) = self . _send_req ( req) . await ?;
156-
157- let mut body = Vec :: new ( ) ;
158- while let Some ( chunk) = resp. chunk ( ) . await . transpose ( ) {
159- let chunk = chunk
160- . context ( "reading stream failed" )
161- . map_err ( anyhow:: Error :: from)
162- . context ( req_dbg. clone ( ) ) ?;
163- body. extend_from_slice ( & chunk) ;
164- }
165-
166- Ok ( body)
167- }
168-
169162 pub async fn json < T > ( & self , req : RequestBuilder ) -> anyhow:: Result < T >
170163 where
171164 T : serde:: de:: DeserializeOwned ,
172165 {
173- let ( resp , req_dbg ) = self . _send_req ( req) . await ?;
174- Ok ( resp . json ( ) . await . context ( req_dbg ) ?)
166+ let ( body , _req_dbg ) = self . send_req ( req) . await ?;
167+ Ok ( serde_json :: from_slice ( & body ) ?)
175168 }
176169}
177170
@@ -412,8 +405,8 @@ impl IssueRepository {
412405 async fn has_label ( & self , client : & GithubClient , label : & str ) -> anyhow:: Result < bool > {
413406 #[ allow( clippy:: redundant_pattern_matching) ]
414407 let url = format ! ( "{}/labels/{}" , self . url( ) , label) ;
415- match client. _send_req ( client. get ( & url) ) . await {
416- Ok ( ( _ , _ ) ) => Ok ( true ) ,
408+ match client. send_req ( client. get ( & url) ) . await {
409+ Ok ( _ ) => Ok ( true ) ,
417410 Err ( e) => {
418411 if e. downcast_ref :: < reqwest:: Error > ( )
419412 . map_or ( false , |e| e. status ( ) == Some ( StatusCode :: NOT_FOUND ) )
@@ -493,7 +486,7 @@ impl Issue {
493486 body : & ' a str ,
494487 }
495488 client
496- . _send_req ( client. patch ( & edit_url) . json ( & ChangedIssue { body } ) )
489+ . send_req ( client. patch ( & edit_url) . json ( & ChangedIssue { body } ) )
497490 . await
498491 . context ( "failed to edit issue body" ) ?;
499492 Ok ( ( ) )
@@ -511,7 +504,7 @@ impl Issue {
511504 body : & ' a str ,
512505 }
513506 client
514- . _send_req (
507+ . send_req (
515508 client
516509 . patch ( & comment_url)
517510 . json ( & NewComment { body : new_body } ) ,
@@ -527,7 +520,7 @@ impl Issue {
527520 body : & ' a str ,
528521 }
529522 client
530- . _send_req ( client. post ( & self . comments_url ) . json ( & PostComment { body } ) )
523+ . send_req ( client. post ( & self . comments_url ) . json ( & PostComment { body } ) )
531524 . await
532525 . context ( "failed to post comment" ) ?;
533526 Ok ( ( ) )
@@ -553,7 +546,7 @@ impl Issue {
553546 }
554547
555548 client
556- . _send_req ( client. delete ( & url) )
549+ . send_req ( client. delete ( & url) )
557550 . await
558551 . context ( "failed to delete label" ) ?;
559552
@@ -610,7 +603,7 @@ impl Issue {
610603 }
611604
612605 client
613- . _send_req ( client. post ( & url) . json ( & LabelsReq {
606+ . send_req ( client. post ( & url) . json ( & LabelsReq {
614607 labels : known_labels,
615608 } ) )
616609 . await
@@ -661,7 +654,7 @@ impl Issue {
661654 assignees : & ' a [ & ' a str ] ,
662655 }
663656 client
664- . _send_req ( client. delete ( & url) . json ( & AssigneeReq {
657+ . send_req ( client. delete ( & url) . json ( & AssigneeReq {
665658 assignees : & assignees[ ..] ,
666659 } ) )
667660 . await
@@ -754,7 +747,7 @@ impl Issue {
754747 }
755748 let url = format ! ( "{}/issues/{}" , self . repository( ) . url( ) , self . number) ;
756749 client
757- . _send_req ( client. patch ( & url) . json ( & SetMilestone {
750+ . send_req ( client. patch ( & url) . json ( & SetMilestone {
758751 milestone : milestone_no,
759752 } ) )
760753 . await
@@ -769,7 +762,7 @@ impl Issue {
769762 state : & ' a str ,
770763 }
771764 client
772- . _send_req (
765+ . send_req (
773766 client
774767 . patch ( & edit_url)
775768 . json ( & CloseIssue { state : "closed" } ) ,
@@ -794,8 +787,9 @@ impl Issue {
794787 after
795788 ) ) ;
796789 req = req. header ( "Accept" , "application/vnd.github.v3.diff" ) ;
797- let diff = client. send_req ( req) . await ?;
798- Ok ( Some ( String :: from ( String :: from_utf8_lossy ( & diff) ) ) )
790+ let ( diff, _) = client. send_req ( req) . await ?;
791+ let body = String :: from_utf8_lossy ( & diff) . to_string ( ) ;
792+ Ok ( Some ( body) )
799793 }
800794
801795 /// Returns the commits from this pull request (no commits are returned if this `Issue` is not
@@ -1235,7 +1229,7 @@ impl Repository {
12351229 ) -> anyhow:: Result < ( ) > {
12361230 let url = format ! ( "{}/git/refs/{}" , self . url( ) , refname) ;
12371231 client
1238- . _send_req ( client. patch ( & url) . json ( & serde_json:: json!( {
1232+ . json ( client. patch ( & url) . json ( & serde_json:: json!( {
12391233 "sha" : sha,
12401234 "force" : true ,
12411235 } ) ) )
@@ -1494,7 +1488,7 @@ impl Repository {
14941488 pub async fn merge_upstream ( & self , client : & GithubClient , branch : & str ) -> anyhow:: Result < ( ) > {
14951489 let url = format ! ( "{}/merge-upstream" , self . url( ) ) ;
14961490 client
1497- . _send_req ( client. post ( & url) . json ( & serde_json:: json!( {
1491+ . send_req ( client. post ( & url) . json ( & serde_json:: json!( {
14981492 "branch" : branch,
14991493 } ) ) )
15001494 . await
@@ -1783,7 +1777,7 @@ impl GithubClient {
17831777 repo : & str ,
17841778 branch : & str ,
17851779 path : & str ,
1786- ) -> anyhow:: Result < Option < Vec < u8 > > > {
1780+ ) -> anyhow:: Result < Option < Bytes > > {
17871781 let url = format ! (
17881782 "https://raw.githubusercontent.com/{}/{}/{}" ,
17891783 repo, branch, path
@@ -1793,20 +1787,14 @@ impl GithubClient {
17931787 let req = req
17941788 . build ( )
17951789 . with_context ( || format ! ( "failed to build request {:?}" , req_dbg) ) ?;
1796- let mut resp = self . client . execute ( req) . await . context ( req_dbg. clone ( ) ) ?;
1790+ let resp = self . client . execute ( req) . await . context ( req_dbg. clone ( ) ) ?;
17971791 let status = resp. status ( ) ;
1792+ let body = resp
1793+ . bytes ( )
1794+ . await
1795+ . with_context ( || format ! ( "failed to read response body {req_dbg}" ) ) ?;
17981796 match status {
1799- StatusCode :: OK => {
1800- let mut buf = Vec :: with_capacity ( resp. content_length ( ) . unwrap_or ( 4 ) as usize ) ;
1801- while let Some ( chunk) = resp. chunk ( ) . await . transpose ( ) {
1802- let chunk = chunk
1803- . context ( "reading stream failed" )
1804- . map_err ( anyhow:: Error :: from)
1805- . context ( req_dbg. clone ( ) ) ?;
1806- buf. extend_from_slice ( & chunk) ;
1807- }
1808- Ok ( Some ( buf) )
1809- }
1797+ StatusCode :: OK => Ok ( Some ( body) ) ,
18101798 StatusCode :: NOT_FOUND => Ok ( None ) ,
18111799 status => anyhow:: bail!( "failed to GET {}: {}" , url, status) ,
18121800 }
@@ -2010,11 +1998,8 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests {
20101998 let req = client. post ( Repository :: GITHUB_GRAPHQL_API_URL ) ;
20111999 let req = req. json ( & query) ;
20122000
2013- let ( resp, req_dbg) = client. _send_req ( req) . await ?;
2014- let data = resp
2015- . json :: < cynic:: GraphQlResponse < queries:: LeastRecentlyReviewedPullRequests > > ( )
2016- . await
2017- . context ( req_dbg) ?;
2001+ let data: cynic:: GraphQlResponse < queries:: LeastRecentlyReviewedPullRequests > =
2002+ client. json ( req) . await ?;
20182003 if let Some ( errors) = data. errors {
20192004 anyhow:: bail!( "There were graphql errors. {:?}" , errors) ;
20202005 }
@@ -2147,11 +2132,7 @@ async fn project_items_by_status(
21472132 let req = client. post ( Repository :: GITHUB_GRAPHQL_API_URL ) ;
21482133 let req = req. json ( & query) ;
21492134
2150- let ( resp, req_dbg) = client. _send_req ( req) . await ?;
2151- let data = resp
2152- . json :: < cynic:: GraphQlResponse < project_items_by_status:: Query > > ( )
2153- . await
2154- . context ( req_dbg) ?;
2135+ let data: cynic:: GraphQlResponse < project_items_by_status:: Query > = client. json ( req) . await ?;
21552136 if let Some ( errors) = data. errors {
21562137 anyhow:: bail!( "There were graphql errors. {:?}" , errors) ;
21572138 }
0 commit comments