diff --git a/api/rest/client/client.go b/api/rest/client/client.go index 4c950ba8..8d891212 100644 --- a/api/rest/client/client.go +++ b/api/rest/client/client.go @@ -2,20 +2,13 @@ package client import ( "context" - "errors" "fmt" - "net" "net/http" "time" - p2phttp "github.com/hsanjuan/go-libp2p-http" logging "github.com/ipfs/go-log" - libp2p "github.com/libp2p/go-libp2p" host "github.com/libp2p/go-libp2p-host" - ipnet "github.com/libp2p/go-libp2p-interface-pnet" peer "github.com/libp2p/go-libp2p-peer" - peerstore "github.com/libp2p/go-libp2p-peerstore" - pnet "github.com/libp2p/go-libp2p-pnet" ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" manet "github.com/multiformats/go-multiaddr-net" @@ -80,7 +73,7 @@ type Client struct { ctx context.Context cancel func() config *Config - transport http.RoundTripper + transport *http.Transport net string hostname string client *http.Client @@ -119,49 +112,23 @@ func (c *Client) setupHTTPClient() error { c.config.Timeout = DefaultTimeout } - tr := c.defaultTransport() + var err error switch { case c.config.PeerAddr != nil: - pid, addr, err := multiaddrSplit(c.config.PeerAddr) - if err != nil { - return err - } - - var prot ipnet.Protector - if c.config.ProtectorKey != nil && len(c.config.ProtectorKey) > 0 { - if len(c.config.ProtectorKey) != 32 { - return errors.New("length of ProtectorKey should be 32") - } - var key [32]byte - copy(key[:], c.config.ProtectorKey) - - prot, err = pnet.NewV1ProtectorFromBytes(&key) - if err != nil { - return err - } - } - - h, err := libp2p.New(c.ctx, libp2p.PrivateNetwork(prot)) - if err != nil { - return err - } - - // This should resolve addr too. - h.Peerstore().AddAddr(pid, addr, peerstore.PermanentAddrTTL) - tr.RegisterProtocol("libp2p", p2phttp.NewTransport(h)) - c.net = "libp2p" - c.p2p = h - c.hostname = pid.Pretty() + err = c.enableLibp2p() case c.config.SSL: - tr.TLSClientConfig = tlsConfig(c.config.NoVerifyCert) - c.net = "https" + err = c.enableTLS() default: - c.net = "http" + c.defaultTransport() + } + + if err != nil { + return err } c.client = &http.Client{ - Transport: tr, + Transport: c.transport, Timeout: c.config.Timeout, } return nil @@ -214,21 +181,3 @@ func multiaddrSplit(addr ma.Multiaddr) (peer.ID, ma.Multiaddr, error) { } return peerID, decapAddr, nil } - -// This is essentially a http.DefaultTransport. We should not mess -// with it since it's a global variable, so we create our own. -// TODO: Allow more configuration options. -func (c *Client) defaultTransport() *http.Transport { - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } -} diff --git a/api/rest/client/tls.go b/api/rest/client/tls.go deleted file mode 100644 index 79fba423..00000000 --- a/api/rest/client/tls.go +++ /dev/null @@ -1,19 +0,0 @@ -package client - -import "crypto/tls" - -func tlsConfig(skipVerify bool) *tls.Config { - // based on https://github.com/denji/golang-tls - return &tls.Config{ - MinVersion: tls.VersionTLS12, - CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, - PreferServerCipherSuites: true, - CipherSuites: []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - tls.TLS_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_RSA_WITH_AES_256_CBC_SHA, - }, - InsecureSkipVerify: skipVerify, - } -} diff --git a/api/rest/client/transports.go b/api/rest/client/transports.go new file mode 100644 index 00000000..898f2484 --- /dev/null +++ b/api/rest/client/transports.go @@ -0,0 +1,90 @@ +package client + +import ( + "crypto/tls" + "errors" + "net" + "net/http" + "time" + + p2phttp "github.com/hsanjuan/go-libp2p-http" + libp2p "github.com/libp2p/go-libp2p" + ipnet "github.com/libp2p/go-libp2p-interface-pnet" + peerstore "github.com/libp2p/go-libp2p-peerstore" + pnet "github.com/libp2p/go-libp2p-pnet" +) + +// This is essentially a http.DefaultTransport. We should not mess +// with it since it's a global variable, and we don't know who else uses +// it, so we create our own. +// TODO: Allow more configuration options. +func (c *Client) defaultTransport() { + c.transport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + } + c.net = "http" +} + +func (c *Client) enableLibp2p() error { + c.defaultTransport() + + pid, addr, err := multiaddrSplit(c.config.PeerAddr) + if err != nil { + return err + } + + var prot ipnet.Protector + if c.config.ProtectorKey != nil && len(c.config.ProtectorKey) > 0 { + if len(c.config.ProtectorKey) != 32 { + return errors.New("length of ProtectorKey should be 32") + } + var key [32]byte + copy(key[:], c.config.ProtectorKey) + + prot, err = pnet.NewV1ProtectorFromBytes(&key) + if err != nil { + return err + } + } + + h, err := libp2p.New(c.ctx, libp2p.PrivateNetwork(prot)) + if err != nil { + return err + } + + // This should resolve addr too. + h.Peerstore().AddAddr(pid, addr, peerstore.PermanentAddrTTL) + c.transport.RegisterProtocol("libp2p", p2phttp.NewTransport(h)) + c.net = "libp2p" + c.p2p = h + c.hostname = pid.Pretty() + return nil +} + +func (c *Client) enableTLS() error { + c.defaultTransport() + // based on https://github.com/denji/golang-tls + c.transport.TLSClientConfig = &tls.Config{ + MinVersion: tls.VersionTLS12, + CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, + PreferServerCipherSuites: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + }, + InsecureSkipVerify: c.config.NoVerifyCert, + } + c.net = "https" + return nil +}