Skip to content

Commit

Permalink
fix(deps): replace deprecated httputil.ClientConn and hijack function…
Browse files Browse the repository at this point in the history
…ality

Fix #919

BREAKING CHANGE: Remove usage of deprecated httputil.ClientConn in favor of net/http.Client
per golang/go#28030. Since HTTP connection hijacking is no longer supported in modern Go,
implemented alternative approach for bidirectional TCP communication.
  • Loading branch information
briceamen committed Dec 12, 2024
1 parent f1c2b18 commit dc395d8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 29 deletions.
50 changes: 27 additions & 23 deletions apps/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package apps

import (
"archive/tar"
"bufio"
"bytes"
"compress/gzip"
"context"
Expand All @@ -12,7 +13,6 @@ import (
"mime/multipart"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/signal"
Expand Down Expand Up @@ -322,42 +322,43 @@ func (runCtx *runContext) connectToRunServer(ctx context.Context) (*http.Respons
return nil, nil, errgo.New("No attach URL to connect to")
}

req, err := http.NewRequest("CONNECT", runCtx.attachURL, nil)
url, err := url.Parse(runCtx.attachURL)
if err != nil {
return nil, nil, errgo.Mask(err, errgo.Any)
}
token, err := runCtx.scalingoClient.GetAccessToken(ctx)

// Establish an initial TCP connection
conn, err := net.Dial("tcp", url.Host)
if err != nil {
return nil, nil, errgo.Notef(err, "fail to generate auth")
return nil, nil, errgo.Mask(err, errgo.Any)
}
req.SetBasicAuth("", token)

url, err := url.Parse(runCtx.attachURL)
// Wrap with TLS if using HTTPS
if url.Scheme == "https" {
tlsConfig := config.TLSConfig.Clone()
tlsConfig.ServerName = strings.Split(url.Host, ":")[0]
conn = tls.Client(conn, tlsConfig)
}

req, err := http.NewRequest("CONNECT", runCtx.attachURL, nil)
if err != nil {
return nil, nil, errgo.Mask(err, errgo.Any)
}

dial, err := net.Dial("tcp", url.Host)
token, err := runCtx.scalingoClient.GetAccessToken(ctx)
if err != nil {
return nil, nil, errgo.Mask(err, errgo.Any)
return nil, nil, errgo.Notef(err, "fail to generate auth")
}
req.SetBasicAuth("", token)

var conn *httputil.ClientConn
if url.Scheme == "https" {
host := strings.Split(url.Host, ":")[0]
tlsConfig := config.TLSConfig.Clone()
tlsConfig.ServerName = host
tlsConn := tls.Client(dial, tlsConfig)
conn = httputil.NewClientConn(tlsConn, nil)
} else if url.Scheme == "http" {
conn = httputil.NewClientConn(dial, nil)
} else {
return nil, nil, errgo.Newf("invalid scheme format %s", url.Scheme)
// Write the HTTP request directly to the connection
err = req.Write(conn)
if err != nil {
return nil, nil, errgo.Mask(err, errgo.Any)
}

res, err := conn.Do(req)
if err != httputil.ErrPersistEOF && err != nil {
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
if err != nil {
if err, ok := err.(*net.OpError); ok {
if err.Err.Error() == "record overflow" {
return nil, nil, errgo.Newf(
Expand All @@ -371,8 +372,11 @@ func (runCtx *runContext) connectToRunServer(ctx context.Context) (*http.Respons
return nil, nil, errgo.Mask(err, errgo.Any)
}

connection, _ := conn.Hijack()
return res, connection, nil
if resp.StatusCode != http.StatusOK {
return resp, nil, nil
}

return resp, conn, nil
}

func (runCtx *runContext) validateFiles(files []string) error {
Expand Down
4 changes: 3 additions & 1 deletion apps/run_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package apps

import "testing"
import (
"testing"
)

func TestParseEnvVar(t *testing.T) {
ctx := &runContext{}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.18.0
github.com/go-git/go-git/v5 v5.12.0
github.com/golang/mock v1.6.0
github.com/google/go-github/v47 v47.1.0
github.com/gorilla/websocket v1.5.3
github.com/gosuri/uilive v0.0.4
Expand All @@ -27,7 +28,7 @@ require (
github.com/urfave/cli/v2 v2.27.5
golang.org/x/crypto v0.29.0
golang.org/x/term v0.26.0
golang.org/x/text v0.20.0
golang.org/x/text v0.21.0
gopkg.in/errgo.v1 v1.0.1
)

Expand All @@ -45,7 +46,6 @@ require (
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
Expand Down
2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ golang.org/x/sys/windows
# golang.org/x/term v0.26.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.20.0
# golang.org/x/text v0.21.0
## explicit; go 1.18
golang.org/x/text/cases
golang.org/x/text/internal
Expand Down

0 comments on commit dc395d8

Please sign in to comment.