Partial ipld node impl
This commit was moved from ipfs/go-ipfs-http-client@df916c7849d6cfd7f479c4fe80c0f75d6705a0fc
Łukasz Magiera committed
Nov 6, 2018 at 14:38 UTC
6c927fd9624807e124f0376445c41daaa975fbd8
4 files changed
+151
-4
client/httpapi/api.go
+3
-3
@@ -1,7 +1,7 @@
1
package httpapi
2
3
import (
4
- "github.com/pkg/errors"
4
+ "errors"
5
"io/ioutil"
6
gohttp "net/http"
7
"os"
@@ -12,7 +12,7 @@ import (
12
homedir "github.com/mitchellh/go-homedir"
13
ma "github.com/multiformats/go-multiaddr"
14
manet "github.com/multiformats/go-multiaddr-net"
15
- )
15
+)
16
17
const (
18
DefaultPathName = ".ipfs"
@@ -91,7 +91,7 @@ func (api *HttpApi) Unixfs() iface.UnixfsAPI {
91
}
92
93
func (api *HttpApi) Block() iface.BlockAPI {
94
- return nil
94
+ return (*BlockAPI)(api)
95
}
96
97
func (api *HttpApi) Dag() iface.DagAPI {
client/httpapi/block.go
new
+40
@@ -0,0 +1,40 @@
1
+package httpapi
2
+
3
+import (
4
+ "context"
5
+ "io"
6
+
7
+ "github.com/ipfs/go-ipfs/core/coreapi/interface"
8
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
9
+)
10
+
11
+type BlockAPI HttpApi
12
+
13
+func (api *BlockAPI) Put(ctx context.Context, r io.Reader, opts ...options.BlockPutOption) (iface.BlockStat, error) {
14
+ return nil, ErrNotImplemented
15
+}
16
+
17
+func (api *BlockAPI) Get(ctx context.Context, p iface.Path) (io.Reader, error) {
18
+ resp, err := api.core().request("block/get", p.String()).Send(context.Background())
19
+ if err != nil {
20
+ return nil, err
21
+ }
22
+
23
+ //TODO: is close on the reader enough?
24
+ //defer resp.Close()
25
+
26
+ //TODO: make blockApi return ReadCloser
27
+ return resp.Output, resp.Error
28
+}
29
+
30
+func (api *BlockAPI) Rm(ctx context.Context, p iface.Path, opts ...options.BlockRmOption) error {
31
+ return ErrNotImplemented
32
+}
33
+
34
+func (api *BlockAPI) Stat(ctx context.Context, p iface.Path) (iface.BlockStat, error) {
35
+ return nil, ErrNotImplemented
36
+}
37
+
38
+func (api *BlockAPI) core() *HttpApi {
39
+ return (*HttpApi)(api)
40
+}
client/httpapi/ipldnode.go
new
+107
@@ -0,0 +1,107 @@
1
+package httpapi
2
+
3
+import (
4
+ "context"
5
+ "fmt"
6
+ "github.com/pkg/errors"
7
+ "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
8
+ "io/ioutil"
9
+ "strconv"
10
+
11
+ "github.com/ipfs/go-ipfs/core/coreapi/interface"
12
+
13
+ ipfspath "gx/ipfs/QmRG3XuGwT7GYuAqgWDJBKTzdaHMwAnc1x7J2KHEXNHxzG/go-path"
14
+ ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
15
+)
16
+
17
+type ipldNode struct {
18
+ ctx context.Context //TODO: should we re-consider adding ctx to ipld interfaces?
19
+ path iface.ResolvedPath
20
+ api *HttpApi
21
+}
22
+
23
+func (n *ipldNode) RawData() []byte {
24
+ r, err := n.api.Block().Get(n.ctx, n.path)
25
+ if err != nil {
26
+ panic(err) // TODO: eww, should we add errors too / better ideas?
27
+ }
28
+
29
+ b, err := ioutil.ReadAll(r)
30
+ if err != nil {
31
+ panic(err)
32
+ }
33
+
34
+ return b
35
+}
36
+
37
+func (n *ipldNode) Cid() cid.Cid {
38
+ return n.path.Cid()
39
+}
40
+
41
+func (n *ipldNode) String() string {
42
+ return fmt.Sprintf("[Block %s]", n.Cid())
43
+}
44
+
45
+func (n *ipldNode) Loggable() map[string]interface{} {
46
+ return nil //TODO: we can't really do better here, can we?
47
+}
48
+
49
+// TODO: should we use 'full'/real ipld codecs for this? js-ipfs-api does that.
50
+// We can also give people a choice
51
+func (n *ipldNode) Resolve(path []string) (interface{}, []string, error) {
52
+ p := ipfspath.Join([]string{n.path.String(), ipfspath.Join(path)})
53
+
54
+ var out interface{}
55
+ n.api.request("dag/get", p).Exec(n.ctx, &out)
56
+
57
+ // TODO: this is more than likely wrong, fix if we decide to stick with this 'http-ipld-node' hack
58
+ for len(path) > 0 {
59
+ switch o := out.(type) {
60
+ case map[string]interface{}:
61
+ v, ok := o[path[0]]
62
+ if !ok {
63
+ // TODO: ipld links
64
+ return nil, nil, errors.New("no element under this path")
65
+ }
66
+ out = v
67
+ case []interface{}:
68
+ n, err := strconv.ParseUint(path[0], 10, 32)
69
+ if err != nil {
70
+ return nil, nil, err
71
+ }
72
+ if len(o) < int(n) {
73
+ return nil, nil, errors.New("no element under this path")
74
+ }
75
+ out = o[n]
76
+ }
77
+ path = path[1:]
78
+ }
79
+
80
+ return out, path, nil
81
+}
82
+
83
+func (n *ipldNode) Tree(path string, depth int) []string {
84
+ panic("implement me")
85
+}
86
+
87
+func (n *ipldNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
88
+ panic("implement me")
89
+}
90
+
91
+func (n *ipldNode) Copy() ipld.Node {
92
+ panic("implement me")
93
+}
94
+
95
+func (n *ipldNode) Links() []*ipld.Link {
96
+ panic("implement me")
97
+}
98
+
99
+func (n *ipldNode) Stat() (*ipld.NodeStat, error) {
100
+ panic("implement me")
101
+}
102
+
103
+func (n *ipldNode) Size() (uint64, error) {
104
+ panic("implement me")
105
+}
106
+
107
+var _ ipld.Node = &ipldNode{}
client/httpapi/path.go
+1
-1
@@ -30,7 +30,7 @@ func (api *HttpApi) ResolvePath(ctx context.Context, path iface.Path) (iface.Res
30
}
31
32
// TODO:
33
- ipath, err := ipfspath.FromSegments("/" +path.Namespace() + "/", out.Cid.String(), out.RemPath)
33
+ ipath, err := ipfspath.FromSegments("/"+path.Namespace()+"/", out.Cid.String(), out.RemPath)
34
if err != nil {
35
return nil, err
36
}