Ensure proper closure of HTTP response body to prevent resource leak#331
Ensure proper closure of HTTP response body to prevent resource leak#331SahibYar wants to merge 7 commits intoalpacahq:masterfrom
Conversation
ac09453 to
644a290
Compare
…d removed redundant code
644a290 to
28dad51
Compare
| } | ||
|
|
||
| func verify(resp *http.Response) error { | ||
| func Verify(resp *http.Response) error { |
There was a problem hiding this comment.
Please do not make this and closeResp exported. I understand the intent (to reuse them in the marketdata package), but that isn't worth making these public. On the long run we can consider introducing an internal package and refactor the common code between alpaca and marketdata, but for now let's just keep the duplication please.
There was a problem hiding this comment.
if I don't make Verify exported, I have to copy all the following chunk of code copied to marketdata just to keep the logic same.
func verify(resp *http.Response) error {
if resp.StatusCode >= http.StatusMultipleChoices {
return APIErrorFromResponse(resp)
}
return nil
}
func APIErrorFromResponse(resp *http.Response) error {
defer closeResp(resp)
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
var apiErr APIError
if err := json.Unmarshal(body, &apiErr); err != nil {
// If the error is not in our JSON format, we simply return the HTTP response
return fmt.Errorf("%s (HTTP %d)", body, resp.StatusCode)
}
apiErr.StatusCode = resp.StatusCode
apiErr.Body = strings.TrimSpace(string(body))
return &apiErr
}
func closeResp(resp *http.Response) {
if resp == nil || resp.Body == nil {
return
}
// The underlying TCP connection cannot be reused if the body is not fully read
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}
type APIError struct {
StatusCode int `json:"-"`
Code int `json:"code"`
Message string `json:"message"`
Body string `json:"-"`
}
func (e *APIError) Error() string {
if e.Code != 0 {
return fmt.Sprintf("%s (HTTP %d, Code %d)", e.Message, e.StatusCode, e.Code)
}
return fmt.Sprintf("%s (HTTP %d)", e.Message, e.StatusCode)
}
There was a problem hiding this comment.
actually I am raising another PR, which will remove much of redundant code. #334 It is not rigorous code change, targeting 1 file at a time. Ultimately we can create a common module for redundant code among marketdata and alpaca and move common functions like Verify and CloseResp to a separate make named alpaca-core
and we can call those functions like this
alpacaCore.Verfiy()
alpacaCore.CloseResp()
There was a problem hiding this comment.
alpacaCore is definitely not a good package name and I'm a bit hesitant about this. Could you please focus on finishing this PR (keeping the code duplication between alpaca and marketdata) before doing more refactors?
This PR fixes a potential resource leak issue in code. This oversight could lead to resource exhaustion over time. (Reference)
Changes:
resp.Body.Close()in all relevant places where HTTP requests are made.Testing.
I executed all test cases in following files.