@@ -537,6 +537,56 @@ func TestRepositoriesService_DownloadReleaseAsset_FollowRedirectToError(t *testi
537537 }
538538}
539539
540+ // CheckResponse substitutes resp.Body with a re-readable copy on error
541+ // responses; downloadReleaseAssetFromURL must still close the original body it
542+ // replaces. Unlike its sibling tests, the recorder wraps the follow-redirects
543+ // client's transport: that client, not the library client, performs the
544+ // redirected request, so wrapping the library client would only ever observe
545+ // the first hop's correctly-closed redirect response and never the leak.
546+ func TestRepositoriesService_DownloadReleaseAsset_FollowRedirectToErrorClosesOriginalBody (t * testing.T ) {
547+ t .Parallel ()
548+ client , mux , _ := setup (t )
549+
550+ mux .HandleFunc ("/repos/o/r/releases/assets/1" , func (w http.ResponseWriter , r * http.Request ) {
551+ testMethod (t , r , "GET" )
552+ testHeader (t , r , "Accept" , defaultMediaType )
553+ // /yo, below will be served as baseURLPath/yo
554+ http .Redirect (w , r , baseURLPath + "/yo" , http .StatusFound )
555+ })
556+ mux .HandleFunc ("/yo" , func (w http.ResponseWriter , r * http.Request ) {
557+ testMethod (t , r , "GET" )
558+ testHeader (t , r , "Accept" , defaultMediaType )
559+ http .Error (w , `{"message":"Not Found"}` , 404 )
560+ })
561+
562+ var closed bool
563+ followRedirectsClient := & http.Client {
564+ Transport : roundTripperFunc (func (req * http.Request ) (* http.Response , error ) {
565+ resp , err := http .DefaultTransport .RoundTrip (req )
566+ if resp != nil {
567+ resp .Body = & closeRecorder {ReadCloser : resp .Body , closed : & closed }
568+ }
569+ return resp , err
570+ }),
571+ }
572+
573+ ctx := t .Context ()
574+ rc , loc , err := client .Repositories .DownloadReleaseAsset (ctx , "o" , "r" , 1 , followRedirectsClient )
575+ if err == nil {
576+ t .Error ("Repositories.DownloadReleaseAsset did not return an error" )
577+ }
578+ if rc != nil {
579+ rc .Close ()
580+ t .Error ("Repositories.DownloadReleaseAsset returned stream, want nil" )
581+ }
582+ if loc != "" {
583+ t .Errorf (`Repositories.DownloadReleaseAsset returned "%v", want empty ""` , loc )
584+ }
585+ if ! closed {
586+ t .Error ("original response body was not closed on an error response" )
587+ }
588+ }
589+
540590func TestRepositoriesService_DownloadReleaseAsset_APIError (t * testing.T ) {
541591 t .Parallel ()
542592 client , mux , _ := setup (t )
0 commit comments