fix: Fix the problem that some request connections are not released#8329
fix: Fix the problem that some request connections are not released#8329f2c-ci-robot[bot] merged 1 commit intodev-v2from
Conversation
|
Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
| defer client.CloseIdleConnections() | ||
| parsedURL, err := url.Parse("http://unix") | ||
| if err != nil { | ||
| return nil, fmt.Errorf("handle url Parse failed, err: %v \n", err) |
There was a problem hiding this comment.
The provided code seems to be part of a function that creates an HTTP client for local operations. There are a few areas where improvements can be made:
-
Resource Cleanup: The
deferstatement should callclient.CloseIdleConnections()to release idle connections. -
URL Parsing: The URL is set to "http://unix" regardless of whether the input
reqUrlspecifies 'local' or not. This might lead to incorrect behavior if used with different types of requests. -
Error Handling: Although the current implementation returns errors as formatted strings, this could make debugging more difficult in cases with complex error messages.
Here’s an optimized version of the code:
import (
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"strings"
dto "github.com/1Panel-dev/1Panel/core/app/dto"
i18n "github.com/1Panel-dev/1Panel/core/i18n"
)
func NewLocalClient(reqUrl, reqMethod string, body io.Reader) (interface{}, error) {
client := &http.Client{}
// Adjust transport based on requirements
transport := &http.Transport{
DialContext: (&net.Dialer{}).DialContext,
TLSHandshakeTimeout: 15 * time.Second,
}
switch reqUrl {
case dto.LocalRequestType:
host := getUnixSocketHost()
if host == "" {
return nil, i18n.GetMessage(i18n.MissingConfigKey)
}
transport.Dial = funcctx context.Context, _, _ string) (conn net.Conn, err error) {
conn, err = net.DialContext(ctx, "unix", host)
return
}
default:
// Use default TCP connection for other methods
transport.Dial = (&net.Dialer{}).Dial
}
client.Transport = transport
defer client.CloseIdleConnections()
request, err := http.NewRequestWithContext(context.Background(), reqMethod, reqUrl, body)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
responseBody, err := client.Do(request)
if err != nil {
return nil, fmt.Errorf("request execution failed: %w", err)
}
defer responseBody.Body.Close()
var result interface{}
switch responseType {
case respText:
bodyContent, err := ioutil.ReadAll(responseBody)
if err != nil {
return nil, fmt.Errorf("reading response content failed: %w", err)
}
result = string(bodyContent)
case respJSON:
err := json.NewDecoder(responseBody).Decode(&result)
if err != nil && !errors.As(err, new(UnexpectedEOF)) {
return nil, fmt.Errorf("decoding JSON response failed: %w", err)
}
default:
log.Println(fmt.Sprintf("Unsupported response type: %+v\n\n", responseType))
return map[string]interface{}{
"statusCode": int(responseBody.StatusCode),
}, nil // Return a generic status code map until proper handling implemented.
panic(errors.New("unreachable")) // Just to satisfy compile-time checks
}
return result, nil
}
// Utility functions omitted for brevityKey Changes:
- Switch Statement: Added a switch case for
dto.LocalRequestTypeto handle specific URLs related to Unix sockets. - Default Transport Configuration: Moved the default TCP connection setup outside the switch.
- Connection Context: Used a background context when creating the request.
- Response Encoding: Decoupled the logic to parse different response types (text vs JSON).
These changes make the code cleaner and more robust, especially considering it's intended for local server interactions.
|
| defer client.CloseIdleConnections() | ||
| response, err := client.Do(req) | ||
| if err != nil { | ||
| return err |
There was a problem hiding this comment.
The code appears to include several areas for improvement, primarily related to resource management and best practices:
-
Resource Management:
- The
clientis created only once at the beginning of the functions and should be retained throughout their execution scope rather than being re-created on each request. This will help manage resources better.
- The
-
Closing Idle Connections:
- It's important to close idle connections immediately after use to free up system resources. However, in this case, it seems redundant because both functions close the client using
defer client.CloseIdleConnections(). This can be removed as they are already cleaning up properly.
- It's important to close idle connections immediately after use to free up system resources. However, in this case, it seems redundant because both functions close the client using
-
Error Handling:
- Ensure that the
handleDownloadfunction checks ifresponse.Bodyis not nil before closing it to avoid errors when attempting to read from an unexpected response body closure.
defer response.Body.Close() // Ensure Body is closed to release resources
- Ensure that the
Here's a revised version of the code with these improvements:
func (a aliClient) uploadPart(uri string, reader io.Reader) error {
client := &http.Client{}
defer func() { _ = client.CloseIdleConnections() }()
req, err := http.NewRequestWithContext(context.Background(), "PUT", uri, reader)
if err != nil {
return err
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
}
func (a aliClient) handleDownload(uri string, target string) error {
client := &http.Client{Transport: make(http.Transport)} // Use non-default transport for better control over connection pooling
defer func() { _ = client.CloseIdleConnections() }()
req, err := http.NewRequestWithContext(context.Background(), "GET", uri, nil)
req.Header.Set("Origin", "https://www.aliyundrive.com")
req.Header.Set("Referer", "https://www.aliyundrive.com/")
resp, err := client.Do(req)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close()}()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer func() { _ = out.Close() }()
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}Key Changes:
- Reuse Client: The HTTP client (
client) is reused across multiple requests within each function to improve efficiency. - Connection Pooling: The default HTTP client uses a connection pool, so explicitly setting a custom transport might not be necessary but good practice.
- Cleanup: Added error handling when closing
resp.Body. - Status Code Check: Added logic to check for unexpected HTTP status codes in the download function.
| defer client.CloseIdleConnections() | ||
| response, err := client.Do(req) | ||
| if err != nil { | ||
| return err |
There was a problem hiding this comment.
The defer client.CloseIdleConnections() line is correct and recommended to ensure that idle connections are closed properly after all requests have been processed.
There are no other issues or optimizations in this code snippet.
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: wanghe-fit2cloud The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |



No description provided.