Browse code

api/types: move HijackedResponse into client

Signed-off-by: Cory Snider <csnider@mirantis.com>

Cory Snider authored on 2025/07/25 04:56:41
Showing 13 changed files
... ...
@@ -1,51 +1,9 @@
1 1
 package types
2 2
 
3 3
 import (
4
-	"bufio"
5 4
 	"context"
6
-	"net"
7 5
 )
8 6
 
9
-// NewHijackedResponse initializes a [HijackedResponse] type.
10
-func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse {
11
-	return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType}
12
-}
13
-
14
-// HijackedResponse holds connection information for a hijacked request.
15
-type HijackedResponse struct {
16
-	mediaType string
17
-	Conn      net.Conn
18
-	Reader    *bufio.Reader
19
-}
20
-
21
-// Close closes the hijacked connection and reader.
22
-func (h *HijackedResponse) Close() {
23
-	h.Conn.Close()
24
-}
25
-
26
-// MediaType let client know if HijackedResponse hold a raw or multiplexed stream.
27
-// returns false if HTTP Content-Type is not relevant, and container must be inspected
28
-func (h *HijackedResponse) MediaType() (string, bool) {
29
-	if h.mediaType == "" {
30
-		return "", false
31
-	}
32
-	return h.mediaType, true
33
-}
34
-
35
-// CloseWriter is an interface that implements structs
36
-// that close input streams to prevent from writing.
37
-type CloseWriter interface {
38
-	CloseWrite() error
39
-}
40
-
41
-// CloseWrite closes a readWriter for writing.
42
-func (h *HijackedResponse) CloseWrite() error {
43
-	if conn, ok := h.Conn.(CloseWriter); ok {
44
-		return conn.CloseWrite()
45
-	}
46
-	return nil
47
-}
48
-
49 7
 // PluginRemoveOptions holds parameters to remove plugins.
50 8
 type PluginRemoveOptions struct {
51 9
 	Force bool
... ...
@@ -64,11 +64,11 @@ type HijackDialer interface {
64 64
 
65 65
 // ContainerAPIClient defines API client methods for the containers
66 66
 type ContainerAPIClient interface {
67
-	ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error)
67
+	ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (HijackedResponse, error)
68 68
 	ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (container.CommitResponse, error)
69 69
 	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
70 70
 	ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error)
71
-	ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (types.HijackedResponse, error)
71
+	ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (HijackedResponse, error)
72 72
 	ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error)
73 73
 	ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error)
74 74
 	ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"net/http"
6 6
 	"net/url"
7 7
 
8
-	"github.com/moby/moby/api/types"
9 8
 	"github.com/moby/moby/api/types/container"
10 9
 )
11 10
 
... ...
@@ -33,10 +32,10 @@ import (
33 33
 //
34 34
 // You can use github.com/moby/moby/api/stdcopy.StdCopy to demultiplex this
35 35
 // stream.
36
-func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
36
+func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (HijackedResponse, error) {
37 37
 	containerID, err := trimID("container", containerID)
38 38
 	if err != nil {
39
-		return types.HijackedResponse{}, err
39
+		return HijackedResponse{}, err
40 40
 	}
41 41
 
42 42
 	query := url.Values{}
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"encoding/json"
6 6
 	"net/http"
7 7
 
8
-	"github.com/moby/moby/api/types"
9 8
 	"github.com/moby/moby/api/types/container"
10 9
 	"github.com/moby/moby/api/types/versions"
11 10
 )
... ...
@@ -80,7 +79,7 @@ func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config
80 80
 // You can use [github.com/moby/moby/api/stdcopy.StdCopy] to demultiplex this
81 81
 // stream. Refer to [Client.ContainerAttach] for details about the multiplexed
82 82
 // stream.
83
-func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config container.ExecAttachOptions) (types.HijackedResponse, error) {
83
+func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config container.ExecAttachOptions) (HijackedResponse, error) {
84 84
 	if versions.LessThan(cli.ClientVersion(), "1.42") {
85 85
 		config.ConsoleSize = nil
86 86
 	}
... ...
@@ -9,25 +9,24 @@ import (
9 9
 	"net/url"
10 10
 	"time"
11 11
 
12
-	"github.com/moby/moby/api/types"
13 12
 	"github.com/moby/moby/api/types/versions"
14 13
 	"github.com/pkg/errors"
15 14
 	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
16 15
 )
17 16
 
18 17
 // postHijacked sends a POST request and hijacks the connection.
19
-func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
18
+func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (HijackedResponse, error) {
20 19
 	jsonBody, err := jsonEncode(body)
21 20
 	if err != nil {
22
-		return types.HijackedResponse{}, err
21
+		return HijackedResponse{}, err
23 22
 	}
24 23
 	req, err := cli.buildRequest(ctx, http.MethodPost, cli.getAPIPath(ctx, path, query), jsonBody, headers)
25 24
 	if err != nil {
26
-		return types.HijackedResponse{}, err
25
+		return HijackedResponse{}, err
27 26
 	}
28 27
 	conn, mediaType, err := setupHijackConn(cli.dialer(), req, "tcp")
29 28
 	if err != nil {
30
-		return types.HijackedResponse{}, err
29
+		return HijackedResponse{}, err
31 30
 	}
32 31
 
33 32
 	if versions.LessThan(cli.ClientVersion(), "1.42") {
... ...
@@ -35,7 +34,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
35 35
 		mediaType = ""
36 36
 	}
37 37
 
38
-	return types.NewHijackedResponse(conn, mediaType), nil
38
+	return NewHijackedResponse(conn, mediaType), nil
39 39
 }
40 40
 
41 41
 // DialHijack returns a hijacked connection with negotiated protocol proto.
... ...
@@ -91,7 +90,7 @@ func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.R
91 91
 		// If there is buffered content, wrap the connection.  We return an
92 92
 		// object that implements CloseWrite if the underlying connection
93 93
 		// implements it.
94
-		if _, ok := hc.Conn.(types.CloseWriter); ok {
94
+		if _, ok := hc.Conn.(CloseWriter); ok {
95 95
 			conn = &hijackedConnCloseWriter{hc}
96 96
 		} else {
97 97
 			conn = hc
... ...
@@ -131,9 +130,49 @@ type hijackedConnCloseWriter struct {
131 131
 	*hijackedConn
132 132
 }
133 133
 
134
-var _ types.CloseWriter = &hijackedConnCloseWriter{}
134
+var _ CloseWriter = &hijackedConnCloseWriter{}
135 135
 
136 136
 func (c *hijackedConnCloseWriter) CloseWrite() error {
137
-	conn := c.Conn.(types.CloseWriter)
137
+	conn := c.Conn.(CloseWriter)
138 138
 	return conn.CloseWrite()
139 139
 }
140
+
141
+// NewHijackedResponse initializes a [HijackedResponse] type.
142
+func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse {
143
+	return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType}
144
+}
145
+
146
+// HijackedResponse holds connection information for a hijacked request.
147
+type HijackedResponse struct {
148
+	mediaType string
149
+	Conn      net.Conn
150
+	Reader    *bufio.Reader
151
+}
152
+
153
+// Close closes the hijacked connection and reader.
154
+func (h *HijackedResponse) Close() {
155
+	h.Conn.Close()
156
+}
157
+
158
+// MediaType let client know if HijackedResponse hold a raw or multiplexed stream.
159
+// returns false if HTTP Content-Type is not relevant, and container must be inspected
160
+func (h *HijackedResponse) MediaType() (string, bool) {
161
+	if h.mediaType == "" {
162
+		return "", false
163
+	}
164
+	return h.mediaType, true
165
+}
166
+
167
+// CloseWriter is an interface that implements structs
168
+// that close input streams to prevent from writing.
169
+type CloseWriter interface {
170
+	CloseWrite() error
171
+}
172
+
173
+// CloseWrite closes a readWriter for writing.
174
+func (h *HijackedResponse) CloseWrite() error {
175
+	if conn, ok := h.Conn.(CloseWriter); ok {
176
+		return conn.CloseWrite()
177
+	}
178
+	return nil
179
+}
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"testing"
13 13
 	"time"
14 14
 
15
-	"github.com/moby/moby/api/types"
16 15
 	"gotest.tools/v3/assert"
17 16
 	is "gotest.tools/v3/assert/cmp"
18 17
 )
... ...
@@ -94,7 +93,7 @@ func TestTLSCloseWriter(t *testing.T) {
94 94
 	assert.NilError(t, err)
95 95
 	defer resp.Close()
96 96
 
97
-	_, ok := resp.Conn.(types.CloseWriter)
97
+	_, ok := resp.Conn.(CloseWriter)
98 98
 	assert.Check(t, ok, "tls conn did not implement the CloseWrite interface")
99 99
 
100 100
 	_, err = resp.Conn.Write([]byte("hello"))
... ...
@@ -9,7 +9,6 @@ import (
9 9
 	"testing"
10 10
 
11 11
 	"github.com/moby/moby/api/stdcopy"
12
-	"github.com/moby/moby/api/types"
13 12
 	"github.com/moby/moby/api/types/container"
14 13
 	"github.com/moby/moby/api/types/network"
15 14
 	"github.com/moby/moby/client"
... ...
@@ -129,7 +128,7 @@ type streams struct {
129 129
 // demultiplexStreams starts a goroutine to demultiplex stdout and stderr from the types.HijackedResponse resp and
130 130
 // waits until either multiplexed stream reaches EOF or the context expires. It unconditionally closes resp and waits
131 131
 // until the demultiplexing goroutine has finished its work before returning.
132
-func demultiplexStreams(ctx context.Context, resp types.HijackedResponse) (streams, error) {
132
+func demultiplexStreams(ctx context.Context, resp client.HijackedResponse) (streams, error) {
133 133
 	var s streams
134 134
 	outputDone := make(chan error, 1)
135 135
 
... ...
@@ -8,7 +8,6 @@ import (
8 8
 
9 9
 	"github.com/docker/docker/testutil/daemon"
10 10
 	"github.com/docker/docker/testutil/environment"
11
-	"github.com/moby/moby/api/types"
12 11
 	"github.com/moby/moby/api/types/container"
13 12
 	"github.com/moby/moby/api/types/filters"
14 13
 	swarmtypes "github.com/moby/moby/api/types/swarm"
... ...
@@ -212,7 +211,7 @@ func GetRunningTasks(ctx context.Context, t *testing.T, c client.ServiceAPIClien
212 212
 }
213 213
 
214 214
 // ExecTask runs the passed in exec config on the given task
215
-func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, options container.ExecOptions) types.HijackedResponse {
215
+func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, options container.ExecOptions) client.HijackedResponse {
216 216
 	t.Helper()
217 217
 	apiClient := d.NewClientT(t)
218 218
 	defer apiClient.Close()
... ...
@@ -1,51 +1,9 @@
1 1
 package types
2 2
 
3 3
 import (
4
-	"bufio"
5 4
 	"context"
6
-	"net"
7 5
 )
8 6
 
9
-// NewHijackedResponse initializes a [HijackedResponse] type.
10
-func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse {
11
-	return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType}
12
-}
13
-
14
-// HijackedResponse holds connection information for a hijacked request.
15
-type HijackedResponse struct {
16
-	mediaType string
17
-	Conn      net.Conn
18
-	Reader    *bufio.Reader
19
-}
20
-
21
-// Close closes the hijacked connection and reader.
22
-func (h *HijackedResponse) Close() {
23
-	h.Conn.Close()
24
-}
25
-
26
-// MediaType let client know if HijackedResponse hold a raw or multiplexed stream.
27
-// returns false if HTTP Content-Type is not relevant, and container must be inspected
28
-func (h *HijackedResponse) MediaType() (string, bool) {
29
-	if h.mediaType == "" {
30
-		return "", false
31
-	}
32
-	return h.mediaType, true
33
-}
34
-
35
-// CloseWriter is an interface that implements structs
36
-// that close input streams to prevent from writing.
37
-type CloseWriter interface {
38
-	CloseWrite() error
39
-}
40
-
41
-// CloseWrite closes a readWriter for writing.
42
-func (h *HijackedResponse) CloseWrite() error {
43
-	if conn, ok := h.Conn.(CloseWriter); ok {
44
-		return conn.CloseWrite()
45
-	}
46
-	return nil
47
-}
48
-
49 7
 // PluginRemoveOptions holds parameters to remove plugins.
50 8
 type PluginRemoveOptions struct {
51 9
 	Force bool
... ...
@@ -64,11 +64,11 @@ type HijackDialer interface {
64 64
 
65 65
 // ContainerAPIClient defines API client methods for the containers
66 66
 type ContainerAPIClient interface {
67
-	ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error)
67
+	ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (HijackedResponse, error)
68 68
 	ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (container.CommitResponse, error)
69 69
 	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
70 70
 	ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error)
71
-	ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (types.HijackedResponse, error)
71
+	ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (HijackedResponse, error)
72 72
 	ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error)
73 73
 	ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error)
74 74
 	ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"net/http"
6 6
 	"net/url"
7 7
 
8
-	"github.com/moby/moby/api/types"
9 8
 	"github.com/moby/moby/api/types/container"
10 9
 )
11 10
 
... ...
@@ -33,10 +32,10 @@ import (
33 33
 //
34 34
 // You can use github.com/moby/moby/api/stdcopy.StdCopy to demultiplex this
35 35
 // stream.
36
-func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
36
+func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (HijackedResponse, error) {
37 37
 	containerID, err := trimID("container", containerID)
38 38
 	if err != nil {
39
-		return types.HijackedResponse{}, err
39
+		return HijackedResponse{}, err
40 40
 	}
41 41
 
42 42
 	query := url.Values{}
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"encoding/json"
6 6
 	"net/http"
7 7
 
8
-	"github.com/moby/moby/api/types"
9 8
 	"github.com/moby/moby/api/types/container"
10 9
 	"github.com/moby/moby/api/types/versions"
11 10
 )
... ...
@@ -80,7 +79,7 @@ func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config
80 80
 // You can use [github.com/moby/moby/api/stdcopy.StdCopy] to demultiplex this
81 81
 // stream. Refer to [Client.ContainerAttach] for details about the multiplexed
82 82
 // stream.
83
-func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config container.ExecAttachOptions) (types.HijackedResponse, error) {
83
+func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config container.ExecAttachOptions) (HijackedResponse, error) {
84 84
 	if versions.LessThan(cli.ClientVersion(), "1.42") {
85 85
 		config.ConsoleSize = nil
86 86
 	}
... ...
@@ -9,25 +9,24 @@ import (
9 9
 	"net/url"
10 10
 	"time"
11 11
 
12
-	"github.com/moby/moby/api/types"
13 12
 	"github.com/moby/moby/api/types/versions"
14 13
 	"github.com/pkg/errors"
15 14
 	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
16 15
 )
17 16
 
18 17
 // postHijacked sends a POST request and hijacks the connection.
19
-func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
18
+func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (HijackedResponse, error) {
20 19
 	jsonBody, err := jsonEncode(body)
21 20
 	if err != nil {
22
-		return types.HijackedResponse{}, err
21
+		return HijackedResponse{}, err
23 22
 	}
24 23
 	req, err := cli.buildRequest(ctx, http.MethodPost, cli.getAPIPath(ctx, path, query), jsonBody, headers)
25 24
 	if err != nil {
26
-		return types.HijackedResponse{}, err
25
+		return HijackedResponse{}, err
27 26
 	}
28 27
 	conn, mediaType, err := setupHijackConn(cli.dialer(), req, "tcp")
29 28
 	if err != nil {
30
-		return types.HijackedResponse{}, err
29
+		return HijackedResponse{}, err
31 30
 	}
32 31
 
33 32
 	if versions.LessThan(cli.ClientVersion(), "1.42") {
... ...
@@ -35,7 +34,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
35 35
 		mediaType = ""
36 36
 	}
37 37
 
38
-	return types.NewHijackedResponse(conn, mediaType), nil
38
+	return NewHijackedResponse(conn, mediaType), nil
39 39
 }
40 40
 
41 41
 // DialHijack returns a hijacked connection with negotiated protocol proto.
... ...
@@ -91,7 +90,7 @@ func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.R
91 91
 		// If there is buffered content, wrap the connection.  We return an
92 92
 		// object that implements CloseWrite if the underlying connection
93 93
 		// implements it.
94
-		if _, ok := hc.Conn.(types.CloseWriter); ok {
94
+		if _, ok := hc.Conn.(CloseWriter); ok {
95 95
 			conn = &hijackedConnCloseWriter{hc}
96 96
 		} else {
97 97
 			conn = hc
... ...
@@ -131,9 +130,49 @@ type hijackedConnCloseWriter struct {
131 131
 	*hijackedConn
132 132
 }
133 133
 
134
-var _ types.CloseWriter = &hijackedConnCloseWriter{}
134
+var _ CloseWriter = &hijackedConnCloseWriter{}
135 135
 
136 136
 func (c *hijackedConnCloseWriter) CloseWrite() error {
137
-	conn := c.Conn.(types.CloseWriter)
137
+	conn := c.Conn.(CloseWriter)
138 138
 	return conn.CloseWrite()
139 139
 }
140
+
141
+// NewHijackedResponse initializes a [HijackedResponse] type.
142
+func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse {
143
+	return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType}
144
+}
145
+
146
+// HijackedResponse holds connection information for a hijacked request.
147
+type HijackedResponse struct {
148
+	mediaType string
149
+	Conn      net.Conn
150
+	Reader    *bufio.Reader
151
+}
152
+
153
+// Close closes the hijacked connection and reader.
154
+func (h *HijackedResponse) Close() {
155
+	h.Conn.Close()
156
+}
157
+
158
+// MediaType let client know if HijackedResponse hold a raw or multiplexed stream.
159
+// returns false if HTTP Content-Type is not relevant, and container must be inspected
160
+func (h *HijackedResponse) MediaType() (string, bool) {
161
+	if h.mediaType == "" {
162
+		return "", false
163
+	}
164
+	return h.mediaType, true
165
+}
166
+
167
+// CloseWriter is an interface that implements structs
168
+// that close input streams to prevent from writing.
169
+type CloseWriter interface {
170
+	CloseWrite() error
171
+}
172
+
173
+// CloseWrite closes a readWriter for writing.
174
+func (h *HijackedResponse) CloseWrite() error {
175
+	if conn, ok := h.Conn.(CloseWriter); ok {
176
+		return conn.CloseWrite()
177
+	}
178
+	return nil
179
+}