-
Notifications
You must be signed in to change notification settings - Fork 1
/
client_options.go
157 lines (143 loc) · 4.42 KB
/
client_options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package rpc
import (
"time"
"go.bryk.io/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/encoding/gzip"
"google.golang.org/grpc/keepalive"
)
// ClientOption allows adjusting client settings following a functional
// pattern.
type ClientOption func(*Client) error
// WithInsecureSkipVerify controls whether a client verifies the server's
// certificate chain and host name. If InsecureSkipVerify is true, TLS accepts
// any certificate presented by the server and any host name in that certificate.
// In this mode, TLS is susceptible to MITM attacks. This should be used only
// for testing.
func WithInsecureSkipVerify() ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.skipVerify = true
return nil
}
}
// WithServerNameOverride adjust the identifier expected to be present on the
// upstream RPC server's certificate, when using TLS. This option is meant for
// testing only. If set to a non-empty string, it will override the virtual host
// name of authority (e.g. :authority header field) in requests.
func WithServerNameOverride(name string) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.nameOverride = name
return nil
}
}
// WithAuthCertificate enabled certificate-based client authentication with the
// provided credentials.
func WithAuthCertificate(cert, key []byte) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
cert, err := LoadCertificate(cert, key)
if err != nil {
return errors.WithStack(err)
}
c.cert = &cert
return nil
}
}
// WithAuthToken use the provided token string as bearer authentication credential.
func WithAuthToken(token string) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
ct := authToken{
kind: "Bearer",
value: token,
}
c.dialOpts = append(c.dialOpts, grpc.WithPerRPCCredentials(ct))
return nil
}
}
// WithUserAgent sets the "user-agent" value use by the client instance.
func WithUserAgent(val string) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.dialOpts = append(c.dialOpts, grpc.WithUserAgent(val))
return nil
}
}
// WithTimeout establish a time limit when dialing a connection with the server.
func WithTimeout(timeout time.Duration) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.timeout = timeout
return nil
}
}
// WithClientTLS set parameters to establish a secure connection channel with the
// server.
func WithClientTLS(opts ClientTLSConfig) ClientOption {
return func(c *Client) (err error) {
c.mu.Lock()
defer c.mu.Unlock()
c.tlsOpts = opts
c.tlsConf, err = clientTLSConf(opts)
return errors.WithStack(err)
}
}
// WithCompression will enable standard GZIP compression on all client requests.
func WithCompression() ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.callOpts = append(c.callOpts, grpc.UseCompressor(gzip.Name))
return nil
}
}
// WithRetry will enable automatic error retries on all client requests.
func WithRetry(config *RetryOptions) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.callOpts = append(c.callOpts, Retry(config)...)
return nil
}
}
// WithKeepalive will configure the client to send a ping message when a certain
// time (in seconds) has passed without activity in the connection. The minimum valid
// interval is 10 seconds.
func WithKeepalive(t int) ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
if t < 10 {
t = 10
}
c.dialOpts = append(c.dialOpts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: time.Duration(t) * time.Second,
Timeout: time.Duration(t) * time.Second,
PermitWithoutStream: true,
}))
return nil
}
}
// WithLoadBalancer configures the client connection to enable load balancing, by
// default the "round-robin" strategy is used to choose a backend for RPC requests.
// When enabling this option the provided endpoint is expected to be a DNS record that
// returns a set of reachable IP addresses.
// When deploying with Kubernetes this is done by using a [Headless Service].
//
// [Headless Service]: https://kubernetes.io/docs/concepts/services-networking/service/#headless-services
func WithLoadBalancer() ClientOption {
return func(c *Client) error {
c.mu.Lock()
defer c.mu.Unlock()
c.useBalancer = true
return nil
}
}