Skip to content

Commit d56eb26

Browse files
committed
Add tests for HTTP check
Adds a mock trustless gateway server and a mock routing v1 server and checks that finding a CID works via both.
1 parent 659cd69 commit d56eb26

File tree

4 files changed

+156
-1
lines changed

4 files changed

+156
-1
lines changed

daemon.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ func checkHTTPRetrieval(ctx context.Context, host host.Host, c cid.Cid, pinfo pe
539539
htnet := httpnet.New(host,
540540
httpnet.WithUserAgent(userAgent),
541541
httpnet.WithResponseHeaderTimeout(5*time.Second), // default: 10
542+
httpnet.WithInsecureSkipVerify(true),
542543
httpnet.WithHTTPWorkers(1),
543544
)
544545
defer htnet.Stop()

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/ipfs/go-block-format v0.2.1
1010
github.com/ipfs/go-cid v0.5.0
1111
github.com/ipfs/go-datastore v0.8.2
12+
github.com/ipfs/go-ipld-format v0.6.1
1213
github.com/libp2p/go-libp2p v0.41.1
1314
github.com/libp2p/go-libp2p-kad-dht v0.33.0
1415
github.com/libp2p/go-libp2p-record v0.3.1
@@ -65,7 +66,6 @@ require (
6566
github.com/ipfs/bbloom v0.0.4 // indirect
6667
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
6768
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
68-
github.com/ipfs/go-ipld-format v0.6.1 // indirect
6969
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
7070
github.com/ipfs/go-log/v2 v2.6.0 // indirect
7171
github.com/ipfs/go-metrics-interface v0.3.0 // indirect

integration_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ package main
22

33
import (
44
"context"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"net/http"
9+
"net/http/httptest"
10+
"strings"
511
"testing"
612
"time"
713

@@ -12,19 +18,108 @@ import (
1218
"github.com/ipfs/go-cid"
1319
"github.com/ipfs/go-datastore"
1420
dssync "github.com/ipfs/go-datastore/sync"
21+
ipld "github.com/ipfs/go-ipld-format"
1522
"github.com/ipfs/ipfs-check/test"
1623
"github.com/libp2p/go-libp2p"
1724
dht "github.com/libp2p/go-libp2p-kad-dht"
1825
"github.com/libp2p/go-libp2p/core/host"
1926
"github.com/libp2p/go-libp2p/core/peer"
2027
"github.com/libp2p/go-libp2p/core/protocol"
2128
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
29+
multiaddr "github.com/multiformats/go-multiaddr"
2230
manet "github.com/multiformats/go-multiaddr/net"
2331
"github.com/multiformats/go-multihash"
2432
"github.com/prometheus/client_golang/prometheus"
2533
"github.com/stretchr/testify/require"
2634
)
2735

36+
type trustlessGateway struct {
37+
bstore blockstore.Blockstore
38+
}
39+
40+
// A HTTP server for blocks in a blockstore.
41+
func (h *trustlessGateway) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
42+
path := r.URL.Path
43+
_, cidstr, ok := strings.Cut(path, "/ipfs/")
44+
if !ok {
45+
rw.WriteHeader(http.StatusBadRequest)
46+
return
47+
}
48+
49+
if cidstr == "bafkqaaa" {
50+
rw.WriteHeader(http.StatusOK)
51+
return
52+
}
53+
54+
c, err := cid.Parse(cidstr)
55+
if err != nil {
56+
rw.WriteHeader(http.StatusBadRequest)
57+
return
58+
}
59+
60+
b, err := h.bstore.Get(r.Context(), c)
61+
if errors.Is(err, ipld.ErrNotFound{}) {
62+
rw.WriteHeader(http.StatusNotFound)
63+
return
64+
}
65+
if err != nil {
66+
rw.WriteHeader(http.StatusInternalServerError)
67+
return
68+
}
69+
70+
rw.WriteHeader(http.StatusOK)
71+
if r.Method == "HEAD" {
72+
return
73+
}
74+
75+
rw.Write(b.RawData())
76+
}
77+
78+
type httpRouting struct {
79+
bstore blockstore.Blockstore
80+
addrs []multiaddr.Multiaddr
81+
id peer.ID
82+
}
83+
84+
// A HTTP server for blocks in a blockstore.
85+
func (h *httpRouting) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
86+
path := r.URL.Path
87+
_, cidstr, ok := strings.Cut(path, "/routing/v1/providers/")
88+
if !ok {
89+
rw.WriteHeader(http.StatusBadRequest)
90+
return
91+
}
92+
93+
c, err := cid.Parse(cidstr)
94+
if err != nil {
95+
rw.WriteHeader(http.StatusBadRequest)
96+
return
97+
}
98+
99+
_, err = h.bstore.Get(r.Context(), c)
100+
if errors.Is(err, ipld.ErrNotFound{}) {
101+
rw.WriteHeader(http.StatusNotFound)
102+
return
103+
}
104+
if err != nil {
105+
rw.WriteHeader(http.StatusInternalServerError)
106+
return
107+
}
108+
rw.Header().Set("Content-Type", "application/x-ndjson")
109+
rw.WriteHeader(http.StatusOK)
110+
jaddrs, _ := json.Marshal(h.addrs)
111+
resp := `
112+
{
113+
"Schema": "peer",
114+
"ID": "` + h.id.String() + `",
115+
"Addrs": ` + string(jaddrs) + `,
116+
"Protocols": ["transport-ipfs-gateway-http"]
117+
}
118+
`
119+
fmt.Println(resp)
120+
rw.Write([]byte(resp))
121+
}
122+
28123
func TestBasicIntegration(t *testing.T) {
29124
ctx, cancel := context.WithCancel(context.Background())
30125
defer cancel()
@@ -95,6 +190,30 @@ func TestBasicIntegration(t *testing.T) {
95190
require.NoError(t, err)
96191
hostAddr := mas[0]
97192

193+
gw := &trustlessGateway{
194+
bstore: bstore,
195+
}
196+
httpServer := httptest.NewUnstartedServer(gw)
197+
httpServer.EnableHTTP2 = true
198+
httpServer.StartTLS()
199+
maddr, err := manet.FromNetAddr(httpServer.Listener.Addr())
200+
require.NoError(t, err)
201+
httpAddr, err := multiaddr.NewMultiaddr("/https")
202+
require.NoError(t, err)
203+
peerAddr, err := multiaddr.NewMultiaddr("/p2p/" + h.ID().String())
204+
require.NoError(t, err)
205+
httpPeerAddr := maddr.Encapsulate(httpAddr).Encapsulate(peerAddr)
206+
207+
rt := &httpRouting{
208+
bstore: bstore,
209+
addrs: []multiaddr.Multiaddr{maddr.Encapsulate(httpAddr)},
210+
id: h.ID(),
211+
}
212+
213+
routingServer := httptest.NewUnstartedServer(rt)
214+
routingServer.Start()
215+
ipniAddr := "http://" + routingServer.Listener.Addr().String()
216+
98217
t.Run("Data on reachable peer that's advertised", func(t *testing.T) {
99218
testData := []byte(t.Name())
100219
mh, err := multihash.Sum(testData, multihash.SHA2_256, -1)
@@ -184,4 +303,35 @@ func TestBasicIntegration(t *testing.T) {
184303
res.Value(0).Object().Value("DataAvailableOverBitswap").Object().Value("Found").Boolean().IsTrue()
185304
res.Value(0).Object().Value("DataAvailableOverBitswap").Object().Value("Responded").Boolean().IsTrue()
186305
})
306+
307+
t.Run("Data found via HTTP", func(t *testing.T) {
308+
testData := []byte(t.Name())
309+
mh, err := multihash.Sum(testData, multihash.SHA2_256, -1)
310+
require.NoError(t, err)
311+
testCid := cid.NewCidV1(cid.Raw, mh)
312+
testBlock, err := blocks.NewBlockWithCid(testData, testCid)
313+
require.NoError(t, err)
314+
err = bstore.Put(ctx, testBlock)
315+
require.NoError(t, err)
316+
317+
obj := test.Query(t, "http://localhost:1234", testCid.String(), httpPeerAddr.String(), "httpRetrieval=on")
318+
obj.Value("DataAvailableOverHTTP").Object().Value("Found").Boolean().IsTrue()
319+
})
320+
321+
t.Run("Data found via HTTP with just CID", func(t *testing.T) {
322+
testData := []byte(t.Name())
323+
mh, err := multihash.Sum(testData, multihash.SHA2_256, -1)
324+
require.NoError(t, err)
325+
testCid := cid.NewCidV1(cid.Raw, mh)
326+
testBlock, err := blocks.NewBlockWithCid(testData, testCid)
327+
require.NoError(t, err)
328+
err = bstore.Put(ctx, testBlock)
329+
require.NoError(t, err)
330+
331+
fmt.Println(ipniAddr)
332+
fmt.Println(httpAddr.String())
333+
obj := test.QueryCid(t, "http://localhost:1234", testCid.String(), "httpRetrieval=on", "ipniIndexer="+ipniAddr)
334+
obj.Value(0).Object().Value("DataAvailableOverHTTP").Object().Value("Found").Boolean().IsTrue()
335+
})
336+
187337
}

test/tools.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func Query(
2828
url string,
2929
cid string,
3030
multiaddr string,
31+
flags ...string,
3132
) *httpexpect.Object {
3233
expectedContentType := "application/json"
3334
if url == "https://ipfs-check-backend.ipfs.io" {
@@ -46,6 +47,7 @@ func Query(
4647
return e.POST("/check").
4748
WithQuery("cid", cid).
4849
WithQuery("multiaddr", multiaddr).
50+
WithQueryString(strings.Join(flags, "&")).
4951
Expect().
5052
Status(http.StatusOK).
5153
JSON(opts).Object()
@@ -55,6 +57,7 @@ func QueryCid(
5557
t *testing.T,
5658
url string,
5759
cid string,
60+
flags ...string,
5861
) *httpexpect.Array {
5962
expectedContentType := "application/json"
6063

@@ -66,6 +69,7 @@ func QueryCid(
6669

6770
return e.GET("/check").
6871
WithQuery("cid", cid).
72+
WithQueryString(strings.Join(flags, "&")).
6973
Expect().
7074
Status(http.StatusOK).
7175
JSON(opts).Array()

0 commit comments

Comments
 (0)