c55a4ac779
The io/ioutil package has been deprecated in Go 1.16. This commit replaces the existing io/ioutil functions with their new definitions in io and os packages. Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/api/server/httputils"
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/pkg/errors"
|
|
"gotest.tools/v3/assert"
|
|
)
|
|
|
|
func TestTLSCloseWriter(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var chErr chan error
|
|
ts := &httptest.Server{Config: &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
chErr = make(chan error, 1)
|
|
defer close(chErr)
|
|
if err := httputils.ParseForm(req); err != nil {
|
|
chErr <- errors.Wrap(err, "error parsing form")
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
r, rw, err := httputils.HijackConnection(w)
|
|
if err != nil {
|
|
chErr <- errors.Wrap(err, "error hijacking connection")
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer r.Close()
|
|
|
|
fmt.Fprint(rw, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\n")
|
|
|
|
buf := make([]byte, 5)
|
|
_, err = r.Read(buf)
|
|
if err != nil {
|
|
chErr <- errors.Wrap(err, "error reading from client")
|
|
return
|
|
}
|
|
_, err = rw.Write(buf)
|
|
if err != nil {
|
|
chErr <- errors.Wrap(err, "error writing to client")
|
|
return
|
|
}
|
|
})}}
|
|
|
|
var (
|
|
l net.Listener
|
|
err error
|
|
)
|
|
for i := 1024; i < 10000; i++ {
|
|
l, err = net.Listen("tcp4", fmt.Sprintf("127.0.0.1:%d", i))
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
assert.NilError(t, err)
|
|
|
|
ts.Listener = l
|
|
defer l.Close()
|
|
|
|
defer func() {
|
|
if chErr != nil {
|
|
assert.Assert(t, <-chErr)
|
|
}
|
|
}()
|
|
|
|
ts.StartTLS()
|
|
defer ts.Close()
|
|
|
|
serverURL, err := url.Parse(ts.URL)
|
|
assert.NilError(t, err)
|
|
|
|
client, err := NewClientWithOpts(WithHost("tcp://"+serverURL.Host), WithHTTPClient(ts.Client()))
|
|
assert.NilError(t, err)
|
|
|
|
resp, err := client.postHijacked(context.Background(), "/asdf", url.Values{}, nil, map[string][]string{"Content-Type": {"text/plain"}})
|
|
assert.NilError(t, err)
|
|
defer resp.Close()
|
|
|
|
if _, ok := resp.Conn.(types.CloseWriter); !ok {
|
|
t.Fatal("tls conn did not implement the CloseWrite interface")
|
|
}
|
|
|
|
_, err = resp.Conn.Write([]byte("hello"))
|
|
assert.NilError(t, err)
|
|
|
|
b, err := io.ReadAll(resp.Reader)
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, string(b) == "hello")
|
|
assert.Assert(t, resp.CloseWrite())
|
|
|
|
// This should error since writes are closed
|
|
_, err = resp.Conn.Write([]byte("no"))
|
|
assert.Assert(t, err != nil)
|
|
}
|