New initializes a new API client with a default HTTPClient, and default API host and version. It also initializes the custom HTTP headers to add to each request. It takes an optional list of [Opt] functional arguments, which are applied in the order they're provided, which allows modifying the defa
(ops ...Opt)
| 189 | // |
| 190 | // cli, err := client.New(client.FromEnv) |
| 191 | func New(ops ...Opt) (*Client, error) { |
| 192 | hostURL, err := ParseHostURL(DefaultDockerHost) |
| 193 | if err != nil { |
| 194 | return nil, err |
| 195 | } |
| 196 | |
| 197 | client, err := defaultHTTPClient(hostURL) |
| 198 | if err != nil { |
| 199 | return nil, err |
| 200 | } |
| 201 | c := &Client{ |
| 202 | clientConfig: clientConfig{ |
| 203 | host: DefaultDockerHost, |
| 204 | version: MaxAPIVersion, |
| 205 | client: client, |
| 206 | proto: hostURL.Scheme, |
| 207 | addr: hostURL.Host, |
| 208 | traceOpts: []otelhttp.Option{ |
| 209 | otelhttp.WithSpanNameFormatter(func(_ string, req *http.Request) string { |
| 210 | return req.Method + " " + req.URL.Path |
| 211 | }), |
| 212 | }, |
| 213 | }, |
| 214 | } |
| 215 | cfg := &c.clientConfig |
| 216 | |
| 217 | for _, op := range ops { |
| 218 | if op == nil { |
| 219 | continue |
| 220 | } |
| 221 | if err := op(cfg); err != nil { |
| 222 | return nil, err |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | if cfg.envAPIVersion != "" { |
| 227 | c.setAPIVersion(cfg.envAPIVersion) |
| 228 | } else if cfg.manualAPIVersion != "" { |
| 229 | c.setAPIVersion(cfg.manualAPIVersion) |
| 230 | } |
| 231 | |
| 232 | if tr, ok := c.client.Transport.(*http.Transport); ok { |
| 233 | // Store the base transport before we wrap it in tracing libs below |
| 234 | // This is used, as an example, to close idle connections when the client is closed |
| 235 | c.baseTransport = tr |
| 236 | } |
| 237 | |
| 238 | if c.scheme == "" { |
| 239 | // TODO(stevvooe): This isn't really the right way to write clients in Go. |
| 240 | // `NewClient` should probably only take an `*http.Client` and work from there. |
| 241 | // Unfortunately, the model of having a host-ish/url-thingy as the connection |
| 242 | // string has us confusing protocol and transport layers. We continue doing |
| 243 | // this to avoid breaking existing clients but this should be addressed. |
| 244 | if c.tlsConfig() != nil { |
| 245 | c.scheme = "https" |
| 246 | } else { |
| 247 | c.scheme = "http" |
| 248 | } |