client.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. // tlsConfig holds the tls configuration to use in hijacked requests.
  25. tlsConfig *tls.Config
  26. // httpClient holds the client transport instance. Exported to keep the old code running.
  27. httpClient *http.Client
  28. // version of the server to talk to.
  29. version version.Version
  30. // custom http headers configured by users
  31. customHTTPHeaders map[string]string
  32. }
  33. // NewClient initializes a new API client
  34. // for the given host. It uses the tlsOptions
  35. // to decide whether to use a secure connection or not.
  36. // It also initializes the custom http headers to add to each request.
  37. func NewClient(host string, tlsOptions *tlsconfig.Options, httpHeaders map[string]string) (*Client, error) {
  38. return NewClientWithVersion(host, api.Version, tlsOptions, httpHeaders)
  39. }
  40. // NewClientWithVersion initializes a new API client
  41. // for the given host and API version. It uses the tlsOptions
  42. // to decide whether to use a secure connection or not.
  43. // It also initializes the custom http headers to add to each request.
  44. func NewClientWithVersion(host string, version version.Version, tlsOptions *tlsconfig.Options, httpHeaders map[string]string) (*Client, error) {
  45. var (
  46. basePath string
  47. tlsConfig *tls.Config
  48. scheme = "http"
  49. protoAddrParts = strings.SplitN(host, "://", 2)
  50. proto, addr = protoAddrParts[0], protoAddrParts[1]
  51. )
  52. if proto == "tcp" {
  53. parsed, err := url.Parse("tcp://" + addr)
  54. if err != nil {
  55. return nil, err
  56. }
  57. addr = parsed.Host
  58. basePath = parsed.Path
  59. }
  60. if tlsOptions != nil {
  61. scheme = "https"
  62. var err error
  63. tlsConfig, err = tlsconfig.Client(*tlsOptions)
  64. if err != nil {
  65. return nil, err
  66. }
  67. }
  68. // The transport is created here for reuse during the client session.
  69. transport := &http.Transport{
  70. TLSClientConfig: tlsConfig,
  71. }
  72. sockets.ConfigureTCPTransport(transport, proto, addr)
  73. return &Client{
  74. proto: proto,
  75. addr: addr,
  76. basePath: basePath,
  77. scheme: scheme,
  78. tlsConfig: tlsConfig,
  79. httpClient: &http.Client{Transport: transport},
  80. version: version,
  81. customHTTPHeaders: httpHeaders,
  82. }, nil
  83. }
  84. // getAPIPath returns the versioned request path to call the api.
  85. // It appends the query parameters to the path if they are not empty.
  86. func (cli *Client) getAPIPath(p string, query url.Values) string {
  87. apiPath := fmt.Sprintf("%s/v%s%s", cli.basePath, cli.version, p)
  88. if len(query) > 0 {
  89. apiPath += "?" + query.Encode()
  90. }
  91. return apiPath
  92. }