Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix connections leak: close connections after dispatching request #265

Merged
merged 1 commit into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions cycletls/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ type cycleTLSRequest struct {
Options Options `json:"options"`
}

//rename to request+client+options
// rename to request+client+options
type fullRequest struct {
req *http.Request
client http.Client
options cycleTLSRequest
}

//Response contains Cycletls response data
// Response contains Cycletls response data
type Response struct {
RequestID string
Status int
Body string
Headers map[string]string
}

//JSONBody converts response body to json
// JSONBody converts response body to json
func (re Response) JSONBody() map[string]interface{} {
var data map[string]interface{}
err := json.Unmarshal([]byte(re.Body), &data)
Expand All @@ -60,7 +60,7 @@ func (re Response) JSONBody() map[string]interface{} {
return data
}

//CycleTLS creates full request and response
// CycleTLS creates full request and response
type CycleTLS struct {
ReqChan chan fullRequest
RespChan chan Response
Expand Down Expand Up @@ -168,6 +168,8 @@ func processRequest(request cycleTLSRequest) (result fullRequest) {
}

func dispatcher(res fullRequest) (response Response, err error) {
defer res.client.CloseIdleConnections()

resp, err := res.client.Do(res.req)
if err != nil {

Expand Down
12 changes: 9 additions & 3 deletions cycletls/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (rt *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
// Fix this later for proper cookie parsing
for _, properties := range rt.Cookies {
req.AddCookie(&http.Cookie{
Name: properties.Name,
Name: properties.Name,
Value: properties.Value,
Path: properties.Path,
Domain: properties.Domain,
Expand Down Expand Up @@ -67,7 +67,7 @@ func (rt *roundTripper) getTransport(req *http.Request, addr string) error {
return fmt.Errorf("invalid URL scheme: [%v]", req.URL.Scheme)
}

_, err := rt.dialTLS(context.Background(), "tcp", addr)
_, err := rt.dialTLS(req.Context(), "tcp", addr)
switch err {
case errProtocolNegotiated:
case nil:
Expand All @@ -87,7 +87,6 @@ func (rt *roundTripper) dialTLS(ctx context.Context, network, addr string) (net.
// If we have the connection from when we determined the HTTPS
// cachedTransports to use, return that.
if conn := rt.cachedConnections[addr]; conn != nil {
delete(rt.cachedConnections, addr)
return conn, nil
}
rawConn, err := rt.dialer.DialContext(ctx, network, addr)
Expand Down Expand Up @@ -165,6 +164,13 @@ func (rt *roundTripper) getDialTLSAddr(req *http.Request) string {
return net.JoinHostPort(req.URL.Host, "443") // we can assume port is 443 at this point
}

func (rt *roundTripper) CloseIdleConnections() {
for addr, conn := range rt.cachedConnections {
_ = conn.Close()
delete(rt.cachedConnections, addr)
}
}

func newRoundTripper(browser browser, dialer ...proxy.ContextDialer) http.RoundTripper {
if len(dialer) > 0 {

Expand Down