1+ use  crate :: test_record; 
12use  anyhow:: Context ; 
23use  async_trait:: async_trait; 
4+ use  bytes:: Bytes ; 
35use  chrono:: { DateTime ,  FixedOffset ,  Utc } ; 
46use  futures:: { future:: BoxFuture ,  FutureExt } ; 
57use  hyper:: header:: HeaderValue ; 
@@ -21,22 +23,32 @@ pub struct User {
2123} 
2224
2325impl  GithubClient  { 
24-     async  fn  _send_req ( & self ,  req :  RequestBuilder )  -> anyhow:: Result < ( Response ,  String ) >  { 
26+     async  fn  send_req ( & self ,  req :  RequestBuilder )  -> anyhow:: Result < ( Bytes ,  String ) >  { 
2527        const  MAX_ATTEMPTS :  usize  = 2 ; 
26-         log:: debug!( "_send_req  with {:?}" ,  req) ; 
28+         log:: debug!( "send_req  with {:?}" ,  req) ; 
2729        let  req_dbg = format ! ( "{:?}" ,  req) ; 
2830        let  req = req
2931            . build ( ) 
3032            . with_context ( || format ! ( "building reqwest {}" ,  req_dbg) ) ?; 
3133
34+         let  test_capture_info = test_record:: capture_request ( & req) ; 
35+ 
3236        let  mut  resp = self . client . execute ( req. try_clone ( ) . unwrap ( ) ) . await ?; 
3337        if  let  Some ( sleep)  = Self :: needs_retry ( & resp) . await  { 
3438            resp = self . retry ( req,  sleep,  MAX_ATTEMPTS ) . await ?; 
3539        } 
40+         let  status = resp. status ( ) ; 
41+         let  maybe_err = resp. error_for_status_ref ( ) . err ( ) ; 
42+         let  body = resp
43+             . bytes ( ) 
44+             . await 
45+             . with_context ( || format ! ( "failed to read response body {req_dbg}" ) ) ?; 
46+         test_record:: record_request ( test_capture_info,  status,  & body) ; 
47+         if  let  Some ( e)  = maybe_err { 
48+             return  Err ( e. into ( ) ) ; 
49+         } 
3650
37-         resp. error_for_status_ref ( ) ?; 
38- 
39-         Ok ( ( resp,  req_dbg) ) 
51+         Ok ( ( body,  req_dbg) ) 
4052    } 
4153
4254    async  fn  needs_retry ( resp :  & Response )  -> Option < Duration >  { 
@@ -116,6 +128,7 @@ impl GithubClient {
116128                        . unwrap ( ) , 
117129                ) 
118130                . await ?; 
131+             rate_resp. error_for_status_ref ( ) ?; 
119132            let  rate_limit_response = rate_resp. json :: < RateLimitResponse > ( ) . await ?; 
120133
121134            // Check url for search path because github has different rate limits for the search api 
@@ -151,27 +164,12 @@ impl GithubClient {
151164        . boxed ( ) 
152165    } 
153166
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- 
169167    pub  async  fn  json < T > ( & self ,  req :  RequestBuilder )  -> anyhow:: Result < T > 
170168    where 
171169        T :  serde:: de:: DeserializeOwned , 
172170    { 
173-         let  ( resp ,  req_dbg )  = self . _send_req ( req) . await ?; 
174-         Ok ( resp . json ( ) . await . context ( req_dbg ) ?) 
171+         let  ( body ,  _req_dbg )  = self . send_req ( req) . await ?; 
172+         Ok ( serde_json :: from_slice ( & body ) ?) 
175173    } 
176174} 
177175
@@ -414,8 +412,8 @@ impl IssueRepository {
414412    async  fn  has_label ( & self ,  client :  & GithubClient ,  label :  & str )  -> anyhow:: Result < bool >  { 
415413        #[ allow( clippy:: redundant_pattern_matching) ]  
416414        let  url = format ! ( "{}/labels/{}" ,  self . url( client) ,  label) ; 
417-         match  client. _send_req ( client. get ( & url) ) . await  { 
418-             Ok ( ( _ ,  _ ) )  => Ok ( true ) , 
415+         match  client. send_req ( client. get ( & url) ) . await  { 
416+             Ok ( _ )  => Ok ( true ) , 
419417            Err ( e)  => { 
420418                if  e. downcast_ref :: < reqwest:: Error > ( ) 
421419                    . map_or ( false ,  |e| e. status ( )  == Some ( StatusCode :: NOT_FOUND ) ) 
@@ -495,7 +493,7 @@ impl Issue {
495493            body :  & ' a  str , 
496494        } 
497495        client
498-             . _send_req ( client. patch ( & edit_url) . json ( & ChangedIssue  {  body } ) ) 
496+             . send_req ( client. patch ( & edit_url) . json ( & ChangedIssue  {  body } ) ) 
499497            . await 
500498            . context ( "failed to edit issue body" ) ?; 
501499        Ok ( ( ) ) 
@@ -513,7 +511,7 @@ impl Issue {
513511            body :  & ' a  str , 
514512        } 
515513        client
516-             . _send_req ( 
514+             . send_req ( 
517515                client
518516                    . patch ( & comment_url) 
519517                    . json ( & NewComment  {  body :  new_body } ) , 
@@ -534,7 +532,7 @@ impl Issue {
534532            . expect ( "expected api host" ) ; 
535533        let  comments_url = format ! ( "{}{comments_path}" ,  client. api_url) ; 
536534        client
537-             . _send_req ( client. post ( & comments_url) . json ( & PostComment  {  body } ) ) 
535+             . send_req ( client. post ( & comments_url) . json ( & PostComment  {  body } ) ) 
538536            . await 
539537            . context ( "failed to post comment" ) ?; 
540538        Ok ( ( ) ) 
@@ -560,7 +558,7 @@ impl Issue {
560558        } 
561559
562560        client
563-             . _send_req ( client. delete ( & url) ) 
561+             . send_req ( client. delete ( & url) ) 
564562            . await 
565563            . context ( "failed to delete label" ) ?; 
566564
@@ -617,7 +615,7 @@ impl Issue {
617615        } 
618616
619617        client
620-             . _send_req ( client. post ( & url) . json ( & LabelsReq  { 
618+             . send_req ( client. post ( & url) . json ( & LabelsReq  { 
621619                labels :  known_labels, 
622620            } ) ) 
623621            . await 
@@ -668,7 +666,7 @@ impl Issue {
668666            assignees :  & ' a  [ & ' a  str ] , 
669667        } 
670668        client
671-             . _send_req ( client. delete ( & url) . json ( & AssigneeReq  { 
669+             . send_req ( client. delete ( & url) . json ( & AssigneeReq  { 
672670                assignees :  & assignees[ ..] , 
673671            } ) ) 
674672            . await 
@@ -761,7 +759,7 @@ impl Issue {
761759        } 
762760        let  url = format ! ( "{}/issues/{}" ,  self . repository( ) . url( client) ,  self . number) ; 
763761        client
764-             . _send_req ( client. patch ( & url) . json ( & SetMilestone  { 
762+             . send_req ( client. patch ( & url) . json ( & SetMilestone  { 
765763                milestone :  milestone_no, 
766764            } ) ) 
767765            . await 
@@ -776,7 +774,7 @@ impl Issue {
776774            state :  & ' a  str , 
777775        } 
778776        client
779-             . _send_req ( 
777+             . send_req ( 
780778                client
781779                    . patch ( & edit_url) 
782780                    . json ( & CloseIssue  {  state :  "closed"  } ) , 
@@ -801,8 +799,9 @@ impl Issue {
801799            after
802800        ) ) ; 
803801        req = req. header ( "Accept" ,  "application/vnd.github.v3.diff" ) ; 
804-         let  diff = client. send_req ( req) . await ?; 
805-         Ok ( Some ( String :: from ( String :: from_utf8_lossy ( & diff) ) ) ) 
802+         let  ( diff,  _)  = client. send_req ( req) . await ?; 
803+         let  body = String :: from_utf8_lossy ( & diff) . to_string ( ) ; 
804+         Ok ( Some ( body) ) 
806805    } 
807806
808807    /// Returns the commits from this pull request (no commits are returned if this `Issue` is not 
@@ -1246,7 +1245,7 @@ impl Repository {
12461245    )  -> anyhow:: Result < ( ) >  { 
12471246        let  url = format ! ( "{}/git/refs/{}" ,  self . url( client) ,  refname) ; 
12481247        client
1249-             . _send_req ( client. patch ( & url) . json ( & serde_json:: json!( { 
1248+             . send_req ( client. patch ( & url) . json ( & serde_json:: json!( { 
12501249                "sha" :  sha, 
12511250                "force" :  true , 
12521251            } ) ) ) 
@@ -1505,7 +1504,7 @@ impl Repository {
15051504pub  async  fn  merge_upstream ( & self ,  client :  & GithubClient ,  branch :  & str )  -> anyhow:: Result < ( ) >  { 
15061505        let  url = format ! ( "{}/merge-upstream" ,  self . url( client) ) ; 
15071506        client
1508-             . _send_req ( client. post ( & url) . json ( & serde_json:: json!( { 
1507+             . send_req ( client. post ( & url) . json ( & serde_json:: json!( { 
15091508                "branch" :  branch, 
15101509            } ) ) ) 
15111510            . await 
@@ -1811,27 +1810,23 @@ impl GithubClient {
18111810        repo :  & str , 
18121811        branch :  & str , 
18131812        path :  & str , 
1814-     )  -> anyhow:: Result < Option < Vec < u8 > > >  { 
1813+     )  -> anyhow:: Result < Option < Bytes > >  { 
18151814        let  url = format ! ( "{}/{repo}/{branch}/{path}" ,  self . raw_url) ; 
18161815        let  req = self . get ( & url) ; 
18171816        let  req_dbg = format ! ( "{:?}" ,  req) ; 
18181817        let  req = req
18191818            . build ( ) 
18201819            . with_context ( || format ! ( "failed to build request {:?}" ,  req_dbg) ) ?; 
1821-         let  mut  resp = self . client . execute ( req) . await . context ( req_dbg. clone ( ) ) ?; 
1820+         let  test_capture_info = test_record:: capture_request ( & req) ; 
1821+         let  resp = self . client . execute ( req) . await . context ( req_dbg. clone ( ) ) ?; 
18221822        let  status = resp. status ( ) ; 
1823+         let  body = resp
1824+             . bytes ( ) 
1825+             . await 
1826+             . with_context ( || format ! ( "failed to read response body {req_dbg}" ) ) ?; 
1827+         test_record:: record_request ( test_capture_info,  status,  & body) ; 
18231828        match  status { 
1824-             StatusCode :: OK  => { 
1825-                 let  mut  buf = Vec :: with_capacity ( resp. content_length ( ) . unwrap_or ( 4 )  as  usize ) ; 
1826-                 while  let  Some ( chunk)  = resp. chunk ( ) . await . transpose ( )  { 
1827-                     let  chunk = chunk
1828-                         . context ( "reading stream failed" ) 
1829-                         . map_err ( anyhow:: Error :: from) 
1830-                         . context ( req_dbg. clone ( ) ) ?; 
1831-                     buf. extend_from_slice ( & chunk) ; 
1832-                 } 
1833-                 Ok ( Some ( buf) ) 
1834-             } 
1829+             StatusCode :: OK  => Ok ( Some ( body) ) , 
18351830            StatusCode :: NOT_FOUND  => Ok ( None ) , 
18361831            status => anyhow:: bail!( "failed to GET {}: {}" ,  url,  status) , 
18371832        } 
@@ -2036,11 +2031,8 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests {
20362031            let  req = client. post ( & format ! ( "{}/graphql" ,  client. api_url) ) ; 
20372032            let  req = req. json ( & query) ; 
20382033
2039-             let  ( resp,  req_dbg)  = client. _send_req ( req) . await ?; 
2040-             let  data = resp
2041-                 . json :: < cynic:: GraphQlResponse < queries:: LeastRecentlyReviewedPullRequests > > ( ) 
2042-                 . await 
2043-                 . context ( req_dbg) ?; 
2034+             let  data:  cynic:: GraphQlResponse < queries:: LeastRecentlyReviewedPullRequests >  =
2035+                 client. json ( req) . await ?; 
20442036            if  let  Some ( errors)  = data. errors  { 
20452037                anyhow:: bail!( "There were graphql errors. {:?}" ,  errors) ; 
20462038            } 
0 commit comments