Skip to content

Commit

Permalink
Merge pull request #5 from ipfs/from-gdr
Browse files Browse the repository at this point in the history
  • Loading branch information
ajnavarro authored Nov 30, 2022
2 parents 9bd65e3 + 2ec4894 commit 592a45a
Show file tree
Hide file tree
Showing 11 changed files with 452 additions and 348 deletions.
51 changes: 31 additions & 20 deletions routing/http/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
"github.com/benbjohnson/clock"
"github.com/ipfs/go-cid"
ipns "github.com/ipfs/go-ipns"
delegatedrouting "github.com/ipfs/go-libipfs/routing/http"
"github.com/ipfs/go-libipfs/routing/http/internal/drjson"
"github.com/ipfs/go-libipfs/routing/http/server"
"github.com/ipfs/go-libipfs/routing/http/types"
logging "github.com/ipfs/go-log/v2"
record "github.com/libp2p/go-libp2p-record"
"github.com/libp2p/go-libp2p/core/crypto"
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 routing/http/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-libipfs/routing/http"
"github.com/ipfs/go-libipfs/routing/http/server"
"github.com/ipfs/go-libipfs/routing/http/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 routing/http/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 routing/http/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

0 comments on commit 592a45a

Please sign in to comment.