rest/client: add support for libp2p-tunneled http.
This adds support for libp2p-tunneled http to the rest api component. If PeerAddr is specified in the configuration, then we will create a libp2p host and communicate with the API using that. Tests run now in both http and libp2p mode. Note: pnet support not included, but coming up License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
This commit is contained in:
parent
fb4bda8880
commit
bbe2407531
|
@ -3,10 +3,16 @@ package client
|
|||
import (
|
||||
"context"
|
||||
"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"
|
||||
peer "github.com/libp2p/go-libp2p-peer"
|
||||
peerstore "github.com/libp2p/go-libp2p-peerstore"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
madns "github.com/multiformats/go-multiaddr-dns"
|
||||
manet "github.com/multiformats/go-multiaddr-net"
|
||||
|
@ -25,7 +31,7 @@ var logger = logging.Logger(loggingFacility)
|
|||
// Config allows to configure the parameters to connect
|
||||
// to the ipfs-cluster REST API.
|
||||
type Config struct {
|
||||
// Enable SSL support
|
||||
// Enable SSL support. Only valid without PeerAddr.
|
||||
SSL bool
|
||||
// Skip certificate verification (insecure)
|
||||
NoVerifyCert bool
|
||||
|
@ -35,14 +41,25 @@ type Config struct {
|
|||
Password string
|
||||
|
||||
// The ipfs-cluster REST API endpoint in multiaddress form
|
||||
// (takes precedence over host:port)
|
||||
// (takes precedence over host:port). Only valid without PeerAddr.
|
||||
APIAddr ma.Multiaddr
|
||||
|
||||
// REST API endpoint host and port. Only valid without
|
||||
// APIAddr
|
||||
// APIAddr and PeerAddr
|
||||
Host string
|
||||
Port string
|
||||
|
||||
// The ipfs-cluster REST API peer address (usually
|
||||
// the same as the cluster peer). This will use libp2p
|
||||
// to tunnel HTTP requests, thus getting encryption for
|
||||
// free. It overseeds APIAddr, Host/Port, and SSL configurations.
|
||||
PeerAddr ma.Multiaddr
|
||||
|
||||
// If PeerAddr is provided, and the peer uses private networks
|
||||
// (pnet), then we need to provide the key. If the peer is the
|
||||
// cluster peer, this corresponds to the cluster secret.
|
||||
ProtectorKey []byte
|
||||
|
||||
// Define timeout for network operations
|
||||
Timeout time.Duration
|
||||
|
||||
|
@ -61,69 +78,140 @@ type Client struct {
|
|||
cancel func()
|
||||
config *Config
|
||||
transport http.RoundTripper
|
||||
urlPrefix string
|
||||
net string
|
||||
hostname string
|
||||
client *http.Client
|
||||
p2p host.Host
|
||||
}
|
||||
|
||||
// NewClient initializes a client given a Config.
|
||||
func NewClient(cfg *Config) (*Client, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
var urlPrefix = ""
|
||||
var tr http.RoundTripper
|
||||
if cfg.SSL {
|
||||
tr = newTLSTransport(cfg.NoVerifyCert)
|
||||
urlPrefix += "https://"
|
||||
} else {
|
||||
tr = http.DefaultTransport
|
||||
urlPrefix += "http://"
|
||||
client := &Client{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
}
|
||||
|
||||
if cfg.Timeout == 0 {
|
||||
cfg.Timeout = DefaultTimeout
|
||||
err := client.setupHTTPClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// When no host/port/multiaddress defined, we set the default
|
||||
if cfg.APIAddr == nil && cfg.Host == "" && cfg.Port == "" {
|
||||
cfg.APIAddr, _ = ma.NewMultiaddr(DefaultAPIAddr)
|
||||
err = client.setupHostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var host string
|
||||
// APIAddr takes preference. If it exists, it's resolved and dial args
|
||||
// extracted. Otherwise, host port is used.
|
||||
if cfg.APIAddr != nil {
|
||||
// Resolve multiaddress just in case and extract host:port
|
||||
resolveCtx, cancel := context.WithTimeout(ctx, cfg.Timeout)
|
||||
defer cancel()
|
||||
resolved, err := madns.Resolve(resolveCtx, cfg.APIAddr)
|
||||
cfg.APIAddr = resolved[0]
|
||||
_, host, err = manet.DialArgs(cfg.APIAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
host = fmt.Sprintf("%s:%s", cfg.Host, cfg.Port)
|
||||
}
|
||||
|
||||
urlPrefix += host
|
||||
|
||||
if lvl := cfg.LogLevel; lvl != "" {
|
||||
logging.SetLogLevel(loggingFacility, lvl)
|
||||
} else {
|
||||
logging.SetLogLevel(loggingFacility, DefaultLogLevel)
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: cfg.Timeout,
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Client) setupHTTPClient() error {
|
||||
if c.config.Timeout == 0 {
|
||||
c.config.Timeout = DefaultTimeout
|
||||
}
|
||||
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
cancel: nil,
|
||||
urlPrefix: urlPrefix,
|
||||
transport: tr,
|
||||
config: cfg,
|
||||
client: client,
|
||||
}, nil
|
||||
tr := c.defaultTransport()
|
||||
|
||||
switch {
|
||||
case c.config.PeerAddr != nil:
|
||||
pid, addr, err := multiaddrSplit(c.config.PeerAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h, err := libp2p.New(c.ctx)
|
||||
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()
|
||||
case c.config.SSL:
|
||||
tr.TLSClientConfig = tlsConfig(c.config.NoVerifyCert)
|
||||
c.net = "https"
|
||||
default:
|
||||
c.net = "http"
|
||||
}
|
||||
|
||||
c.client = &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: c.config.Timeout,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) setupHostname() error {
|
||||
// When no host/port/multiaddress defined, we set the default
|
||||
if c.config.APIAddr == nil && c.config.Host == "" && c.config.Port == "" {
|
||||
c.config.APIAddr, _ = ma.NewMultiaddr(DefaultAPIAddr)
|
||||
}
|
||||
|
||||
// PeerAddr takes precedence over APIAddr. APIAddr takes precedence
|
||||
// over Host/Port. APIAddr is resolved and dial args
|
||||
// extracted.
|
||||
switch {
|
||||
case c.config.PeerAddr != nil:
|
||||
// Taken care of in setupHTTPClient
|
||||
case c.config.APIAddr != nil:
|
||||
// Resolve multiaddress just in case and extract host:port
|
||||
resolveCtx, cancel := context.WithTimeout(c.ctx, c.config.Timeout)
|
||||
defer cancel()
|
||||
resolved, err := madns.Resolve(resolveCtx, c.config.APIAddr)
|
||||
c.config.APIAddr = resolved[0]
|
||||
_, c.hostname, err = manet.DialArgs(c.config.APIAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
c.hostname = fmt.Sprintf("%s:%s", c.config.Host, c.config.Port)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func multiaddrSplit(addr ma.Multiaddr) (peer.ID, ma.Multiaddr, error) {
|
||||
pid, err := addr.ValueForProtocol(ma.P_IPFS)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid peer multiaddress: %s: %s", addr, err)
|
||||
logger.Error(err)
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
ipfs, _ := ma.NewMultiaddr("/ipfs/" + pid)
|
||||
decapAddr := addr.Decapsulate(ipfs)
|
||||
|
||||
peerID, err := peer.IDB58Decode(pid)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid peer ID in multiaddress: %s: %s", pid, err)
|
||||
logger.Error(err)
|
||||
return "", nil, err
|
||||
}
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/ipfs/ipfs-cluster/api/rest"
|
||||
"github.com/ipfs/ipfs-cluster/test"
|
||||
|
||||
libp2p "github.com/libp2p/go-libp2p"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
func testAPI(t *testing.T) *rest.API {
|
||||
|
@ -17,9 +19,17 @@ func testAPI(t *testing.T) *rest.API {
|
|||
|
||||
cfg := &rest.Config{}
|
||||
cfg.Default()
|
||||
cfg.ListenAddr = apiMAddr
|
||||
cfg.HTTPListenAddr = apiMAddr
|
||||
|
||||
rest, err := rest.NewAPI(cfg)
|
||||
h, err := libp2p.New(
|
||||
context.Background(),
|
||||
libp2p.ListenAddrs(apiMAddr),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rest, err := rest.NewAPIWithHost(cfg, h)
|
||||
if err != nil {
|
||||
t.Fatal("should be able to create a new Api: ", err)
|
||||
}
|
||||
|
@ -28,16 +38,26 @@ func testAPI(t *testing.T) *rest.API {
|
|||
return rest
|
||||
}
|
||||
|
||||
func shutdown(a *rest.API) {
|
||||
a.Shutdown()
|
||||
a.Host().Close()
|
||||
}
|
||||
|
||||
func apiMAddr(a *rest.API) ma.Multiaddr {
|
||||
hostPort := strings.Split(a.HTTPAddress(), ":")
|
||||
listen, _ := a.HTTPAddress()
|
||||
hostPort := strings.Split(listen, ":")
|
||||
|
||||
addr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%s", hostPort[1]))
|
||||
return addr
|
||||
}
|
||||
|
||||
func testClient(t *testing.T) (*Client, *rest.API) {
|
||||
api := testAPI(t)
|
||||
func peerMAddr(a *rest.API) ma.Multiaddr {
|
||||
listenAddr := a.Host().Addrs()[0]
|
||||
ipfsAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", a.Host().ID().Pretty()))
|
||||
return listenAddr.Encapsulate(ipfsAddr)
|
||||
}
|
||||
|
||||
func testClientHTTP(t *testing.T, api *rest.API) *Client {
|
||||
cfg := &Config{
|
||||
APIAddr: apiMAddr(api),
|
||||
DisableKeepAlives: true,
|
||||
|
@ -47,12 +67,35 @@ func testClient(t *testing.T) (*Client, *rest.API) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return c, api
|
||||
return c
|
||||
}
|
||||
|
||||
func testClientLibp2p(t *testing.T, api *rest.API) *Client {
|
||||
cfg := &Config{
|
||||
PeerAddr: peerMAddr(api),
|
||||
DisableKeepAlives: true,
|
||||
}
|
||||
c, err := NewClient(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
_, api := testClient(t)
|
||||
api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
c := testClientHTTP(t, api)
|
||||
if c.p2p != nil {
|
||||
t.Error("should not use a libp2p host")
|
||||
}
|
||||
|
||||
c = testClientLibp2p(t, api)
|
||||
if c.p2p == nil {
|
||||
t.Error("expected a libp2p host")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultAddress(t *testing.T) {
|
||||
|
@ -64,12 +107,12 @@ func TestDefaultAddress(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.urlPrefix != "http://127.0.0.1:9094" {
|
||||
if c.hostname != "127.0.0.1:9094" {
|
||||
t.Error("default should be used")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiaddressPreference(t *testing.T) {
|
||||
func TestMultiaddressPrecedence(t *testing.T) {
|
||||
addr, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/1234")
|
||||
cfg := &Config{
|
||||
APIAddr: addr,
|
||||
|
@ -81,7 +124,7 @@ func TestMultiaddressPreference(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.urlPrefix != "http://1.2.3.4:1234" {
|
||||
if c.hostname != "1.2.3.4:1234" {
|
||||
t.Error("APIAddr should be used")
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +140,7 @@ func TestHostPort(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.urlPrefix != "http://localhost:9094" {
|
||||
if c.hostname != "localhost:9094" {
|
||||
t.Error("Host Port should be used")
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +157,26 @@ func TestDNSMultiaddress(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.urlPrefix != "http://127.0.0.1:1234" {
|
||||
if c.hostname != "127.0.0.1:1234" {
|
||||
t.Error("bad resolved address")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeerAddress(t *testing.T) {
|
||||
addr2, _ := ma.NewMultiaddr("/dns4/localhost/tcp/1234")
|
||||
peerAddr, _ := ma.NewMultiaddr("/dns4/localhost/tcp/1234/ipfs/QmP7R7gWEnruNePxmCa9GBa4VmUNexLVnb1v47R8Gyo3LP")
|
||||
cfg := &Config{
|
||||
APIAddr: addr2,
|
||||
Host: "localhost",
|
||||
Port: "9094",
|
||||
DisableKeepAlives: true,
|
||||
PeerAddr: peerAddr,
|
||||
}
|
||||
c, err := NewClient(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.hostname != "QmP7R7gWEnruNePxmCa9GBa4VmUNexLVnb1v47R8Gyo3LP" || c.net != "libp2p" {
|
||||
t.Error("bad resolved address")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,224 +3,306 @@ package client
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/ipfs-cluster/api/rest"
|
||||
"github.com/ipfs/ipfs-cluster/test"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/ipfs/ipfs-cluster/test"
|
||||
)
|
||||
|
||||
func testClients(t *testing.T, api *rest.API, f func(*testing.T, *Client)) {
|
||||
t.Run("libp2p", func(t *testing.T) {
|
||||
f(t, testClientLibp2p(t, api))
|
||||
})
|
||||
t.Run("http", func(t *testing.T) {
|
||||
f(t, testClientHTTP(t, api))
|
||||
})
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
v, err := c.Version()
|
||||
if err != nil || v.Version == "" {
|
||||
t.Logf("%+v", v)
|
||||
t.Log(err)
|
||||
t.Error("expected something in version")
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
v, err := c.Version()
|
||||
if err != nil || v.Version == "" {
|
||||
t.Logf("%+v", v)
|
||||
t.Log(err)
|
||||
t.Error("expected something in version")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestID(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
id, err := c.ID()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if id.ID == "" {
|
||||
t.Error("bad id")
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
id, err := c.ID()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if id.ID == "" {
|
||||
t.Error("bad id")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestPeers(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
ids, err := c.Peers()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
t.Error("expected some peers")
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ids, err := c.Peers()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
t.Error("expected some peers")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestPeersWithError(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
addr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/44444")
|
||||
c, _ = NewClient(&Config{APIAddr: addr, DisableKeepAlives: true})
|
||||
ids, err := c.Peers()
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
if ids == nil || len(ids) != 0 {
|
||||
t.Fatal("expected no ids")
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
addr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/44444")
|
||||
c, _ = NewClient(&Config{APIAddr: addr, DisableKeepAlives: true})
|
||||
ids, err := c.Peers()
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
if ids == nil || len(ids) != 0 {
|
||||
t.Fatal("expected no ids")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestPeerAdd(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
addr, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/1234/ipfs/" + test.TestPeerID1.Pretty())
|
||||
id, err := c.PeerAdd(addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if id.ID != test.TestPeerID1 {
|
||||
t.Error("bad peer")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
addr, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/1234/ipfs/" + test.TestPeerID1.Pretty())
|
||||
id, err := c.PeerAdd(addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if id.ID != test.TestPeerID1 {
|
||||
t.Error("bad peer")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestPeerRm(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
err := c.PeerRm(test.TestPeerID1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
err := c.PeerRm(test.TestPeerID1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestPin(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
err := c.Pin(ci, 6, 7, "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
err := c.Pin(ci, 6, 7, "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestUnpin(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
err := c.Unpin(ci)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
err := c.Unpin(ci)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestAllocations(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
pins, err := c.Allocations()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(pins) == 0 {
|
||||
t.Error("should be some pins")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
pins, err := c.Allocations()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(pins) == 0 {
|
||||
t.Error("should be some pins")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestAllocation(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Allocation(ci)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Allocation(ci)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestStatus(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Status(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Status(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestStatusAll(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
pins, err := c.StatusAll(false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
pins, err := c.StatusAll(false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(pins) == 0 {
|
||||
t.Error("there should be some pins")
|
||||
}
|
||||
}
|
||||
|
||||
if len(pins) == 0 {
|
||||
t.Error("there should be some pins")
|
||||
}
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Sync(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Sync(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestSyncAll(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
pins, err := c.SyncAll(false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
pins, err := c.SyncAll(false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(pins) == 0 {
|
||||
t.Error("there should be some pins")
|
||||
}
|
||||
}
|
||||
|
||||
if len(pins) == 0 {
|
||||
t.Error("there should be some pins")
|
||||
}
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestRecover(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Recover(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
ci, _ := cid.Decode(test.TestCid1)
|
||||
pin, err := c.Recover(ci, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pin.Cid.String() != test.TestCid1 {
|
||||
t.Error("should be same pin")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestRecoverAll(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
_, err := c.RecoverAll(true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
_, err := c.RecoverAll(true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
||||
func TestGetConnectGraph(t *testing.T) {
|
||||
c, api := testClient(t)
|
||||
defer api.Shutdown()
|
||||
api := testAPI(t)
|
||||
defer shutdown(api)
|
||||
|
||||
cg, err := c.GetConnectGraph()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(cg.IPFSLinks) != 3 || len(cg.ClusterLinks) != 3 ||
|
||||
len(cg.ClustertoIPFS) != 3 {
|
||||
t.Fatal("Bad graph")
|
||||
testF := func(t *testing.T, c *Client) {
|
||||
cg, err := c.GetConnectGraph()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(cg.IPFSLinks) != 3 || len(cg.ClusterLinks) != 3 ||
|
||||
len(cg.ClustertoIPFS) != 3 {
|
||||
t.Fatal("Bad graph")
|
||||
}
|
||||
}
|
||||
|
||||
testClients(t, api, testF)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ func (c *Client) do(method, path string, body io.Reader, obj interface{}) error
|
|||
}
|
||||
|
||||
func (c *Client) doRequest(method, path string, body io.Reader) (*http.Response, error) {
|
||||
urlpath := c.urlPrefix + "/" + strings.TrimPrefix(path, "/")
|
||||
urlpath := c.net + "://" + c.hostname + "/" + strings.TrimPrefix(path, "/")
|
||||
logger.Debugf("%s: %s", method, urlpath)
|
||||
|
||||
r, err := http.NewRequest(method, urlpath, body)
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
)
|
||||
import "crypto/tls"
|
||||
|
||||
func newTLSTransport(skipVerify bool) *http.Transport {
|
||||
func tlsConfig(skipVerify bool) *tls.Config {
|
||||
// based on https://github.com/denji/golang-tls
|
||||
tlsCfg := &tls.Config{
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||
PreferServerCipherSuites: true,
|
||||
|
@ -19,7 +16,4 @@ func newTLSTransport(skipVerify bool) *http.Transport {
|
|||
},
|
||||
InsecureSkipVerify: skipVerify,
|
||||
}
|
||||
return &http.Transport{
|
||||
TLSClientConfig: tlsCfg,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user