Skip to content

Commit 9bccb84

Browse files
cryo-zd王荣昌
authored andcommitted
fix(client): resource leak in SSEClient.SendRequest() (mark3labs#206)
* refact SSEClient's SendRequest for resource leak * correct comments
1 parent d9d109f commit 9bccb84

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

client/transport/sse.go

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -243,53 +243,54 @@ func (c *SSE) SendRequest(
243243
return nil, fmt.Errorf("endpoint not received")
244244
}
245245

246+
// Marshal request
246247
requestBytes, err := json.Marshal(request)
247248
if err != nil {
248249
return nil, fmt.Errorf("failed to marshal request: %w", err)
249250
}
250251

251-
responseChan := make(chan *JSONRPCResponse, 1)
252-
c.mu.Lock()
253-
c.responses[request.ID] = responseChan
254-
c.mu.Unlock()
255-
256-
req, err := http.NewRequestWithContext(
257-
ctx,
258-
"POST",
259-
c.endpoint.String(),
260-
bytes.NewReader(requestBytes),
261-
)
252+
// Create HTTP request
253+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpoint.String(), bytes.NewReader(requestBytes))
262254
if err != nil {
263255
return nil, fmt.Errorf("failed to create request: %w", err)
264256
}
265257

258+
// Set headers
266259
req.Header.Set("Content-Type", "application/json")
267-
// set custom http headers
268260
for k, v := range c.headers {
269261
req.Header.Set(k, v)
270262
}
271263

264+
// Register response channel
265+
responseChan := make(chan *JSONRPCResponse, 1)
266+
c.mu.Lock()
267+
c.responses[request.ID] = responseChan
268+
c.mu.Unlock()
269+
deleteResponseChan := func() {
270+
c.mu.Lock()
271+
delete(c.responses, request.ID)
272+
c.mu.Unlock()
273+
}
274+
275+
// Send request
272276
resp, err := c.httpClient.Do(req)
273277
if err != nil {
278+
deleteResponseChan()
274279
return nil, fmt.Errorf("failed to send request: %w", err)
275280
}
276281
defer resp.Body.Close()
277282

278-
if resp.StatusCode != http.StatusOK &&
279-
resp.StatusCode != http.StatusAccepted {
283+
// Check if we got an error response
284+
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
285+
deleteResponseChan()
286+
280287
body, _ := io.ReadAll(resp.Body)
281-
return nil, fmt.Errorf(
282-
"request failed with status %d: %s",
283-
resp.StatusCode,
284-
body,
285-
)
288+
return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, body)
286289
}
287290

288291
select {
289292
case <-ctx.Done():
290-
c.mu.Lock()
291-
delete(c.responses, request.ID)
292-
c.mu.Unlock()
293+
deleteResponseChan()
293294
return nil, ctx.Err()
294295
case response := <-responseChan:
295296
return response, nil

0 commit comments

Comments
 (0)