Skip to content

Commit 8f29e0a

Browse files
committed
wip: car gateway example
1 parent 43deb6b commit 8f29e0a

File tree

8 files changed

+1922
-0
lines changed

8 files changed

+1922
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.car
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
gopath "path"
8+
9+
"github.com/ipfs/go-blockservice"
10+
"github.com/ipfs/go-cid"
11+
bsfetcher "github.com/ipfs/go-fetcher/impl/blockservice"
12+
blockstore "github.com/ipfs/go-ipfs-blockstore"
13+
offline "github.com/ipfs/go-ipfs-exchange-offline"
14+
ipld "github.com/ipfs/go-ipld-format"
15+
"github.com/ipfs/go-merkledag"
16+
ipfspath "github.com/ipfs/go-path"
17+
ipfspathresolver "github.com/ipfs/go-path/resolver"
18+
"github.com/ipfs/go-unixfsnode"
19+
"github.com/ipfs/interface-go-ipfs-core/path"
20+
carblockstore "github.com/ipld/go-car/v2/blockstore"
21+
)
22+
23+
type carGateway struct {
24+
bs blockstore.Blockstore
25+
bsrv blockservice.BlockService
26+
dsrv ipld.DAGService
27+
}
28+
29+
func newCarGateway(car io.ReaderAt) (*carGateway, error) {
30+
bs, err := carblockstore.NewReadOnly(car, nil)
31+
if err != nil {
32+
return nil, err
33+
}
34+
35+
bsrv := blockservice.New(bs, offline.Exchange(bs))
36+
dsrv := merkledag.NewDAGService(bsrv)
37+
38+
return &carGateway{
39+
bs: bs,
40+
bsrv: bsrv,
41+
dsrv: dsrv,
42+
}, nil
43+
}
44+
45+
func (api *carGateway) resolvePath(ctx context.Context, pth path.Path) (path.Resolved, error) {
46+
if _, ok := pth.(path.Resolved); ok {
47+
return pth.(path.Resolved), nil
48+
}
49+
50+
if err := pth.IsValid(); err != nil {
51+
return nil, fmt.Errorf("path: %w", err)
52+
}
53+
54+
if pth.Namespace() != "ipfs" {
55+
return nil, fmt.Errorf("unsupported path namespace: %s", pth.Namespace())
56+
}
57+
58+
ipath := ipfspath.Path(pth.String())
59+
60+
ipldFetcher := bsfetcher.NewFetcherConfig(api.bsrv)
61+
fetcher := ipldFetcher.WithReifier(unixfsnode.Reify)
62+
resolver := ipfspathresolver.NewBasicResolver(fetcher)
63+
64+
node, rest, err := resolver.ResolveToLastNode(ctx, ipath)
65+
if err != nil {
66+
return nil, fmt.Errorf("resolve to last node: %w", err)
67+
}
68+
69+
root, err := cid.Parse(ipath.Segments()[1])
70+
if err != nil {
71+
return nil, fmt.Errorf("parse root cid: %w", err)
72+
}
73+
74+
return path.NewResolvedPath(ipath, node, root, gopath.Join(rest...)), nil
75+
}
76+
77+
func (api *carGateway) resolveNode(ctx context.Context, pth path.Path) (ipld.Node, error) {
78+
rp, err := api.resolvePath(ctx, pth)
79+
if err != nil {
80+
return nil, fmt.Errorf("resolve path: %w", err)
81+
}
82+
83+
node, err := api.dsrv.Get(ctx, rp.Cid())
84+
if err != nil {
85+
return nil, fmt.Errorf("get node: %w", err)
86+
}
87+
return node, nil
88+
}
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"io"
7+
8+
iface "github.com/ipfs/interface-go-ipfs-core"
9+
"github.com/ipfs/interface-go-ipfs-core/path"
10+
)
11+
12+
type readerBlockAPI struct {
13+
api *carGateway
14+
}
15+
16+
func (r *readerBlockAPI) Get(ctx context.Context, pth path.Path) (io.Reader, error) {
17+
rp, err := r.api.resolvePath(ctx, pth)
18+
if err != nil {
19+
return nil, err
20+
}
21+
22+
b, err := r.api.bsrv.GetBlock(ctx, rp.Cid())
23+
if err != nil {
24+
return nil, err
25+
}
26+
27+
return bytes.NewReader(b.RawData()), nil
28+
}
29+
30+
func (r *readerBlockAPI) Stat(ctx context.Context, pth path.Path) (iface.BlockStat, error) {
31+
rp, err := r.api.resolvePath(ctx, pth)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
b, err := r.api.bsrv.GetBlock(ctx, rp.Cid())
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
return &BlockStat{
42+
path: path.IpldPath(b.Cid()),
43+
size: len(b.RawData()),
44+
}, nil
45+
}
46+
47+
type BlockStat struct {
48+
size int
49+
path path.Resolved
50+
}
51+
52+
func (bs *BlockStat) Size() int {
53+
return bs.size
54+
}
55+
56+
func (bs *BlockStat) Path() path.Resolved {
57+
return bs.path
58+
}
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
module car-file-gateway
2+
3+
go 1.19
4+
5+
require (
6+
github.com/ipfs/go-blockservice v0.5.0
7+
github.com/ipfs/go-cid v0.3.2
8+
github.com/ipfs/go-fetcher v1.6.1
9+
github.com/ipfs/go-ipfs-blockstore v1.2.0
10+
github.com/ipfs/go-ipfs-exchange-offline v0.3.0
11+
github.com/ipfs/go-ipld-format v0.4.0
12+
github.com/ipfs/go-libipfs v0.4.0
13+
github.com/ipfs/go-merkledag v0.9.0
14+
github.com/ipfs/go-path v0.3.0
15+
github.com/ipfs/go-unixfs v0.3.1
16+
github.com/ipfs/go-unixfsnode v1.5.1
17+
github.com/ipfs/interface-go-ipfs-core v0.10.0
18+
github.com/ipld/go-car v0.5.0
19+
github.com/ipld/go-car/v2 v2.6.0
20+
)
21+
22+
require (
23+
github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a // indirect
24+
github.com/beorn7/perks v1.0.1 // indirect
25+
github.com/cespare/xxhash v1.1.0 // indirect
26+
github.com/cespare/xxhash/v2 v2.1.2 // indirect
27+
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
28+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
29+
github.com/dustin/go-humanize v1.0.0 // indirect
30+
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
31+
github.com/go-logr/logr v1.2.3 // indirect
32+
github.com/go-logr/stdr v1.2.2 // indirect
33+
github.com/gogo/protobuf v1.3.2 // indirect
34+
github.com/golang/protobuf v1.5.2 // indirect
35+
github.com/google/uuid v1.3.0 // indirect
36+
github.com/hashicorp/golang-lru v0.5.4 // indirect
37+
github.com/ipfs/bbloom v0.0.4 // indirect
38+
github.com/ipfs/go-bitfield v1.0.0 // indirect
39+
github.com/ipfs/go-block-format v0.1.1 // indirect
40+
github.com/ipfs/go-datastore v0.6.0 // indirect
41+
github.com/ipfs/go-ipfs-chunker v0.0.1 // indirect
42+
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
43+
github.com/ipfs/go-ipfs-exchange-interface v0.2.0 // indirect
44+
github.com/ipfs/go-ipfs-files v0.0.8 // indirect
45+
github.com/ipfs/go-ipfs-posinfo v0.0.1 // indirect
46+
github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect
47+
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
48+
github.com/ipfs/go-ipld-cbor v0.0.6 // indirect
49+
github.com/ipfs/go-ipld-legacy v0.1.1 // indirect
50+
github.com/ipfs/go-ipns v0.3.0 // indirect
51+
github.com/ipfs/go-log v1.0.5 // indirect
52+
github.com/ipfs/go-log/v2 v2.5.1 // indirect
53+
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
54+
github.com/ipfs/go-mfs v0.2.1 // indirect
55+
github.com/ipfs/go-verifcid v0.0.2 // indirect
56+
github.com/ipld/go-codec-dagpb v1.5.0 // indirect
57+
github.com/ipld/go-ipld-prime v0.19.0 // indirect
58+
github.com/jbenet/goprocess v0.1.4 // indirect
59+
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
60+
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
61+
github.com/libp2p/go-libp2p v0.23.4 // indirect
62+
github.com/libp2p/go-openssl v0.1.0 // indirect
63+
github.com/mattn/go-isatty v0.0.17 // indirect
64+
github.com/mattn/go-pointer v0.0.1 // indirect
65+
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
66+
github.com/minio/sha256-simd v1.0.0 // indirect
67+
github.com/mr-tron/base58 v1.2.0 // indirect
68+
github.com/multiformats/go-base32 v0.1.0 // indirect
69+
github.com/multiformats/go-base36 v0.2.0 // indirect
70+
github.com/multiformats/go-multiaddr v0.8.0 // indirect
71+
github.com/multiformats/go-multibase v0.1.1 // indirect
72+
github.com/multiformats/go-multicodec v0.7.0 // indirect
73+
github.com/multiformats/go-multihash v0.2.1 // indirect
74+
github.com/multiformats/go-varint v0.0.7 // indirect
75+
github.com/opentracing/opentracing-go v1.2.0 // indirect
76+
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
77+
github.com/pkg/errors v0.9.1 // indirect
78+
github.com/polydawn/refmt v0.89.0 // indirect
79+
github.com/prometheus/client_golang v1.13.0 // indirect
80+
github.com/prometheus/client_model v0.2.0 // indirect
81+
github.com/prometheus/common v0.37.0 // indirect
82+
github.com/prometheus/procfs v0.8.0 // indirect
83+
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
84+
github.com/spaolacci/murmur3 v1.1.0 // indirect
85+
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb // indirect
86+
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
87+
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect
88+
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
89+
go.opentelemetry.io/otel v1.12.0 // indirect
90+
go.opentelemetry.io/otel/trace v1.12.0 // indirect
91+
go.uber.org/atomic v1.10.0 // indirect
92+
go.uber.org/multierr v1.9.0 // indirect
93+
go.uber.org/zap v1.24.0 // indirect
94+
golang.org/x/crypto v0.5.0 // indirect
95+
golang.org/x/exp v0.0.0-20230129154200-a960b3787bd2 // indirect
96+
golang.org/x/net v0.5.0 // indirect
97+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
98+
golang.org/x/sys v0.4.0 // indirect
99+
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
100+
google.golang.org/protobuf v1.28.1 // indirect
101+
lukechampine.com/blake3 v1.1.7 // indirect
102+
)
103+
104+
replace github.com/ipfs/go-libipfs => ../../..

0 commit comments

Comments
 (0)