client.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package lib
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "net/http"
  6. "net/url"
  7. "strings"
  8. "github.com/docker/docker/api"
  9. "github.com/docker/docker/pkg/sockets"
  10. "github.com/docker/docker/pkg/tlsconfig"
  11. "github.com/docker/docker/pkg/version"
  12. )
  13. // Client is the API client that performs all operations
  14. // against a docker server.
  15. type Client struct {
  16. // proto holds the client protocol i.e. unix.
  17. Proto string
  18. // addr holds the client address.
  19. Addr string
  20. // basePath holds the path to prepend to the requests
  21. BasePath string
  22. // scheme holds the scheme of the client i.e. https.
  23. Scheme string
  24. // httpClient holds the client transport instance. Exported to keep the old code running.
  25. HTTPClient *http.Client
  26. // version of the server to talk to.
  27. version version.Version
  28. // custom http headers configured by users
  29. customHTTPHeaders map[string]string
  30. }
  31. // NewClient initializes a new API client
  32. // for the given host. It uses the tlsOptions
  33. // to decide whether to use a secure connection or not.
  34. // It also initializes the custom http headers to add to each request.
  35. func NewClient(host string, tlsOptions *tlsconfig.Options, httpHeaders map[string]string) (*Client, error) {
  36. return NewClientWithVersion(host, api.Version, tlsOptions, httpHeaders)
  37. }
  38. // NewClientWithVersion initializes a new API client
  39. // for the given host and API version. It uses the tlsOptions
  40. // to decide whether to use a secure connection or not.
  41. // It also initializes the custom http headers to add to each request.
  42. func NewClientWithVersion(host string, version version.Version, tlsOptions *tlsconfig.Options, httpHeaders map[string]string) (*Client, error) {
  43. var (
  44. basePath string
  45. tlsConfig *tls.Config
  46. scheme = "http"
  47. protoAddrParts = strings.SplitN(host, "://", 2)
  48. proto, addr = protoAddrParts[0], protoAddrParts[1]
  49. )
  50. if proto == "tcp" {
  51. parsed, err := url.Parse("tcp://" + addr)
  52. if err != nil {
  53. return nil, err
  54. }
  55. addr = parsed.Host
  56. basePath = parsed.Path
  57. }
  58. if tlsOptions != nil {
  59. scheme = "https"
  60. var err error
  61. tlsConfig, err = tlsconfig.Client(*tlsOptions)
  62. if err != nil {
  63. return nil, err
  64. }
  65. }
  66. // The transport is created here for reuse during the client session.
  67. transport := &http.Transport{
  68. TLSClientConfig: tlsConfig,
  69. }
  70. sockets.ConfigureTCPTransport(transport, proto, addr)
  71. return &Client{
  72. Addr: addr,
  73. BasePath: basePath,
  74. Scheme: scheme,
  75. HTTPClient: &http.Client{Transport: transport},
  76. version: version,
  77. customHTTPHeaders: httpHeaders,
  78. }, nil
  79. }
  80. // getAPIPath returns the versioned request path to call the api.
  81. // It appends the query parameters to the path if they are not empty.
  82. func (cli *Client) getAPIPath(p string, query url.Values) string {
  83. apiPath := fmt.Sprintf("%s/v%s%s", cli.BasePath, cli.version, p)
  84. if len(query) > 0 {
  85. apiPath += "?" + query.Encode()
  86. }
  87. return apiPath
  88. }