Skip to content

Commit 455cc3b

Browse files
authored
OAS-10132 Add connection configuration helper (#627)
1 parent 0c74253 commit 455cc3b

File tree

6 files changed

+195
-51
lines changed

6 files changed

+195
-51
lines changed

v2/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [master](https://github.com/arangodb/go-driver/tree/master) (N/A)
44
- Expose `NewType` method
5+
- Connection configuration helper
56

67
## [2.1.1](https://github.com/arangodb/go-driver/tree/v2.1.1) (2024-09-27)
78
- Improve backup tests stability
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package connection
22+
23+
import (
24+
"context"
25+
"crypto/tls"
26+
"net"
27+
"net/http"
28+
"time"
29+
30+
"golang.org/x/net/http2"
31+
)
32+
33+
func DefaultHTTPConfigurationWrapper(endpoint Endpoint, insecureSkipVerify bool) HttpConfiguration {
34+
mods := []Mod[HttpConfiguration]{
35+
WithHTTPEndpoint(endpoint),
36+
}
37+
if insecureSkipVerify {
38+
mods = append(mods, WithHTTPTransport(DefaultHTTPTransportSettings, WithHTTPInsecureSkipVerify))
39+
} else {
40+
mods = append(mods, WithHTTPTransport(DefaultHTTPTransportSettings))
41+
}
42+
return New[HttpConfiguration](mods...)
43+
}
44+
45+
func DefaultHTTP2ConfigurationWrapper(endpoint Endpoint, insecureSkipVerify bool) Http2Configuration {
46+
mods := []Mod[Http2Configuration]{
47+
WithHTT2PEndpoint(endpoint),
48+
}
49+
if insecureSkipVerify {
50+
mods = append(mods, WithHTTP2Transport(DefaultHTTP2TransportSettings, WithHTTP2InsecureSkipVerify))
51+
} else {
52+
mods = append(mods, WithHTTP2Transport(DefaultHTTP2TransportSettings))
53+
}
54+
return New[Http2Configuration](mods...)
55+
}
56+
57+
type Mod[T any] func(in *T)
58+
59+
func New[T any](mods ...Mod[T]) T {
60+
var h T
61+
for _, mod := range mods {
62+
mod(&h)
63+
}
64+
return h
65+
}
66+
67+
func WithHTTPEndpoint(endpoint Endpoint) Mod[HttpConfiguration] {
68+
return func(in *HttpConfiguration) {
69+
in.Endpoint = endpoint
70+
}
71+
}
72+
73+
func WithHTT2PEndpoint(endpoint Endpoint) Mod[Http2Configuration] {
74+
return func(in *Http2Configuration) {
75+
in.Endpoint = endpoint
76+
}
77+
}
78+
79+
func WithHTTPTransport(mods ...Mod[http.Transport]) Mod[HttpConfiguration] {
80+
return func(in *HttpConfiguration) {
81+
t := New[http.Transport](mods...)
82+
in.Transport = &t
83+
}
84+
}
85+
86+
func WithHTTP2Transport(mods ...Mod[http2.Transport]) Mod[Http2Configuration] {
87+
return func(in *Http2Configuration) {
88+
t := New[http2.Transport](mods...)
89+
in.Transport = &t
90+
}
91+
}
92+
93+
func WithHTTPInsecureSkipVerify(in *http.Transport) {
94+
if in.TLSClientConfig == nil {
95+
in.TLSClientConfig = &tls.Config{}
96+
}
97+
in.TLSClientConfig.InsecureSkipVerify = true
98+
}
99+
100+
func WithHTTP2InsecureSkipVerify(in *http2.Transport) {
101+
if in.TLSClientConfig == nil {
102+
in.TLSClientConfig = &tls.Config{}
103+
}
104+
in.TLSClientConfig.InsecureSkipVerify = true
105+
in.AllowHTTP = true
106+
107+
in.DialTLSContext = func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
108+
// Use net.Dial for plain TCP connection (h2c)
109+
return net.DialTimeout(network, addr, 30*time.Second)
110+
}
111+
}
112+
113+
func DefaultHTTPTransportSettings(in *http.Transport) {
114+
in.Proxy = http.ProxyFromEnvironment
115+
in.DialContext = (&net.Dialer{
116+
Timeout: 30 * time.Second,
117+
KeepAlive: 90 * time.Second,
118+
}).DialContext
119+
in.MaxIdleConns = 100
120+
in.IdleConnTimeout = 90 * time.Second
121+
in.TLSHandshakeTimeout = 10 * time.Second
122+
in.ExpectContinueTimeout = 1 * time.Second
123+
124+
if in.TLSClientConfig == nil {
125+
in.TLSClientConfig = &tls.Config{}
126+
}
127+
128+
in.TLSClientConfig = &tls.Config{
129+
MinVersion: tls.VersionTLS12,
130+
}
131+
}
132+
133+
func DefaultHTTP2TransportSettings(in *http2.Transport) {
134+
in.IdleConnTimeout = 90 * time.Second
135+
136+
if in.TLSClientConfig == nil {
137+
in.TLSClientConfig = &tls.Config{}
138+
}
139+
in.TLSClientConfig = &tls.Config{
140+
MinVersion: tls.VersionTLS12,
141+
InsecureSkipVerify: false,
142+
}
143+
}

v2/examples/example_client_async_test.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ package examples
2222

2323
import (
2424
"context"
25-
"fmt"
2625
"log"
2726
"time"
2827

@@ -32,10 +31,16 @@ import (
3231

3332
// ExampleNewConnectionAsyncWrapper shows how to create a connection wrapper for async requests
3433
// It lets use async requests on demand
35-
func ExampleNewConnectionAsyncWrapper() {
34+
func Main() {
3635
// Create an HTTP connection to the database
3736
endpoint := connection.NewRoundRobinEndpoints([]string{"http://localhost:8529"})
38-
conn := connection.NewHttpConnection(exampleJSONHTTPConnectionConfig(endpoint))
37+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
38+
39+
auth := connection.NewBasicAuth("root", "")
40+
err := conn.SetAuthentication(auth)
41+
if err != nil {
42+
log.Fatalf("Failed to set authentication: %v", err)
43+
}
3944

4045
// Create ASYNC wrapper for the connection
4146
conn = connection.NewConnectionAsyncWrapper(conn)
@@ -46,24 +51,23 @@ func ExampleNewConnectionAsyncWrapper() {
4651
// Ask the version of the server
4752
versionInfo, err := client.Version(context.Background())
4853
if err != nil {
49-
fmt.Printf("Failed to get version info: %v", err)
50-
} else {
51-
fmt.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
54+
log.Fatalf("Failed to get version info: %v", err)
5255
}
56+
log.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
5357

5458
// Trigger async request
5559
info, err := client.Version(connection.WithAsync(context.Background()))
5660
if err != nil {
57-
fmt.Printf("this is expected error since we are using async mode and response is not ready yet: %v", err)
61+
log.Printf("this is expected error since we are using async mode and response is not ready yet: %v", err)
5862
}
5963
if info.Version != "" {
60-
fmt.Printf("Expected empty version if async request is in progress, got %s", info.Version)
64+
log.Printf("Expected empty version if async request is in progress, got %s", info.Version)
6165
}
6266

6367
// Fetch an async job id from the error
6468
id, isAsyncId := connection.IsAsyncJobInProgress(err)
6569
if !isAsyncId {
66-
fmt.Printf("Expected async job id, got %v", id)
70+
log.Fatalf("Expected async job id, got %v", id)
6771
}
6872

6973
// Wait for an async result
@@ -83,4 +87,5 @@ func ExampleNewConnectionAsyncWrapper() {
8387
if err != nil {
8488
log.Fatalf("Failed to fetch async job result: %v", err)
8589
}
90+
log.Printf("Async job result: %s", info.Version)
8691
}
Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -22,11 +22,7 @@ package examples
2222

2323
import (
2424
"context"
25-
"crypto/tls"
26-
"fmt"
27-
"net"
28-
"net/http"
29-
"time"
25+
"log"
3026

3127
"github.com/arangodb/go-driver/v2/arangodb"
3228
"github.com/arangodb/go-driver/v2/connection"
@@ -36,34 +32,21 @@ import (
3632
func ExampleNewClient() {
3733
// Create an HTTP connection to the database
3834
endpoint := connection.NewRoundRobinEndpoints([]string{"http://localhost:8529"})
39-
conn := connection.NewHttpConnection(exampleJSONHTTPConnectionConfig(endpoint))
35+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
4036

37+
// Add authentication
38+
auth := connection.NewBasicAuth("root", "")
39+
err := conn.SetAuthentication(auth)
40+
if err != nil {
41+
log.Fatalf("Failed to set authentication: %v", err)
42+
}
4143
// Create a client
4244
client := arangodb.NewClient(conn)
4345

4446
// Ask the version of the server
4547
versionInfo, err := client.Version(context.Background())
4648
if err != nil {
47-
fmt.Printf("Failed to get version info: %v", err)
48-
} else {
49-
fmt.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
50-
}
51-
}
52-
53-
func exampleJSONHTTPConnectionConfig(endpoint connection.Endpoint) connection.HttpConfiguration {
54-
return connection.HttpConfiguration{
55-
Endpoint: endpoint,
56-
ContentType: connection.ApplicationJSON,
57-
Transport: &http.Transport{
58-
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
59-
DialContext: (&net.Dialer{
60-
Timeout: 30 * time.Second,
61-
KeepAlive: 90 * time.Second,
62-
}).DialContext,
63-
MaxIdleConns: 100,
64-
IdleConnTimeout: 90 * time.Second,
65-
TLSHandshakeTimeout: 10 * time.Second,
66-
ExpectContinueTimeout: 1 * time.Second,
67-
},
49+
log.Printf("Failed to get version info: %v", err)
6850
}
51+
log.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
6952
}

v2/examples/example_client_maglev_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ package examples
2222

2323
import (
2424
"context"
25-
"fmt"
25+
"log"
2626

2727
"github.com/arangodb/go-driver/v2/arangodb"
2828
"github.com/arangodb/go-driver/v2/connection"
@@ -35,21 +35,27 @@ import (
3535
// - all requests to _db/<db-name-2> will use endpoint 2
3636
func ExampleNewMaglevHashEndpoints() {
3737
// Create an HTTP connection to the database
38-
endpoints, err := connection.NewMaglevHashEndpoints(
38+
endpoint, err := connection.NewMaglevHashEndpoints(
3939
[]string{"https://a:8529", "https://a:8539", "https://b:8529"},
4040
connection.RequestDBNameValueExtractor,
4141
)
4242

43-
conn := connection.NewHttpConnection(exampleJSONHTTPConnectionConfig(endpoints))
43+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
44+
45+
// Add authentication
46+
auth := connection.NewBasicAuth("root", "")
47+
err = conn.SetAuthentication(auth)
48+
if err != nil {
49+
log.Fatalf("Failed to set authentication: %v", err)
50+
}
4451

4552
// Create a client
4653
client := arangodb.NewClient(conn)
4754

4855
// Ask the version of the server
4956
versionInfo, err := client.Version(context.Background())
5057
if err != nil {
51-
fmt.Printf("Failed to get version info: %v", err)
52-
} else {
53-
fmt.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
58+
log.Printf("Failed to get version info: %v", err)
5459
}
60+
log.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
5561
}

v2/examples/example_client_roundrobin_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ package examples
2222

2323
import (
2424
"context"
25-
"fmt"
25+
"log"
2626

2727
"github.com/arangodb/go-driver/v2/arangodb"
2828
"github.com/arangodb/go-driver/v2/connection"
@@ -31,17 +31,23 @@ import (
3131
// ExampleNewRoundRobinEndpoints shows how to create a client with round-robin endpoint list
3232
func ExampleNewRoundRobinEndpoints() {
3333
// Create an HTTP connection to the database
34-
endpoints := connection.NewRoundRobinEndpoints([]string{"https://a:8529", "https://a:8539", "https://b:8529"})
35-
conn := connection.NewHttpConnection(exampleJSONHTTPConnectionConfig(endpoints))
34+
endpoint := connection.NewRoundRobinEndpoints([]string{"https://a:8529", "https://a:8539", "https://b:8529"})
35+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
36+
37+
// Add authentication
38+
auth := connection.NewBasicAuth("root", "")
39+
err := conn.SetAuthentication(auth)
40+
if err != nil {
41+
log.Fatalf("Failed to set authentication: %v", err)
42+
}
3643

3744
// Create a client
3845
client := arangodb.NewClient(conn)
3946

4047
// Ask the version of the server
4148
versionInfo, err := client.Version(context.Background())
4249
if err != nil {
43-
fmt.Printf("Failed to get version info: %v", err)
44-
} else {
45-
fmt.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
50+
log.Printf("Failed to get version info: %v", err)
4651
}
52+
log.Printf("Database has version '%s' and license '%s'\n", versionInfo.Version, versionInfo.License)
4753
}

0 commit comments

Comments
 (0)