Skip to content

Commit 4a22ce6

Browse files
edanielsbenjirewismatthewdale
authored
GODRIVER-2050 - Add settable http.Clients and gracefully close provided defaults (#1093)
Co-authored-by: Benjamin Rewis <[email protected]> Co-authored-by: Matt Dale <[email protected]>
1 parent edfc51c commit 4a22ce6

18 files changed

+222
-57
lines changed

internal/http.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (C) MongoDB, Inc. 2022-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package internal // import "go.mongodb.org/mongo-driver/internal"
8+
9+
import (
10+
"net/http"
11+
"time"
12+
)
13+
14+
// DefaultHTTPClient is the default HTTP client used across the driver.
15+
var DefaultHTTPClient = &http.Client{
16+
// TODO(GODRIVER-2623): Use "http.DefaultTransport.Clone" once we change the minimum supported Go version to 1.13.
17+
Transport: &http.Transport{
18+
Proxy: http.ProxyFromEnvironment,
19+
MaxIdleConns: 100,
20+
IdleConnTimeout: 90 * time.Second,
21+
TLSHandshakeTimeout: 10 * time.Second,
22+
ExpectContinueTimeout: 1 * time.Second,
23+
},
24+
}
25+
26+
// CloseIdleHTTPConnections closes any connections which were previously
27+
// connected from previous requests but are now sitting idle in
28+
// a "keep-alive" state. It does not interrupt any connections currently
29+
// in use.
30+
// Borrowed from go standard library.
31+
func CloseIdleHTTPConnections(client *http.Client) {
32+
type closeIdler interface {
33+
CloseIdleConnections()
34+
}
35+
if tr, ok := client.Transport.(closeIdler); ok {
36+
tr.CloseIdleConnections()
37+
}
38+
}

mongo/client.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import (
1010
"context"
1111
"errors"
1212
"fmt"
13+
"net/http"
1314
"time"
1415

1516
"go.mongodb.org/mongo-driver/bson"
1617
"go.mongodb.org/mongo-driver/bson/bsoncodec"
1718
"go.mongodb.org/mongo-driver/event"
19+
"go.mongodb.org/mongo-driver/internal"
1820
"go.mongodb.org/mongo-driver/internal/uuid"
1921
"go.mongodb.org/mongo-driver/mongo/description"
2022
"go.mongodb.org/mongo-driver/mongo/options"
@@ -64,6 +66,7 @@ type Client struct {
6466
serverMonitor *event.ServerMonitor
6567
sessionPool *session.Pool
6668
timeout *time.Duration
69+
httpClient *http.Client
6770

6871
// client-side encryption fields
6972
keyVaultClientFLE *Client
@@ -173,6 +176,7 @@ func NewClient(opts ...*options.ClientOptions) (*Client, error) {
173176
}
174177
// Timeout
175178
client.timeout = clientOpt.Timeout
179+
client.httpClient = clientOpt.HTTPClient
176180
// WriteConcern
177181
if clientOpt.WriteConcern != nil {
178182
client.writeConcern = clientOpt.WriteConcern
@@ -307,6 +311,11 @@ func (c *Client) Disconnect(ctx context.Context) error {
307311
if disconnector, ok := c.deployment.(driver.Disconnector); ok {
308312
return replaceErrors(disconnector.Disconnect(ctx))
309313
}
314+
315+
if c.httpClient == internal.DefaultHTTPClient {
316+
internal.CloseIdleHTTPConnections(c.httpClient)
317+
}
318+
310319
return nil
311320
}
312321

@@ -600,6 +609,7 @@ func (c *Client) configureCryptFLE(mc *mongocrypt.MongoCrypt, opts *options.Auto
600609
KeyFn: kr.cryptKeys,
601610
MarkFn: c.mongocryptdFLE.markCommand,
602611
TLSConfig: opts.TLSConfig,
612+
HTTPClient: opts.HTTPClient,
603613
BypassAutoEncryption: bypass,
604614
})
605615
}

mongo/client_encryption.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func NewClientEncryption(keyVaultClient *Client, opts ...*options.ClientEncrypti
6666
KeyFn: kr.cryptKeys,
6767
CollInfoFn: cir.cryptCollInfo,
6868
TLSConfig: ceo.TLSConfig,
69+
HTTPClient: ceo.HTTPClient,
6970
})
7071

7172
return ce, nil

mongo/options/autoencryptionoptions.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ package options
88

99
import (
1010
"crypto/tls"
11+
"net/http"
12+
13+
"go.mongodb.org/mongo-driver/internal"
1114
)
1215

1316
// AutoEncryptionOptions represents options used to configure auto encryption/decryption behavior for a mongo.Client
@@ -32,13 +35,16 @@ type AutoEncryptionOptions struct {
3235
BypassAutoEncryption *bool
3336
ExtraOptions map[string]interface{}
3437
TLSConfig map[string]*tls.Config
38+
HTTPClient *http.Client
3539
EncryptedFieldsMap map[string]interface{}
3640
BypassQueryAnalysis *bool
3741
}
3842

3943
// AutoEncryption creates a new AutoEncryptionOptions configured with default values.
4044
func AutoEncryption() *AutoEncryptionOptions {
41-
return &AutoEncryptionOptions{}
45+
return &AutoEncryptionOptions{
46+
HTTPClient: internal.DefaultHTTPClient,
47+
}
4248
}
4349

4450
// SetKeyVaultClientOptions specifies options for the client used to communicate with the key vault collection.
@@ -194,6 +200,9 @@ func MergeAutoEncryptionOptions(opts ...*AutoEncryptionOptions) *AutoEncryptionO
194200
if opt.BypassQueryAnalysis != nil {
195201
aeo.BypassQueryAnalysis = opt.BypassQueryAnalysis
196202
}
203+
if opt.HTTPClient != nil {
204+
aeo.HTTPClient = opt.HTTPClient
205+
}
197206
}
198207

199208
return aeo

mongo/options/clientencryptionoptions.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,24 @@ package options
99
import (
1010
"crypto/tls"
1111
"fmt"
12+
"net/http"
13+
14+
"go.mongodb.org/mongo-driver/internal"
1215
)
1316

1417
// ClientEncryptionOptions represents all possible options used to configure a ClientEncryption instance.
1518
type ClientEncryptionOptions struct {
1619
KeyVaultNamespace string
1720
KmsProviders map[string]map[string]interface{}
1821
TLSConfig map[string]*tls.Config
22+
HTTPClient *http.Client
1923
}
2024

2125
// ClientEncryption creates a new ClientEncryptionOptions instance.
2226
func ClientEncryption() *ClientEncryptionOptions {
23-
return &ClientEncryptionOptions{}
27+
return &ClientEncryptionOptions{
28+
HTTPClient: internal.DefaultHTTPClient,
29+
}
2430
}
2531

2632
// SetKeyVaultNamespace specifies the namespace of the key vault collection. This is required.
@@ -132,6 +138,9 @@ func MergeClientEncryptionOptions(opts ...*ClientEncryptionOptions) *ClientEncry
132138
if opt.TLSConfig != nil {
133139
ceo.TLSConfig = opt.TLSConfig
134140
}
141+
if opt.HTTPClient != nil {
142+
ceo.HTTPClient = opt.HTTPClient
143+
}
135144
}
136145

137146
return ceo

mongo/options/clientoptions.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"fmt"
1717
"io/ioutil"
1818
"net"
19+
"net/http"
1920
"strings"
2021
"time"
2122

@@ -104,6 +105,7 @@ type ClientOptions struct {
104105
DisableOCSPEndpointCheck *bool
105106
HeartbeatInterval *time.Duration
106107
Hosts []string
108+
HTTPClient *http.Client
107109
LoadBalanced *bool
108110
LocalThreshold *time.Duration
109111
MaxConnIdleTime *time.Duration
@@ -162,7 +164,9 @@ type ClientOptions struct {
162164

163165
// Client creates a new ClientOptions instance.
164166
func Client() *ClientOptions {
165-
return new(ClientOptions)
167+
return &ClientOptions{
168+
HTTPClient: internal.DefaultHTTPClient,
169+
}
166170
}
167171

168172
// Validate validates the client options. This method will return the first error found.
@@ -767,6 +771,14 @@ func (c *ClientOptions) SetTLSConfig(cfg *tls.Config) *ClientOptions {
767771
return c
768772
}
769773

774+
// SetHTTPClient specifies the http.Client to be used for any HTTP requests.
775+
//
776+
// This should only be used to set custom HTTP client configurations. By default, the connection will use an internal.DefaultHTTPClient.
777+
func (c *ClientOptions) SetHTTPClient(client *http.Client) *ClientOptions {
778+
c.HTTPClient = client
779+
return c
780+
}
781+
770782
// SetWriteConcern specifies the write concern to use to for write operations. This can also be set through the following
771783
// URI options:
772784
//
@@ -889,6 +901,9 @@ func MergeClientOptions(opts ...*ClientOptions) *ClientOptions {
889901
if len(opt.Hosts) > 0 {
890902
c.Hosts = opt.Hosts
891903
}
904+
if opt.HTTPClient != nil {
905+
c.HTTPClient = opt.HTTPClient
906+
}
892907
if opt.LoadBalanced != nil {
893908
c.LoadBalanced = opt.LoadBalanced
894909
}

0 commit comments

Comments
 (0)