Merge pull request #45923 from thaJeztah/client_header
client: remove custom "headers" type (use http.Header), and omit "version" header on API >= 1.30
This commit is contained in:
commit
ebcb230cff
14 changed files with 83 additions and 62 deletions
|
@ -2,6 +2,7 @@ package client // import "github.com/docker/docker/client"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -52,8 +53,7 @@ func (cli *Client) ContainerAttach(ctx context.Context, container string, option
|
|||
query.Set("logs", "1")
|
||||
}
|
||||
|
||||
headers := map[string][]string{
|
||||
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, http.Header{
|
||||
"Content-Type": {"text/plain"},
|
||||
}
|
||||
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
|
@ -46,10 +47,9 @@ func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, confi
|
|||
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
||||
config.ConsoleSize = nil
|
||||
}
|
||||
headers := map[string][]string{
|
||||
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, http.Header{
|
||||
"Content-Type": {"application/json"},
|
||||
}
|
||||
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
|
||||
})
|
||||
}
|
||||
|
||||
// ContainerExecInspect returns information about a specific exec process on the docker host.
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
|
@ -19,10 +20,10 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
|
|||
if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
|
||||
return distributionInspect, err
|
||||
}
|
||||
var headers map[string][]string
|
||||
|
||||
var headers http.Header
|
||||
if encodedRegistryAuth != "" {
|
||||
headers = map[string][]string{
|
||||
headers = http.Header{
|
||||
registry.AuthHeader: {encodedRegistryAuth},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
|||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
||||
headers := http.Header(make(map[string][]string))
|
||||
buf, err := json.Marshal(options.AuthConfigs)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
|
||||
headers := http.Header{}
|
||||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
headers.Set("Content-Type", "application/x-tar")
|
||||
|
||||
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
|
@ -37,11 +37,9 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
|||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
||||
osType := getDockerOS(serverResp.header.Get("Server"))
|
||||
|
||||
return types.ImageBuildResponse{
|
||||
Body: serverResp.body,
|
||||
OSType: osType,
|
||||
OSType: getDockerOS(serverResp.header.Get("Server")),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
|
@ -33,6 +34,7 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
|
|||
}
|
||||
|
||||
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/images/create", query, nil, headers)
|
||||
return cli.post(ctx, "/images/create", query, nil, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -17,8 +18,9 @@ func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (
|
|||
if quiet {
|
||||
v.Set("quiet", "1")
|
||||
}
|
||||
headers := map[string][]string{"Content-Type": {"application/x-tar"}}
|
||||
resp, err := cli.postRaw(ctx, "/images/load", v, input, headers)
|
||||
resp, err := cli.postRaw(ctx, "/images/load", v, input, http.Header{
|
||||
"Content-Type": {"application/x-tar"},
|
||||
})
|
||||
if err != nil {
|
||||
return types.ImageLoadResponse{}, err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
|
@ -50,6 +51,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im
|
|||
}
|
||||
|
||||
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
|
||||
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
|
@ -48,6 +49,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
|
|||
}
|
||||
|
||||
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.get(ctx, "/images/search", query, headers)
|
||||
return cli.get(ctx, "/images/search", query, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
|
@ -68,13 +69,15 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
|
|||
}
|
||||
|
||||
func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.get(ctx, "/plugins/privileges", query, headers)
|
||||
return cli.get(ctx, "/plugins/privileges", query, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
||||
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/plugins/pull", query, privileges, headers)
|
||||
return cli.post(ctx, "/plugins/pull", query, privileges, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
||||
func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) {
|
||||
|
|
|
@ -3,14 +3,16 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
)
|
||||
|
||||
// PluginPush pushes a plugin to a registry
|
||||
func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers)
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
|
@ -35,6 +36,7 @@ func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types
|
|||
}
|
||||
|
||||
func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) {
|
||||
headers := map[string][]string{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, headers)
|
||||
return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -28,17 +28,17 @@ type serverResponse struct {
|
|||
}
|
||||
|
||||
// head sends an http request to the docker API using the method HEAD.
|
||||
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) {
|
||||
return cli.sendRequest(ctx, http.MethodHead, path, query, nil, headers)
|
||||
}
|
||||
|
||||
// get sends an http request to the docker API using the method GET with a specific Go context.
|
||||
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) {
|
||||
return cli.sendRequest(ctx, http.MethodGet, path, query, nil, headers)
|
||||
}
|
||||
|
||||
// post sends an http request to the docker API using the method POST with a specific Go context.
|
||||
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (serverResponse, error) {
|
||||
body, headers, err := encodeBody(obj, headers)
|
||||
if err != nil {
|
||||
return serverResponse{}, err
|
||||
|
@ -46,11 +46,11 @@ func (cli *Client) post(ctx context.Context, path string, query url.Values, obj
|
|||
return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers)
|
||||
}
|
||||
|
||||
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) {
|
||||
return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers)
|
||||
}
|
||||
|
||||
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers http.Header) (serverResponse, error) {
|
||||
body, headers, err := encodeBody(obj, headers)
|
||||
if err != nil {
|
||||
return serverResponse{}, err
|
||||
|
@ -59,7 +59,7 @@ func (cli *Client) put(ctx context.Context, path string, query url.Values, obj i
|
|||
}
|
||||
|
||||
// putRaw sends an http request to the docker API using the method PUT.
|
||||
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) {
|
||||
// PUT requests are expected to always have a body (apparently)
|
||||
// so explicitly pass an empty body to sendRequest to signal that
|
||||
// it should set the Content-Type header if not already present.
|
||||
|
@ -70,13 +70,11 @@ func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, bo
|
|||
}
|
||||
|
||||
// delete sends an http request to the docker API using the method DELETE.
|
||||
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
|
||||
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers http.Header) (serverResponse, error) {
|
||||
return cli.sendRequest(ctx, http.MethodDelete, path, query, nil, headers)
|
||||
}
|
||||
|
||||
type headers map[string][]string
|
||||
|
||||
func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) {
|
||||
func encodeBody(obj interface{}, headers http.Header) (io.Reader, http.Header, error) {
|
||||
if obj == nil {
|
||||
return nil, headers, nil
|
||||
}
|
||||
|
@ -98,7 +96,7 @@ func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) {
|
|||
return body, headers, nil
|
||||
}
|
||||
|
||||
func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) {
|
||||
func (cli *Client) buildRequest(method, path string, body io.Reader, headers http.Header) (*http.Request, error) {
|
||||
req, err := http.NewRequest(method, path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -123,7 +121,7 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea
|
|||
return req, nil
|
||||
}
|
||||
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) {
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers http.Header) (serverResponse, error) {
|
||||
req, err := cli.buildRequest(method, cli.getAPIPath(ctx, path, query), body, headers)
|
||||
if err != nil {
|
||||
return serverResponse{}, err
|
||||
|
@ -161,19 +159,19 @@ func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResp
|
|||
return serverResp, err
|
||||
}
|
||||
|
||||
if nErr, ok := err.(*url.Error); ok {
|
||||
if nErr, ok := nErr.Err.(*net.OpError); ok {
|
||||
if uErr, ok := err.(*url.Error); ok {
|
||||
if nErr, ok := uErr.Err.(*net.OpError); ok {
|
||||
if os.IsPermission(nErr.Err) {
|
||||
return serverResp, errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err, ok := err.(net.Error); ok {
|
||||
if err.Timeout() {
|
||||
if nErr, ok := err.(net.Error); ok {
|
||||
if nErr.Timeout() {
|
||||
return serverResp, ErrorConnectionFailed(cli.host)
|
||||
}
|
||||
if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
|
||||
if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
|
||||
return serverResp, ErrorConnectionFailed(cli.host)
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +251,7 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
|
|||
return errors.Wrap(errors.New(errorMessage), "Error response from daemon")
|
||||
}
|
||||
|
||||
func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request {
|
||||
func (cli *Client) addHeaders(req *http.Request, headers http.Header) *http.Request {
|
||||
// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
|
||||
// then the user can't change OUR headers
|
||||
for k, v := range cli.customHTTPHeaders {
|
||||
|
|
|
@ -4,12 +4,14 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -17,13 +19,6 @@ import (
|
|||
// ServiceCreate creates a new service.
|
||||
func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) {
|
||||
var response types.ServiceCreateResponse
|
||||
headers := map[string][]string{
|
||||
"version": {cli.version},
|
||||
}
|
||||
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
|
||||
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container
|
||||
if service.TaskTemplate.ContainerSpec == nil && (service.TaskTemplate.Runtime == "" || service.TaskTemplate.Runtime == swarm.RuntimeContainer) {
|
||||
|
@ -53,6 +48,16 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
|
|||
}
|
||||
}
|
||||
|
||||
headers := http.Header{}
|
||||
if versions.LessThan(cli.version, "1.30") {
|
||||
// the custom "version" header was used by engine API before 20.10
|
||||
// (API 1.30) to switch between client- and server-side lookup of
|
||||
// image digests.
|
||||
headers["version"] = []string{cli.version}
|
||||
}
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/create", nil, service, headers)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
|
|
|
@ -3,11 +3,13 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
)
|
||||
|
||||
// ServiceUpdate updates a Service. The version number is required to avoid conflicting writes.
|
||||
|
@ -19,14 +21,6 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
|||
response = types.ServiceUpdateResponse{}
|
||||
)
|
||||
|
||||
headers := map[string][]string{
|
||||
"version": {cli.version},
|
||||
}
|
||||
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
|
||||
if options.RegistryAuthFrom != "" {
|
||||
query.Set("registryAuthFrom", options.RegistryAuthFrom)
|
||||
}
|
||||
|
@ -60,6 +54,16 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
|||
}
|
||||
}
|
||||
|
||||
headers := http.Header{}
|
||||
if versions.LessThan(cli.version, "1.30") {
|
||||
// the custom "version" header was used by engine API before 20.10
|
||||
// (API 1.30) to switch between client- and server-side lookup of
|
||||
// image digests.
|
||||
headers["version"] = []string{cli.version}
|
||||
}
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue