blob: 7a5ac2e7c4948ca3ff55aab1d3a27a3b5c41e15f [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001/*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package grpc
20
21import (
22 "context"
William Kurkianea869482019-04-09 15:16:11 -040023 "net"
Abhay Kumara61c5222025-11-10 07:32:50 +000024 "net/url"
William Kurkianea869482019-04-09 15:16:11 -040025 "time"
26
Devmalya Pauldd23a992019-11-14 07:06:31 +000027 "google.golang.org/grpc/backoff"
Abhay Kumara61c5222025-11-10 07:32:50 +000028 "google.golang.org/grpc/channelz"
William Kurkianea869482019-04-09 15:16:11 -040029 "google.golang.org/grpc/credentials"
Abhay Kumara61c5222025-11-10 07:32:50 +000030 "google.golang.org/grpc/credentials/insecure"
William Kurkianea869482019-04-09 15:16:11 -040031 "google.golang.org/grpc/internal"
Devmalya Pauldd23a992019-11-14 07:06:31 +000032 internalbackoff "google.golang.org/grpc/internal/backoff"
Abhay Kumara61c5222025-11-10 07:32:50 +000033 "google.golang.org/grpc/internal/binarylog"
William Kurkianea869482019-04-09 15:16:11 -040034 "google.golang.org/grpc/internal/transport"
35 "google.golang.org/grpc/keepalive"
Abhay Kumara61c5222025-11-10 07:32:50 +000036 "google.golang.org/grpc/mem"
William Kurkianea869482019-04-09 15:16:11 -040037 "google.golang.org/grpc/resolver"
38 "google.golang.org/grpc/stats"
39)
40
Abhay Kumara61c5222025-11-10 07:32:50 +000041const (
42 // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#limits-on-retries-and-hedges
43 defaultMaxCallAttempts = 5
44)
45
46func init() {
47 internal.AddGlobalDialOptions = func(opt ...DialOption) {
48 globalDialOptions = append(globalDialOptions, opt...)
49 }
50 internal.ClearGlobalDialOptions = func() {
51 globalDialOptions = nil
52 }
53 internal.AddGlobalPerTargetDialOptions = func(opt any) {
54 if ptdo, ok := opt.(perTargetDialOption); ok {
55 globalPerTargetDialOptions = append(globalPerTargetDialOptions, ptdo)
56 }
57 }
58 internal.ClearGlobalPerTargetDialOptions = func() {
59 globalPerTargetDialOptions = nil
60 }
61 internal.WithBinaryLogger = withBinaryLogger
62 internal.JoinDialOptions = newJoinDialOption
63 internal.DisableGlobalDialOptions = newDisableGlobalDialOptions
64 internal.WithBufferPool = withBufferPool
65}
66
William Kurkianea869482019-04-09 15:16:11 -040067// dialOptions configure a Dial call. dialOptions are set by the DialOption
68// values passed to Dial.
69type dialOptions struct {
Abhilash S.L3b494632019-07-16 15:51:09 +053070 unaryInt UnaryClientInterceptor
71 streamInt StreamClientInterceptor
72
73 chainUnaryInts []UnaryClientInterceptor
74 chainStreamInts []StreamClientInterceptor
75
Abhay Kumara61c5222025-11-10 07:32:50 +000076 compressorV0 Compressor
77 dc Decompressor
78 bs internalbackoff.Strategy
79 block bool
80 returnLastError bool
81 timeout time.Duration
82 authority string
83 binaryLogger binarylog.Logger
84 copts transport.ConnectOptions
85 callOptions []CallOption
86 channelzParent channelz.Identifier
Abhilash S.L3b494632019-07-16 15:51:09 +053087 disableServiceConfig bool
88 disableRetry bool
89 disableHealthCheck bool
Abhilash S.L3b494632019-07-16 15:51:09 +053090 minConnectTimeout func() time.Duration
91 defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
92 defaultServiceConfigRawJSON *string
Abhay Kumara61c5222025-11-10 07:32:50 +000093 resolvers []resolver.Builder
94 idleTimeout time.Duration
95 defaultScheme string
96 maxCallAttempts int
97 enableLocalDNSResolution bool // Specifies if target hostnames should be resolved when proxying is enabled.
98 useProxy bool // Specifies if a server should be connected via proxy.
William Kurkianea869482019-04-09 15:16:11 -040099}
100
101// DialOption configures how we set up the connection.
102type DialOption interface {
103 apply(*dialOptions)
104}
105
Abhay Kumara61c5222025-11-10 07:32:50 +0000106var globalDialOptions []DialOption
107
108// perTargetDialOption takes a parsed target and returns a dial option to apply.
109//
110// This gets called after NewClient() parses the target, and allows per target
111// configuration set through a returned DialOption. The DialOption will not take
112// effect if specifies a resolver builder, as that Dial Option is factored in
113// while parsing target.
114type perTargetDialOption interface {
115 // DialOption returns a Dial Option to apply.
116 DialOptionForTarget(parsedTarget url.URL) DialOption
117}
118
119var globalPerTargetDialOptions []perTargetDialOption
120
William Kurkianea869482019-04-09 15:16:11 -0400121// EmptyDialOption does not alter the dial configuration. It can be embedded in
122// another structure to build custom dial options.
123//
Abhay Kumara61c5222025-11-10 07:32:50 +0000124// # Experimental
125//
126// Notice: This type is EXPERIMENTAL and may be changed or removed in a
127// later release.
William Kurkianea869482019-04-09 15:16:11 -0400128type EmptyDialOption struct{}
129
130func (EmptyDialOption) apply(*dialOptions) {}
131
Abhay Kumara61c5222025-11-10 07:32:50 +0000132type disableGlobalDialOptions struct{}
133
134func (disableGlobalDialOptions) apply(*dialOptions) {}
135
136// newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn
137// from applying the global DialOptions (set via AddGlobalDialOptions).
138func newDisableGlobalDialOptions() DialOption {
139 return &disableGlobalDialOptions{}
140}
141
William Kurkianea869482019-04-09 15:16:11 -0400142// funcDialOption wraps a function that modifies dialOptions into an
143// implementation of the DialOption interface.
144type funcDialOption struct {
145 f func(*dialOptions)
146}
147
148func (fdo *funcDialOption) apply(do *dialOptions) {
149 fdo.f(do)
150}
151
152func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
153 return &funcDialOption{
154 f: f,
155 }
156}
157
Abhay Kumara61c5222025-11-10 07:32:50 +0000158type joinDialOption struct {
159 opts []DialOption
160}
161
162func (jdo *joinDialOption) apply(do *dialOptions) {
163 for _, opt := range jdo.opts {
164 opt.apply(do)
165 }
166}
167
168func newJoinDialOption(opts ...DialOption) DialOption {
169 return &joinDialOption{opts: opts}
170}
171
172// WithSharedWriteBuffer allows reusing per-connection transport write buffer.
173// If this option is set to true every connection will release the buffer after
174// flushing the data on the wire.
William Kurkianea869482019-04-09 15:16:11 -0400175//
Abhay Kumara61c5222025-11-10 07:32:50 +0000176// # Experimental
177//
178// Notice: This API is EXPERIMENTAL and may be changed or removed in a
179// later release.
180func WithSharedWriteBuffer(val bool) DialOption {
181 return newFuncDialOption(func(o *dialOptions) {
182 o.copts.SharedWriteBuffer = val
183 })
184}
185
186// WithWriteBufferSize determines how much data can be batched before doing a
187// write on the wire. The default value for this buffer is 32KB.
188//
189// Zero or negative values will disable the write buffer such that each write
190// will be on underlying connection. Note: A Send call may not directly
191// translate to a write.
William Kurkianea869482019-04-09 15:16:11 -0400192func WithWriteBufferSize(s int) DialOption {
193 return newFuncDialOption(func(o *dialOptions) {
194 o.copts.WriteBufferSize = s
195 })
196}
197
198// WithReadBufferSize lets you set the size of read buffer, this determines how
199// much data can be read at most for each read syscall.
200//
Abhay Kumara61c5222025-11-10 07:32:50 +0000201// The default value for this buffer is 32KB. Zero or negative values will
202// disable read buffer for a connection so data framer can access the
203// underlying conn directly.
William Kurkianea869482019-04-09 15:16:11 -0400204func WithReadBufferSize(s int) DialOption {
205 return newFuncDialOption(func(o *dialOptions) {
206 o.copts.ReadBufferSize = s
207 })
208}
209
210// WithInitialWindowSize returns a DialOption which sets the value for initial
211// window size on a stream. The lower bound for window size is 64K and any value
212// smaller than that will be ignored.
213func WithInitialWindowSize(s int32) DialOption {
214 return newFuncDialOption(func(o *dialOptions) {
215 o.copts.InitialWindowSize = s
Abhay Kumara61c5222025-11-10 07:32:50 +0000216 o.copts.StaticWindowSize = true
William Kurkianea869482019-04-09 15:16:11 -0400217 })
218}
219
220// WithInitialConnWindowSize returns a DialOption which sets the value for
221// initial window size on a connection. The lower bound for window size is 64K
222// and any value smaller than that will be ignored.
223func WithInitialConnWindowSize(s int32) DialOption {
224 return newFuncDialOption(func(o *dialOptions) {
225 o.copts.InitialConnWindowSize = s
Abhay Kumara61c5222025-11-10 07:32:50 +0000226 o.copts.StaticWindowSize = true
227 })
228}
229
230// WithStaticStreamWindowSize returns a DialOption which sets the initial
231// stream window size to the value provided and disables dynamic flow control.
232func WithStaticStreamWindowSize(s int32) DialOption {
233 return newFuncDialOption(func(o *dialOptions) {
234 o.copts.InitialWindowSize = s
235 o.copts.StaticWindowSize = true
236 })
237}
238
239// WithStaticConnWindowSize returns a DialOption which sets the initial
240// connection window size to the value provided and disables dynamic flow
241// control.
242func WithStaticConnWindowSize(s int32) DialOption {
243 return newFuncDialOption(func(o *dialOptions) {
244 o.copts.InitialConnWindowSize = s
245 o.copts.StaticWindowSize = true
William Kurkianea869482019-04-09 15:16:11 -0400246 })
247}
248
249// WithMaxMsgSize returns a DialOption which sets the maximum message size the
250// client can receive.
251//
David Bainbridge788e5202019-10-21 18:49:40 +0000252// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead. Will
253// be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400254func WithMaxMsgSize(s int) DialOption {
255 return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
256}
257
258// WithDefaultCallOptions returns a DialOption which sets the default
259// CallOptions for calls over the connection.
260func WithDefaultCallOptions(cos ...CallOption) DialOption {
261 return newFuncDialOption(func(o *dialOptions) {
262 o.callOptions = append(o.callOptions, cos...)
263 })
264}
265
266// WithCodec returns a DialOption which sets a codec for message marshaling and
267// unmarshaling.
268//
David Bainbridge788e5202019-10-21 18:49:40 +0000269// Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead. Will be
270// supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400271func WithCodec(c Codec) DialOption {
272 return WithDefaultCallOptions(CallCustomCodec(c))
273}
274
275// WithCompressor returns a DialOption which sets a Compressor to use for
276// message compression. It has lower priority than the compressor set by the
277// UseCompressor CallOption.
278//
David Bainbridge788e5202019-10-21 18:49:40 +0000279// Deprecated: use UseCompressor instead. Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400280func WithCompressor(cp Compressor) DialOption {
281 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000282 o.compressorV0 = cp
William Kurkianea869482019-04-09 15:16:11 -0400283 })
284}
285
286// WithDecompressor returns a DialOption which sets a Decompressor to use for
287// incoming message decompression. If incoming response messages are encoded
288// using the decompressor's Type(), it will be used. Otherwise, the message
289// encoding will be used to look up the compressor registered via
290// encoding.RegisterCompressor, which will then be used to decompress the
291// message. If no compressor is registered for the encoding, an Unimplemented
292// status error will be returned.
293//
David Bainbridge788e5202019-10-21 18:49:40 +0000294// Deprecated: use encoding.RegisterCompressor instead. Will be supported
295// throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400296func WithDecompressor(dc Decompressor) DialOption {
297 return newFuncDialOption(func(o *dialOptions) {
298 o.dc = dc
299 })
300}
301
Abhay Kumara61c5222025-11-10 07:32:50 +0000302// WithConnectParams configures the ClientConn to use the provided ConnectParams
303// for creating and maintaining connections to servers.
Devmalya Pauldd23a992019-11-14 07:06:31 +0000304//
305// The backoff configuration specified as part of the ConnectParams overrides
306// all defaults specified in
307// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider
308// using the backoff.DefaultConfig as a base, in cases where you want to
309// override only a subset of the backoff configuration.
Devmalya Pauldd23a992019-11-14 07:06:31 +0000310func WithConnectParams(p ConnectParams) DialOption {
311 return newFuncDialOption(func(o *dialOptions) {
312 o.bs = internalbackoff.Exponential{Config: p.Backoff}
313 o.minConnectTimeout = func() time.Duration {
314 return p.MinConnectTimeout
315 }
316 })
317}
318
William Kurkianea869482019-04-09 15:16:11 -0400319// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
320// when backing off after failed connection attempts.
Devmalya Pauldd23a992019-11-14 07:06:31 +0000321//
322// Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400323func WithBackoffMaxDelay(md time.Duration) DialOption {
324 return WithBackoffConfig(BackoffConfig{MaxDelay: md})
325}
326
327// WithBackoffConfig configures the dialer to use the provided backoff
328// parameters after connection failures.
329//
Devmalya Pauldd23a992019-11-14 07:06:31 +0000330// Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400331func WithBackoffConfig(b BackoffConfig) DialOption {
Devmalya Pauldd23a992019-11-14 07:06:31 +0000332 bc := backoff.DefaultConfig
333 bc.MaxDelay = b.MaxDelay
334 return withBackoff(internalbackoff.Exponential{Config: bc})
William Kurkianea869482019-04-09 15:16:11 -0400335}
336
337// withBackoff sets the backoff strategy used for connectRetryNum after a failed
338// connection attempt.
339//
340// This can be exported if arbitrary backoff strategies are allowed by gRPC.
Devmalya Pauldd23a992019-11-14 07:06:31 +0000341func withBackoff(bs internalbackoff.Strategy) DialOption {
William Kurkianea869482019-04-09 15:16:11 -0400342 return newFuncDialOption(func(o *dialOptions) {
343 o.bs = bs
344 })
345}
346
Abhay Kumara61c5222025-11-10 07:32:50 +0000347// WithBlock returns a DialOption which makes callers of Dial block until the
William Kurkianea869482019-04-09 15:16:11 -0400348// underlying connection is up. Without this, Dial returns immediately and
349// connecting the server happens in background.
Abhay Kumara61c5222025-11-10 07:32:50 +0000350//
351// Use of this feature is not recommended. For more information, please see:
352// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
353//
354// Deprecated: this DialOption is not supported by NewClient.
355// Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400356func WithBlock() DialOption {
357 return newFuncDialOption(func(o *dialOptions) {
358 o.block = true
359 })
360}
361
Abhay Kumara61c5222025-11-10 07:32:50 +0000362// WithReturnConnectionError returns a DialOption which makes the client connection
363// return a string containing both the last connection error that occurred and
364// the context.DeadlineExceeded error.
365// Implies WithBlock()
366//
367// Use of this feature is not recommended. For more information, please see:
368// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
369//
370// Deprecated: this DialOption is not supported by NewClient.
371// Will be supported throughout 1.x.
372func WithReturnConnectionError() DialOption {
373 return newFuncDialOption(func(o *dialOptions) {
374 o.block = true
375 o.returnLastError = true
376 })
377}
378
William Kurkianea869482019-04-09 15:16:11 -0400379// WithInsecure returns a DialOption which disables transport security for this
Abhay Kumara61c5222025-11-10 07:32:50 +0000380// ClientConn. Under the hood, it uses insecure.NewCredentials().
381//
382// Note that using this DialOption with per-RPC credentials (through
383// WithCredentialsBundle or WithPerRPCCredentials) which require transport
384// security is incompatible and will cause RPCs to fail.
385//
386// Deprecated: use WithTransportCredentials and insecure.NewCredentials()
387// instead. Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400388func WithInsecure() DialOption {
389 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000390 o.copts.TransportCredentials = insecure.NewCredentials()
391 })
392}
393
394// WithNoProxy returns a DialOption which disables the use of proxies for this
395// ClientConn. This is ignored if WithDialer or WithContextDialer are used.
396//
397// # Experimental
398//
399// Notice: This API is EXPERIMENTAL and may be changed or removed in a
400// later release.
401func WithNoProxy() DialOption {
402 return newFuncDialOption(func(o *dialOptions) {
403 o.useProxy = false
404 })
405}
406
407// WithLocalDNSResolution forces local DNS name resolution even when a proxy is
408// specified in the environment. By default, the server name is provided
409// directly to the proxy as part of the CONNECT handshake. This is ignored if
410// WithNoProxy is used.
411//
412// # Experimental
413//
414// Notice: This API is EXPERIMENTAL and may be changed or removed in a
415// later release.
416func WithLocalDNSResolution() DialOption {
417 return newFuncDialOption(func(o *dialOptions) {
418 o.enableLocalDNSResolution = true
William Kurkianea869482019-04-09 15:16:11 -0400419 })
420}
421
422// WithTransportCredentials returns a DialOption which configures a connection
423// level security credentials (e.g., TLS/SSL). This should not be used together
424// with WithCredentialsBundle.
425func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
426 return newFuncDialOption(func(o *dialOptions) {
427 o.copts.TransportCredentials = creds
428 })
429}
430
431// WithPerRPCCredentials returns a DialOption which sets credentials and places
432// auth state on each outbound RPC.
433func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
434 return newFuncDialOption(func(o *dialOptions) {
435 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
436 })
437}
438
439// WithCredentialsBundle returns a DialOption to set a credentials bundle for
440// the ClientConn.WithCreds. This should not be used together with
441// WithTransportCredentials.
442//
Abhay Kumara61c5222025-11-10 07:32:50 +0000443// # Experimental
444//
445// Notice: This API is EXPERIMENTAL and may be changed or removed in a
446// later release.
William Kurkianea869482019-04-09 15:16:11 -0400447func WithCredentialsBundle(b credentials.Bundle) DialOption {
448 return newFuncDialOption(func(o *dialOptions) {
449 o.copts.CredsBundle = b
450 })
451}
452
453// WithTimeout returns a DialOption that configures a timeout for dialing a
454// ClientConn initially. This is valid if and only if WithBlock() is present.
455//
Abhay Kumara61c5222025-11-10 07:32:50 +0000456// Deprecated: this DialOption is not supported by NewClient.
457// Will be supported throughout 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400458func WithTimeout(d time.Duration) DialOption {
459 return newFuncDialOption(func(o *dialOptions) {
460 o.timeout = d
461 })
462}
463
464// WithContextDialer returns a DialOption that sets a dialer to create
465// connections. If FailOnNonTempDialError() is set to true, and an error is
466// returned by f, gRPC checks the error's Temporary() method to decide if it
467// should try to reconnect to the network address.
Abhay Kumara61c5222025-11-10 07:32:50 +0000468//
469// Note that gRPC by default performs name resolution on the target passed to
470// NewClient. To bypass name resolution and cause the target string to be
471// passed directly to the dialer here instead, use the "passthrough" resolver
472// by specifying it in the target string, e.g. "passthrough:target".
473//
474// Note: All supported releases of Go (as of December 2023) override the OS
475// defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
476// with OS defaults for keepalive time and interval, use a net.Dialer that sets
477// the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket
478// option to true from the Control field. For a concrete example of how to do
479// this, see internal.NetDialerWithTCPKeepalive().
480//
481// For more information, please see [issue 23459] in the Go GitHub repo.
482//
483// [issue 23459]: https://github.com/golang/go/issues/23459
William Kurkianea869482019-04-09 15:16:11 -0400484func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
485 return newFuncDialOption(func(o *dialOptions) {
486 o.copts.Dialer = f
487 })
488}
489
William Kurkianea869482019-04-09 15:16:11 -0400490// WithDialer returns a DialOption that specifies a function to use for dialing
491// network addresses. If FailOnNonTempDialError() is set to true, and an error
492// is returned by f, gRPC checks the error's Temporary() method to decide if it
493// should try to reconnect to the network address.
494//
David Bainbridge788e5202019-10-21 18:49:40 +0000495// Deprecated: use WithContextDialer instead. Will be supported throughout
496// 1.x.
William Kurkianea869482019-04-09 15:16:11 -0400497func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
498 return WithContextDialer(
499 func(ctx context.Context, addr string) (net.Conn, error) {
500 if deadline, ok := ctx.Deadline(); ok {
501 return f(addr, time.Until(deadline))
502 }
503 return f(addr, 0)
504 })
505}
506
507// WithStatsHandler returns a DialOption that specifies the stats handler for
508// all the RPCs and underlying network connections in this ClientConn.
509func WithStatsHandler(h stats.Handler) DialOption {
510 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000511 if h == nil {
512 logger.Error("ignoring nil parameter in grpc.WithStatsHandler ClientOption")
513 // Do not allow a nil stats handler, which would otherwise cause
514 // panics.
515 return
516 }
517 o.copts.StatsHandlers = append(o.copts.StatsHandlers, h)
518 })
519}
520
521// withBinaryLogger returns a DialOption that specifies the binary logger for
522// this ClientConn.
523func withBinaryLogger(bl binarylog.Logger) DialOption {
524 return newFuncDialOption(func(o *dialOptions) {
525 o.binaryLogger = bl
William Kurkianea869482019-04-09 15:16:11 -0400526 })
527}
528
529// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
530// non-temporary dial errors. If f is true, and dialer returns a non-temporary
531// error, gRPC will fail the connection to the network address and won't try to
532// reconnect. The default value of FailOnNonTempDialError is false.
533//
534// FailOnNonTempDialError only affects the initial dial, and does not do
535// anything useful unless you are also using WithBlock().
536//
Abhay Kumara61c5222025-11-10 07:32:50 +0000537// Use of this feature is not recommended. For more information, please see:
538// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
539//
540// Deprecated: this DialOption is not supported by NewClient.
541// This API may be changed or removed in a
542// later release.
William Kurkianea869482019-04-09 15:16:11 -0400543func FailOnNonTempDialError(f bool) DialOption {
544 return newFuncDialOption(func(o *dialOptions) {
545 o.copts.FailOnNonTempDialError = f
546 })
547}
548
549// WithUserAgent returns a DialOption that specifies a user agent string for all
550// the RPCs.
551func WithUserAgent(s string) DialOption {
552 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000553 o.copts.UserAgent = s + " " + grpcUA
William Kurkianea869482019-04-09 15:16:11 -0400554 })
555}
556
557// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
558// for the client transport.
Abhay Kumara61c5222025-11-10 07:32:50 +0000559//
560// Keepalive is disabled by default.
William Kurkianea869482019-04-09 15:16:11 -0400561func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
562 if kp.Time < internal.KeepaliveMinPingTime {
Abhay Kumara61c5222025-11-10 07:32:50 +0000563 logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
William Kurkianea869482019-04-09 15:16:11 -0400564 kp.Time = internal.KeepaliveMinPingTime
565 }
566 return newFuncDialOption(func(o *dialOptions) {
567 o.copts.KeepaliveParams = kp
568 })
569}
570
571// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
572// unary RPCs.
573func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
574 return newFuncDialOption(func(o *dialOptions) {
575 o.unaryInt = f
576 })
577}
578
Abhilash S.L3b494632019-07-16 15:51:09 +0530579// WithChainUnaryInterceptor returns a DialOption that specifies the chained
580// interceptor for unary RPCs. The first interceptor will be the outer most,
581// while the last interceptor will be the inner most wrapper around the real call.
582// All interceptors added by this method will be chained, and the interceptor
583// defined by WithUnaryInterceptor will always be prepended to the chain.
584func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
585 return newFuncDialOption(func(o *dialOptions) {
586 o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
587 })
588}
589
William Kurkianea869482019-04-09 15:16:11 -0400590// WithStreamInterceptor returns a DialOption that specifies the interceptor for
591// streaming RPCs.
592func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
593 return newFuncDialOption(func(o *dialOptions) {
594 o.streamInt = f
595 })
596}
597
Abhilash S.L3b494632019-07-16 15:51:09 +0530598// WithChainStreamInterceptor returns a DialOption that specifies the chained
Abhay Kumara61c5222025-11-10 07:32:50 +0000599// interceptor for streaming RPCs. The first interceptor will be the outer most,
Abhilash S.L3b494632019-07-16 15:51:09 +0530600// while the last interceptor will be the inner most wrapper around the real call.
601// All interceptors added by this method will be chained, and the interceptor
602// defined by WithStreamInterceptor will always be prepended to the chain.
603func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
604 return newFuncDialOption(func(o *dialOptions) {
605 o.chainStreamInts = append(o.chainStreamInts, interceptors...)
606 })
607}
608
William Kurkianea869482019-04-09 15:16:11 -0400609// WithAuthority returns a DialOption that specifies the value to be used as the
Abhay Kumara61c5222025-11-10 07:32:50 +0000610// :authority pseudo-header and as the server name in authentication handshake.
611// This overrides all other ways of setting authority on the channel, but can be
612// overridden per-call by using grpc.CallAuthority.
William Kurkianea869482019-04-09 15:16:11 -0400613func WithAuthority(a string) DialOption {
614 return newFuncDialOption(func(o *dialOptions) {
615 o.authority = a
616 })
617}
618
619// WithChannelzParentID returns a DialOption that specifies the channelz ID of
620// current ClientConn's parent. This function is used in nested channel creation
621// (e.g. grpclb dial).
Abhay Kumara61c5222025-11-10 07:32:50 +0000622//
623// # Experimental
624//
625// Notice: This API is EXPERIMENTAL and may be changed or removed in a
626// later release.
627func WithChannelzParentID(c channelz.Identifier) DialOption {
William Kurkianea869482019-04-09 15:16:11 -0400628 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000629 o.channelzParent = c
William Kurkianea869482019-04-09 15:16:11 -0400630 })
631}
632
Abhilash S.L3b494632019-07-16 15:51:09 +0530633// WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
William Kurkianea869482019-04-09 15:16:11 -0400634// service config provided by the resolver and provides a hint to the resolver
635// to not fetch service configs.
Abhilash S.L3b494632019-07-16 15:51:09 +0530636//
637// Note that this dial option only disables service config from resolver. If
638// default service config is provided, gRPC will use the default service config.
William Kurkianea869482019-04-09 15:16:11 -0400639func WithDisableServiceConfig() DialOption {
640 return newFuncDialOption(func(o *dialOptions) {
641 o.disableServiceConfig = true
642 })
643}
644
Abhilash S.L3b494632019-07-16 15:51:09 +0530645// WithDefaultServiceConfig returns a DialOption that configures the default
646// service config, which will be used in cases where:
David Bainbridge788e5202019-10-21 18:49:40 +0000647//
Abhay Kumara61c5222025-11-10 07:32:50 +0000648// 1. WithDisableServiceConfig is also used, or
Abhilash S.L3b494632019-07-16 15:51:09 +0530649//
Abhay Kumara61c5222025-11-10 07:32:50 +0000650// 2. The name resolver does not provide a service config or provides an
651// invalid service config.
652//
653// The parameter s is the JSON representation of the default service config.
654// For more information about service configs, see:
655// https://github.com/grpc/grpc/blob/master/doc/service_config.md
656// For a simple example of usage, see:
657// examples/features/load_balancing/client/main.go
Abhilash S.L3b494632019-07-16 15:51:09 +0530658func WithDefaultServiceConfig(s string) DialOption {
659 return newFuncDialOption(func(o *dialOptions) {
660 o.defaultServiceConfigRawJSON = &s
661 })
662}
663
William Kurkianea869482019-04-09 15:16:11 -0400664// WithDisableRetry returns a DialOption that disables retries, even if the
665// service config enables them. This does not impact transparent retries, which
666// will happen automatically if no data is written to the wire or if the RPC is
667// unprocessed by the remote server.
William Kurkianea869482019-04-09 15:16:11 -0400668func WithDisableRetry() DialOption {
669 return newFuncDialOption(func(o *dialOptions) {
670 o.disableRetry = true
671 })
672}
673
Abhay Kumara61c5222025-11-10 07:32:50 +0000674// MaxHeaderListSizeDialOption is a DialOption that specifies the maximum
675// (uncompressed) size of header list that the client is prepared to accept.
676type MaxHeaderListSizeDialOption struct {
677 MaxHeaderListSize uint32
678}
679
680func (o MaxHeaderListSizeDialOption) apply(do *dialOptions) {
681 do.copts.MaxHeaderListSize = &o.MaxHeaderListSize
682}
683
William Kurkianea869482019-04-09 15:16:11 -0400684// WithMaxHeaderListSize returns a DialOption that specifies the maximum
685// (uncompressed) size of header list that the client is prepared to accept.
686func WithMaxHeaderListSize(s uint32) DialOption {
Abhay Kumara61c5222025-11-10 07:32:50 +0000687 return MaxHeaderListSizeDialOption{
688 MaxHeaderListSize: s,
689 }
William Kurkianea869482019-04-09 15:16:11 -0400690}
691
Abhilash S.L3b494632019-07-16 15:51:09 +0530692// WithDisableHealthCheck disables the LB channel health checking for all
693// SubConns of this ClientConn.
William Kurkianea869482019-04-09 15:16:11 -0400694//
Abhay Kumara61c5222025-11-10 07:32:50 +0000695// # Experimental
696//
697// Notice: This API is EXPERIMENTAL and may be changed or removed in a
698// later release.
William Kurkianea869482019-04-09 15:16:11 -0400699func WithDisableHealthCheck() DialOption {
700 return newFuncDialOption(func(o *dialOptions) {
701 o.disableHealthCheck = true
702 })
703}
704
William Kurkianea869482019-04-09 15:16:11 -0400705func defaultDialOptions() dialOptions {
706 return dialOptions{
William Kurkianea869482019-04-09 15:16:11 -0400707 copts: transport.ConnectOptions{
William Kurkianea869482019-04-09 15:16:11 -0400708 ReadBufferSize: defaultReadBufSize,
Abhay Kumara61c5222025-11-10 07:32:50 +0000709 WriteBufferSize: defaultWriteBufSize,
710 UserAgent: grpcUA,
711 BufferPool: mem.DefaultBufferPool(),
William Kurkianea869482019-04-09 15:16:11 -0400712 },
Abhay Kumara61c5222025-11-10 07:32:50 +0000713 bs: internalbackoff.DefaultExponential,
714 idleTimeout: 30 * time.Minute,
715 defaultScheme: "dns",
716 maxCallAttempts: defaultMaxCallAttempts,
717 useProxy: true,
718 enableLocalDNSResolution: false,
William Kurkianea869482019-04-09 15:16:11 -0400719 }
720}
Abhilash S.L3b494632019-07-16 15:51:09 +0530721
Abhay Kumara61c5222025-11-10 07:32:50 +0000722// withMinConnectDeadline specifies the function that clientconn uses to
Abhilash S.L3b494632019-07-16 15:51:09 +0530723// get minConnectDeadline. This can be used to make connection attempts happen
724// faster/slower.
725//
726// For testing purpose only.
727func withMinConnectDeadline(f func() time.Duration) DialOption {
728 return newFuncDialOption(func(o *dialOptions) {
729 o.minConnectTimeout = f
730 })
731}
Devmalya Pauldd23a992019-11-14 07:06:31 +0000732
Abhay Kumara61c5222025-11-10 07:32:50 +0000733// withDefaultScheme is used to allow Dial to use "passthrough" as the default
734// name resolver, while NewClient uses "dns" otherwise.
735func withDefaultScheme(s string) DialOption {
Devmalya Pauldd23a992019-11-14 07:06:31 +0000736 return newFuncDialOption(func(o *dialOptions) {
Abhay Kumara61c5222025-11-10 07:32:50 +0000737 o.defaultScheme = s
738 })
739}
740
741// WithResolvers allows a list of resolver implementations to be registered
742// locally with the ClientConn without needing to be globally registered via
743// resolver.Register. They will be matched against the scheme used for the
744// current Dial only, and will take precedence over the global registry.
745//
746// # Experimental
747//
748// Notice: This API is EXPERIMENTAL and may be changed or removed in a
749// later release.
750func WithResolvers(rs ...resolver.Builder) DialOption {
751 return newFuncDialOption(func(o *dialOptions) {
752 o.resolvers = append(o.resolvers, rs...)
753 })
754}
755
756// WithIdleTimeout returns a DialOption that configures an idle timeout for the
757// channel. If the channel is idle for the configured timeout, i.e there are no
758// ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode
759// and as a result the name resolver and load balancer will be shut down. The
760// channel will exit idle mode when the Connect() method is called or when an
761// RPC is initiated.
762//
763// A default timeout of 30 minutes will be used if this dial option is not set
764// at dial time and idleness can be disabled by passing a timeout of zero.
765//
766// # Experimental
767//
768// Notice: This API is EXPERIMENTAL and may be changed or removed in a
769// later release.
770func WithIdleTimeout(d time.Duration) DialOption {
771 return newFuncDialOption(func(o *dialOptions) {
772 o.idleTimeout = d
773 })
774}
775
776// WithMaxCallAttempts returns a DialOption that configures the maximum number
777// of attempts per call (including retries and hedging) using the channel.
778// Service owners may specify a higher value for these parameters, but higher
779// values will be treated as equal to the maximum value by the client
780// implementation. This mitigates security concerns related to the service
781// config being transferred to the client via DNS.
782//
783// A value of 5 will be used if this dial option is not set or n < 2.
784func WithMaxCallAttempts(n int) DialOption {
785 return newFuncDialOption(func(o *dialOptions) {
786 if n < 2 {
787 n = defaultMaxCallAttempts
788 }
789 o.maxCallAttempts = n
790 })
791}
792
793func withBufferPool(bufferPool mem.BufferPool) DialOption {
794 return newFuncDialOption(func(o *dialOptions) {
795 o.copts.BufferPool = bufferPool
Devmalya Pauldd23a992019-11-14 07:06:31 +0000796 })
797}