Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

fix: Improve types and follow the specs #66

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 31 additions & 20 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (

"github.com/benbjohnson/clock"
"github.com/ipfs/go-cid"
delegatedrouting "github.com/ipfs/go-delegated-routing"
"github.com/ipfs/go-delegated-routing/internal/drjson"
"github.com/ipfs/go-delegated-routing/server"
"github.com/ipfs/go-delegated-routing/types"
ipns "github.com/ipfs/go-ipns"
logging "github.com/ipfs/go-log/v2"
record "github.com/libp2p/go-libp2p-record"
Expand All @@ -29,12 +31,12 @@ type client struct {
clock clock.Clock

peerID peer.ID
addrs []delegatedrouting.Multiaddr
addrs []types.Multiaddr
identity crypto.PrivKey

// called immeidately after signing a provide req
// used for testing, e.g. testing the server with a mangled signature
afterSignCallback func(req *delegatedrouting.BitswapWriteProviderRequest)
afterSignCallback func(req *types.WriteBitswapProviderRecord)
}

type httpClient interface {
Expand All @@ -59,7 +61,7 @@ func WithProviderInfo(peerID peer.ID, addrs []multiaddr.Multiaddr) option {
return func(c *client) {
c.peerID = peerID
for _, a := range addrs {
c.addrs = append(c.addrs, delegatedrouting.Multiaddr{Multiaddr: a})
c.addrs = append(c.addrs, types.Multiaddr{Multiaddr: a})
}
}
}
Expand All @@ -85,8 +87,8 @@ func New(baseURL string, opts ...option) (*client, error) {
return client, nil
}

func (c *client) FindProviders(ctx context.Context, key cid.Cid) ([]delegatedrouting.Provider, error) {
url := c.baseURL + "/v1/providers/" + key.String()
func (c *client) FindProviders(ctx context.Context, key cid.Cid) ([]types.ProviderResponse, error) {
url := c.baseURL + server.ProvidePath + key.String()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
Expand All @@ -102,7 +104,7 @@ func (c *client) FindProviders(ctx context.Context, key cid.Cid) ([]delegatedrou
return nil, httpError(resp.StatusCode, resp.Body)
}

parsedResp := &delegatedrouting.FindProvidersResponse{}
parsedResp := &types.ReadProvidersResponse{}
err = json.NewDecoder(resp.Body).Decode(parsedResp)
return parsedResp.Providers, err
}
Expand All @@ -115,19 +117,19 @@ func (c *client) ProvideBitswap(ctx context.Context, keys []cid.Cid, ttl time.Du
return 0, errors.New("cannot provide Bitswap records without a peer ID")
}

ks := make([]delegatedrouting.CID, len(keys))
ks := make([]types.CID, len(keys))
for i, c := range keys {
ks[i] = delegatedrouting.CID{Cid: c}
ks[i] = types.CID{Cid: c}
}

now := c.clock.Now()

req := delegatedrouting.BitswapWriteProviderRequest{
Protocol: "bitswap",
Payload: delegatedrouting.BitswapWriteProviderRequestPayload{
req := types.WriteBitswapProviderRecord{
Protocol: types.BitswapProviderID,
Payload: types.BitswapPayload{
Keys: ks,
AdvisoryTTL: &delegatedrouting.Duration{Duration: ttl},
Timestamp: &delegatedrouting.Time{Time: now},
AdvisoryTTL: &types.Duration{Duration: ttl},
Timestamp: &types.Time{Time: now},
ID: &c.peerID,
Addrs: c.addrs,
},
Expand All @@ -150,12 +152,12 @@ func (c *client) ProvideBitswap(ctx context.Context, keys []cid.Cid, ttl time.Du
}

// ProvideAsync makes a provide request to a delegated router
func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *delegatedrouting.BitswapWriteProviderRequest) (time.Duration, error) {
req := delegatedrouting.WriteProvidersRequest{Providers: []delegatedrouting.Provider{bswp}}
func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *types.WriteBitswapProviderRecord) (time.Duration, error) {
req := types.WriteProvidersRequest{Providers: []types.WriteProviderRecord{bswp}}

url := c.baseURL + "/v1/providers"
url := c.baseURL + server.ProvidePath

b, err := json.Marshal(req)
b, err := drjson.MarshalJSONBytes(req)
if err != nil {
return 0, err
}
Expand All @@ -174,7 +176,7 @@ func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *delegated
if resp.StatusCode != http.StatusOK {
return 0, httpError(resp.StatusCode, resp.Body)
}
provideResult := delegatedrouting.WriteProvidersResponse{Protocols: []string{"bitswap"}}
var provideResult types.WriteProvidersResponse
err = json.NewDecoder(resp.Body).Decode(&provideResult)
if err != nil {
return 0, err
Expand All @@ -183,5 +185,14 @@ func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *delegated
return 0, fmt.Errorf("expected 1 result but got %d", len(provideResult.ProvideResults))
}

return provideResult.ProvideResults[0].(*delegatedrouting.BitswapWriteProviderResponse).AdvisoryTTL, nil
v, ok := provideResult.ProvideResults[0].(*types.WriteBitswapProviderRecordResponse)
if !ok {
return 0, fmt.Errorf("expected AdvisoryTTL field")
}

if v.AdvisoryTTL != nil {
return v.AdvisoryTTL.Duration, nil
}

return 0, nil
}
39 changes: 20 additions & 19 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

"github.com/benbjohnson/clock"
"github.com/ipfs/go-cid"
delegatedrouting "github.com/ipfs/go-delegated-routing"
"github.com/ipfs/go-delegated-routing/server"
"github.com/ipfs/go-delegated-routing/types"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
Expand All @@ -24,17 +24,18 @@ import (

type mockContentRouter struct{ mock.Mock }

func (m *mockContentRouter) FindProviders(ctx context.Context, key cid.Cid) ([]delegatedrouting.Provider, error) {
func (m *mockContentRouter) FindProviders(ctx context.Context, key cid.Cid) ([]types.ProviderResponse, error) {
args := m.Called(ctx, key)
return args.Get(0).([]delegatedrouting.Provider), args.Error(1)
return args.Get(0).([]types.ProviderResponse), args.Error(1)
}
func (m *mockContentRouter) Provide(ctx context.Context, req server.ProvideRequest) (time.Duration, error) {
func (m *mockContentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapWriteProvideRequest) (time.Duration, error) {
args := m.Called(ctx, req)
return args.Get(0).(time.Duration), args.Error(1)
}
func (m *mockContentRouter) Ready() bool {
args := m.Called()
return args.Bool(0)

func (m *mockContentRouter) Provide(ctx context.Context, req *server.WriteProvideRequest) (types.ProviderResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(types.ProviderResponse), args.Error(1)
}

type testDeps struct {
Expand Down Expand Up @@ -78,24 +79,24 @@ func makeCID() cid.Cid {
return c
}

func addrsToDRAddrs(addrs []multiaddr.Multiaddr) (drmas []delegatedrouting.Multiaddr) {
func addrsToDRAddrs(addrs []multiaddr.Multiaddr) (drmas []types.Multiaddr) {
for _, a := range addrs {
drmas = append(drmas, delegatedrouting.Multiaddr{Multiaddr: a})
drmas = append(drmas, types.Multiaddr{Multiaddr: a})
}
return
}

func drAddrsToAddrs(drmas []delegatedrouting.Multiaddr) (addrs []multiaddr.Multiaddr) {
func drAddrsToAddrs(drmas []types.Multiaddr) (addrs []multiaddr.Multiaddr) {
for _, a := range drmas {
addrs = append(addrs, a.Multiaddr)
}
return
}

func makeBSReadProviderResp() delegatedrouting.BitswapReadProviderResponse {
func makeBSReadProviderResp() types.ReadBitswapProviderRecord {
peerID, addrs, _ := makeProviderAndIdentity()
return delegatedrouting.BitswapReadProviderResponse{
Protocol: "bitswap",
return types.ReadBitswapProviderRecord{
Protocol: types.BitswapProviderID,
ID: &peerID,
Addrs: addrsToDRAddrs(addrs),
}
Expand Down Expand Up @@ -125,16 +126,16 @@ func makeProviderAndIdentity() (peer.ID, []multiaddr.Multiaddr, crypto.PrivKey)

func TestClient_FindProviders(t *testing.T) {
bsReadProvResp := makeBSReadProviderResp()
bitswapProvs := []delegatedrouting.Provider{&bsReadProvResp}
bitswapProvs := []types.ProviderResponse{&bsReadProvResp}

cases := []struct {
name string
manglePath bool
stopServer bool
routerProvs []delegatedrouting.Provider
routerProvs []types.ProviderResponse
routerErr error

expProvs []delegatedrouting.Provider
expProvs []types.ProviderResponse
expErrContains []string
expWinErrContains []string
}{
Expand Down Expand Up @@ -278,7 +279,7 @@ func TestClient_Provide(t *testing.T) {
deps.server.Close()
}
if c.mangleSignature {
client.afterSignCallback = func(req *delegatedrouting.BitswapWriteProviderRequest) {
client.afterSignCallback = func(req *types.WriteBitswapProviderRecord) {
mh, err := multihash.Encode([]byte("boom"), multihash.SHA2_256)
require.NoError(t, err)
mb, err := multibase.Encode(multibase.Base64, mh)
Expand All @@ -288,15 +289,15 @@ func TestClient_Provide(t *testing.T) {
}
}

expectedProvReq := server.ProvideRequest{
expectedProvReq := &server.BitswapWriteProvideRequest{
Keys: c.cids,
Timestamp: clock.Now().Truncate(time.Millisecond),
AdvisoryTTL: c.ttl,
Addrs: drAddrsToAddrs(client.addrs),
ID: client.peerID,
}

router.On("Provide", mock.Anything, expectedProvReq).
router.On("ProvideBitswap", mock.Anything, expectedProvReq).
Return(c.routerAdvisoryTTL, c.routerErr)

advisoryTTL, err := client.ProvideBitswap(ctx, c.cids, c.ttl)
Expand Down
26 changes: 26 additions & 0 deletions internal/drjson/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package drjson

import (
"bytes"
"encoding/json"
)

func marshalJSON(val any) (*bytes.Buffer, error) {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(val)
return buf, err
}

// MarshalJSONBytes is needed to avoid changes
// on the original bytes due to HTML escapes.
func MarshalJSONBytes(val any) ([]byte, error) {
buf, err := marshalJSON(val)
if err != nil {
return nil, err
}

// remove last \n added by Encode
return buf.Bytes()[:buf.Len()-1], nil
}
16 changes: 16 additions & 0 deletions internal/drjson/json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package drjson

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestMarshalJSON(t *testing.T) {
// ensure that < is not escaped, which is the default Go behavior
bytes, err := MarshalJSONBytes(map[string]string{"<": "<"})
if err != nil {
panic(err)
}
require.Equal(t, "{\"<\":\"<\"}", string(bytes))
}
Loading