Skip to content

Commit 1e16435

Browse files
handle resource leaks (#399)
Co-authored-by: Benji Vesterby <[email protected]>
1 parent 13da37b commit 1e16435

File tree

12 files changed

+63
-10
lines changed

12 files changed

+63
-10
lines changed

authentication.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ func (s *AuthenticationService) LogoutWithContext(ctx context.Context) error {
142142
if err != nil {
143143
return fmt.Errorf("error sending the logout request: %s", err)
144144
}
145+
defer resp.Body.Close()
145146
if resp.StatusCode != 204 {
146147
return fmt.Errorf("the logout was unsuccessful with status %d", resp.StatusCode)
147148
}
@@ -182,11 +183,10 @@ func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (
182183
if err != nil {
183184
return nil, fmt.Errorf("error sending request to get user info : %s", err)
184185
}
186+
defer resp.Body.Close()
185187
if resp.StatusCode != 200 {
186188
return nil, fmt.Errorf("getting user info failed with status : %d", resp.StatusCode)
187189
}
188-
189-
defer resp.Body.Close()
190190
ret := new(Session)
191191
data, err := ioutil.ReadAll(resp.Body)
192192
if err != nil {

board.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) {
215215
// DeleteBoardWithContext will delete an agile board.
216216
//
217217
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard
218+
// Caller must close resp.Body
218219
func (s *BoardService) DeleteBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) {
219220
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
220221
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@@ -230,6 +231,7 @@ func (s *BoardService) DeleteBoardWithContext(ctx context.Context, boardID int)
230231
}
231232

232233
// DeleteBoard wraps DeleteBoardWithContext using the background context.
234+
// Caller must close resp.Body
233235
func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
234236
return s.DeleteBoardWithContext(context.Background(), boardID)
235237
}

examples/do/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ func main() {
1111
req, _ := jiraClient.NewRequest("GET", "/rest/api/2/project", nil)
1212

1313
projects := new([]jira.Project)
14-
_, err := jiraClient.Do(req, projects)
14+
res, err := jiraClient.Do(req, projects)
1515
if err != nil {
1616
panic(err)
1717
}
18+
defer res.Body.Close()
1819

1920
for _, project := range *projects {
2021
fmt.Printf("%s: %s\n", project.Key, project.Name)

group.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ func (s *GroupService) Add(groupname string, username string) (*Group, *Response
155155
// RemoveWithContext removes user from group
156156
//
157157
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup
158+
// Caller must close resp.Body
158159
func (s *GroupService) RemoveWithContext(ctx context.Context, groupname string, username string) (*Response, error) {
159160
apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s&username=%s", groupname, username)
160161
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@@ -172,6 +173,7 @@ func (s *GroupService) RemoveWithContext(ctx context.Context, groupname string,
172173
}
173174

174175
// Remove wraps RemoveWithContext using the background context.
176+
// Caller must close resp.Body
175177
func (s *GroupService) Remove(groupname string, username string) (*Response, error) {
176178
return s.RemoveWithContext(context.Background(), groupname, username)
177179
}

issue.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ func (s *IssueService) Get(issueID string, options *GetQueryOptions) (*Issue, *R
649649
// DownloadAttachmentWithContext returns a Response of an attachment for a given attachmentID.
650650
// The attachment is in the Response.Body of the response.
651651
// This is an io.ReadCloser.
652-
// The caller should close the resp.Body.
652+
// Caller must close resp.Body.
653653
func (s *IssueService) DownloadAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) {
654654
apiEndpoint := fmt.Sprintf("secure/attachment/%s/", attachmentID)
655655
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
@@ -667,6 +667,7 @@ func (s *IssueService) DownloadAttachmentWithContext(ctx context.Context, attach
667667
}
668668

669669
// DownloadAttachment wraps DownloadAttachmentWithContext using the background context.
670+
// Caller must close resp.Body
670671
func (s *IssueService) DownloadAttachment(attachmentID string) (*Response, error) {
671672
return s.DownloadAttachmentWithContext(context.Background(), attachmentID)
672673
}
@@ -715,6 +716,7 @@ func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentNam
715716
}
716717

717718
// DeleteAttachmentWithContext deletes an attachment of a given attachmentID
719+
// Caller must close resp.Body
718720
func (s *IssueService) DeleteAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) {
719721
apiEndpoint := fmt.Sprintf("rest/api/2/attachment/%s", attachmentID)
720722

@@ -733,11 +735,13 @@ func (s *IssueService) DeleteAttachmentWithContext(ctx context.Context, attachme
733735
}
734736

735737
// DeleteAttachment wraps DeleteAttachmentWithContext using the background context.
738+
// Caller must close resp.Body
736739
func (s *IssueService) DeleteAttachment(attachmentID string) (*Response, error) {
737740
return s.DeleteAttachmentWithContext(context.Background(), attachmentID)
738741
}
739742

740743
// DeleteLinkWithContext deletes a link of a given linkID
744+
// Caller must close resp.Body
741745
func (s *IssueService) DeleteLinkWithContext(ctx context.Context, linkID string) (*Response, error) {
742746
apiEndpoint := fmt.Sprintf("rest/api/2/issueLink/%s", linkID)
743747

@@ -756,6 +760,7 @@ func (s *IssueService) DeleteLinkWithContext(ctx context.Context, linkID string)
756760
}
757761

758762
// DeleteLink wraps DeleteLinkWithContext using the background context.
763+
// Caller must close resp.Body
759764
func (s *IssueService) DeleteLink(linkID string) (*Response, error) {
760765
return s.DeleteLinkWithContext(context.Background(), linkID)
761766
}
@@ -844,6 +849,7 @@ func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) {
844849
// while also specifying query params. The issue is found by key.
845850
//
846851
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue
852+
// Caller must close resp.Body
847853
func (s *IssueService) UpdateWithOptionsWithContext(ctx context.Context, issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) {
848854
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", issue.Key)
849855
url, err := addOptions(apiEndpoint, opts)
@@ -867,6 +873,7 @@ func (s *IssueService) UpdateWithOptionsWithContext(ctx context.Context, issue *
867873
}
868874

869875
// UpdateWithOptions wraps UpdateWithOptionsWithContext using the background context.
876+
// Caller must close resp.Body
870877
func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) {
871878
return s.UpdateWithOptionsWithContext(context.Background(), issue, opts)
872879
}
@@ -886,6 +893,7 @@ func (s *IssueService) Update(issue *Issue) (*Issue, *Response, error) {
886893
// UpdateIssueWithContext updates an issue from a JSON representation. The issue is found by key.
887894
//
888895
// https://docs.atlassian.com/jira/REST/7.4.0/#api/2/issue-editIssue
896+
// Caller must close resp.Body
889897
func (s *IssueService) UpdateIssueWithContext(ctx context.Context, jiraID string, data map[string]interface{}) (*Response, error) {
890898
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", jiraID)
891899
req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, data)
@@ -903,6 +911,7 @@ func (s *IssueService) UpdateIssueWithContext(ctx context.Context, jiraID string
903911
}
904912

905913
// UpdateIssue wraps UpdateIssueWithContext using the background context.
914+
// Caller must close resp.Body
906915
func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (*Response, error) {
907916
return s.UpdateIssueWithContext(context.Background(), jiraID, data)
908917
}
@@ -976,6 +985,7 @@ func (s *IssueService) DeleteCommentWithContext(ctx context.Context, issueID, co
976985
jerr := NewJiraError(resp, err)
977986
return jerr
978987
}
988+
defer resp.Body.Close()
979989

980990
return nil
981991
}
@@ -1052,6 +1062,7 @@ func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *Wo
10521062
// AddLinkWithContext adds a link between two issues.
10531063
//
10541064
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issueLink
1065+
// Caller must close resp.Body
10551066
func (s *IssueService) AddLinkWithContext(ctx context.Context, issueLink *IssueLink) (*Response, error) {
10561067
apiEndpoint := "rest/api/2/issueLink"
10571068
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issueLink)
@@ -1068,6 +1079,7 @@ func (s *IssueService) AddLinkWithContext(ctx context.Context, issueLink *IssueL
10681079
}
10691080

10701081
// AddLink wraps AddLinkWithContext using the background context.
1082+
// Caller must close resp.Body
10711083
func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) {
10721084
return s.AddLinkWithContext(context.Background(), issueLink)
10731085
}
@@ -1259,6 +1271,7 @@ func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, e
12591271
// When performing the transition you can update or set other issue fields.
12601272
//
12611273
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
1274+
// Caller must close resp.Body
12621275
func (s *IssueService) DoTransitionWithPayloadWithContext(ctx context.Context, ticketID, payload interface{}) (*Response, error) {
12631276
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID)
12641277

@@ -1276,6 +1289,7 @@ func (s *IssueService) DoTransitionWithPayloadWithContext(ctx context.Context, t
12761289
}
12771290

12781291
// DoTransitionWithPayload wraps DoTransitionWithPayloadWithContext using the background context.
1292+
// Caller must close resp.Body
12791293
func (s *IssueService) DoTransitionWithPayload(ticketID, payload interface{}) (*Response, error) {
12801294
return s.DoTransitionWithPayloadWithContext(context.Background(), ticketID, payload)
12811295
}
@@ -1360,6 +1374,7 @@ func InitIssueWithMetaAndFields(metaProject *MetaProject, metaIssuetype *MetaIss
13601374
}
13611375

13621376
// DeleteWithContext will delete a specified issue.
1377+
// Caller must close resp.Body
13631378
func (s *IssueService) DeleteWithContext(ctx context.Context, issueID string) (*Response, error) {
13641379
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID)
13651380

@@ -1378,6 +1393,7 @@ func (s *IssueService) DeleteWithContext(ctx context.Context, issueID string) (*
13781393
}
13791394

13801395
// Delete wraps DeleteWithContext using the background context.
1396+
// Caller must close resp.Body
13811397
func (s *IssueService) Delete(issueID string) (*Response, error) {
13821398
return s.DeleteWithContext(context.Background(), issueID)
13831399
}
@@ -1422,6 +1438,7 @@ func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) {
14221438
// AddWatcherWithContext adds watcher to the given issue
14231439
//
14241440
// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-addWatcher
1441+
// Caller must close resp.Body
14251442
func (s *IssueService) AddWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) {
14261443
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID)
14271444

@@ -1439,13 +1456,15 @@ func (s *IssueService) AddWatcherWithContext(ctx context.Context, issueID string
14391456
}
14401457

14411458
// AddWatcher wraps AddWatcherWithContext using the background context.
1459+
// Caller must close resp.Body
14421460
func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, error) {
14431461
return s.AddWatcherWithContext(context.Background(), issueID, userName)
14441462
}
14451463

14461464
// RemoveWatcherWithContext removes given user from given issue
14471465
//
14481466
// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-removeWatcher
1467+
// Caller must close resp.Body
14491468
func (s *IssueService) RemoveWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) {
14501469
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID)
14511470

@@ -1463,13 +1482,15 @@ func (s *IssueService) RemoveWatcherWithContext(ctx context.Context, issueID str
14631482
}
14641483

14651484
// RemoveWatcher wraps RemoveWatcherWithContext using the background context.
1485+
// Caller must close resp.Body
14661486
func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response, error) {
14671487
return s.RemoveWatcherWithContext(context.Background(), issueID, userName)
14681488
}
14691489

14701490
// UpdateAssigneeWithContext updates the user assigned to work on the given issue
14711491
//
14721492
// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.2/#api/2/issue-assign
1493+
// Caller must close resp.Body
14731494
func (s *IssueService) UpdateAssigneeWithContext(ctx context.Context, issueID string, assignee *User) (*Response, error) {
14741495
apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/assignee", issueID)
14751496

@@ -1487,6 +1508,7 @@ func (s *IssueService) UpdateAssigneeWithContext(ctx context.Context, issueID st
14871508
}
14881509

14891510
// UpdateAssignee wraps UpdateAssigneeWithContext using the background context.
1511+
// Caller must close resp.Body
14901512
func (s *IssueService) UpdateAssignee(issueID string, assignee *User) (*Response, error) {
14911513
return s.UpdateAssigneeWithContext(context.Background(), issueID, assignee)
14921514
}
@@ -1520,6 +1542,7 @@ func (s *IssueService) GetRemoteLinksWithContext(ctx context.Context, id string)
15201542
}
15211543

15221544
// GetRemoteLinks wraps GetRemoteLinksWithContext using the background context.
1545+
// Caller must close resp.Body
15231546
func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, error) {
15241547
return s.GetRemoteLinksWithContext(context.Background(), id)
15251548
}

issuelinktype.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType,
9898
// UpdateWithContext updates an issue link type. The issue is found by key.
9999
//
100100
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put
101+
// Caller must close resp.Body
101102
func (s *IssueLinkTypeService) UpdateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
102103
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID)
103104
req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType)
@@ -113,13 +114,15 @@ func (s *IssueLinkTypeService) UpdateWithContext(ctx context.Context, linkType *
113114
}
114115

115116
// Update wraps UpdateWithContext using the background context.
117+
// Caller must close resp.Body
116118
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
117119
return s.UpdateWithContext(context.Background(), linkType)
118120
}
119121

120122
// DeleteWithContext deletes an issue link type based on provided ID.
121123
//
122124
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete
125+
// Caller must close resp.Body
123126
func (s *IssueLinkTypeService) DeleteWithContext(ctx context.Context, ID string) (*Response, error) {
124127
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
125128
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
@@ -132,6 +135,7 @@ func (s *IssueLinkTypeService) DeleteWithContext(ctx context.Context, ID string)
132135
}
133136

134137
// Delete wraps DeleteWithContext using the background context.
138+
// Caller must close resp.Body
135139
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
136140
return s.DeleteWithContext(context.Background(), ID)
137141
}

jira.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ func (t *CookieAuthTransport) setSessionObject() error {
519519
if err != nil {
520520
return err
521521
}
522+
defer resp.Body.Close()
522523

523524
t.SessionObject = resp.Cookies()
524525
return nil

organization.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ func (s *OrganizationService) GetOrganization(organizationID int) (*Organization
161161
// For example, associations with service desks.
162162
//
163163
// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-delete
164+
// Caller must close resp.Body
164165
func (s *OrganizationService) DeleteOrganizationWithContext(ctx context.Context, organizationID int) (*Response, error) {
165166
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d", organizationID)
166167

@@ -180,6 +181,7 @@ func (s *OrganizationService) DeleteOrganizationWithContext(ctx context.Context,
180181
}
181182

182183
// DeleteOrganization wraps DeleteOrganizationWithContext using the background context.
184+
// Caller must close resp.Body
183185
func (s *OrganizationService) DeleteOrganization(organizationID int) (*Response, error) {
184186
return s.DeleteOrganizationWithContext(context.Background(), organizationID)
185187
}
@@ -250,6 +252,7 @@ func (s *OrganizationService) GetProperty(organizationID int, propertyKey string
250252
// resource to store custom data against an organization.
251253
//
252254
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-put
255+
// Caller must close resp.Body
253256
func (s *OrganizationService) SetPropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) {
254257
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey)
255258

@@ -270,13 +273,15 @@ func (s *OrganizationService) SetPropertyWithContext(ctx context.Context, organi
270273
}
271274

272275
// SetProperty wraps SetPropertyWithContext using the background context.
276+
// Caller must close resp.Body
273277
func (s *OrganizationService) SetProperty(organizationID int, propertyKey string) (*Response, error) {
274278
return s.SetPropertyWithContext(context.Background(), organizationID, propertyKey)
275279
}
276280

277281
// DeletePropertyWithContext removes a property from an organization.
278282
//
279283
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-delete
284+
// Caller must close resp.Body
280285
func (s *OrganizationService) DeletePropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) {
281286
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey)
282287

@@ -297,6 +302,7 @@ func (s *OrganizationService) DeletePropertyWithContext(ctx context.Context, org
297302
}
298303

299304
// DeleteProperty wraps DeletePropertyWithContext using the background context.
305+
// Caller must close resp.Body
300306
func (s *OrganizationService) DeleteProperty(organizationID int, propertyKey string) (*Response, error) {
301307
return s.DeletePropertyWithContext(context.Background(), organizationID, propertyKey)
302308
}
@@ -336,6 +342,7 @@ func (s *OrganizationService) GetUsers(organizationID int, start int, limit int)
336342
// AddUsersWithContext adds users to an organization.
337343
//
338344
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-post
345+
// Caller must close resp.Body
339346
func (s *OrganizationService) AddUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) {
340347
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID)
341348

@@ -355,13 +362,15 @@ func (s *OrganizationService) AddUsersWithContext(ctx context.Context, organizat
355362
}
356363

357364
// AddUsers wraps AddUsersWithContext using the background context.
365+
// Caller must close resp.Body
358366
func (s *OrganizationService) AddUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) {
359367
return s.AddUsersWithContext(context.Background(), organizationID, users)
360368
}
361369

362370
// RemoveUsersWithContext removes users from an organization.
363371
//
364372
// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-delete
373+
// Caller must close resp.Body
365374
func (s *OrganizationService) RemoveUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) {
366375
apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID)
367376

@@ -382,6 +391,7 @@ func (s *OrganizationService) RemoveUsersWithContext(ctx context.Context, organi
382391
}
383392

384393
// RemoveUsers wraps RemoveUsersWithContext using the background context.
394+
// Caller must close resp.Body
385395
func (s *OrganizationService) RemoveUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) {
386396
return s.RemoveUsersWithContext(context.Background(), organizationID, users)
387397
}

0 commit comments

Comments
 (0)