Implement Object API
This commit was moved from ipfs/go-ipfs-http-client@38149e46c8c3a1544dc3e3108ef72ffbc885e410
Łukasz Magiera committed
Jan 15, 2019 at 16:31 UTC
eaa19388d4d86eebf09d93a3a637e0690df722bd
5 files changed
+208
-31
client/httpapi/block.go
+1
-1
@@ -67,7 +67,7 @@ func (api *BlockAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.BlockP
67
}
68
69
func (api *BlockAPI) Get(ctx context.Context, p iface.Path) (io.Reader, error) {
70
- resp, err := api.core().request("block/get", p.String()).Send(context.Background())
70
+ resp, err := api.core().request("block/get", p.String()).Send(ctx)
71
if err != nil {
72
return nil, err
73
}
client/httpapi/ipldnode.go
+3
-4
@@ -3,7 +3,6 @@ package httpapi
3
import (
4
"context"
5
"errors"
6
- "fmt"
6
"io/ioutil"
7
"strconv"
8
@@ -20,11 +19,11 @@ type ipldNode struct {
19
api *HttpApi
20
}
21
23
-func (a *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
22
+func (api *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
23
return &ipldNode{
24
ctx: ctx,
25
path: p,
27
- api: a,
26
+ api: api,
27
}
28
}
29
@@ -47,7 +46,7 @@ func (n *ipldNode) Cid() cid.Cid {
46
}
47
48
func (n *ipldNode) String() string {
50
- return fmt.Sprintf("[Block %s]", n.Cid())
49
+ return n.Cid().String()
50
}
51
52
func (n *ipldNode) Loggable() map[string]interface{} {
client/httpapi/key.go
+4
-4
@@ -59,10 +59,10 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
59
return nil, false, err
60
}
61
62
- var out struct{
63
- Was string
64
- Now string
65
- Id string
62
+ var out struct {
63
+ Was string
64
+ Now string
65
+ Id string
66
Overwrite bool
67
}
68
err = api.core().request("key/rename", oldName, newName).
client/httpapi/object.go
+197
-19
@@ -1,14 +1,17 @@
1
package httpapi
2
3
import (
4
+ "bytes"
5
"context"
5
- "github.com/ipfs/go-cid"
6
"io"
7
+ "io/ioutil"
8
9
"github.com/ipfs/go-ipfs/core/coreapi/interface"
10
caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11
12
+ "github.com/ipfs/go-cid"
13
"github.com/ipfs/go-ipld-format"
14
+ "github.com/ipfs/go-merkledag"
15
)
16
17
type ObjectAPI HttpApi
@@ -37,44 +40,219 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (
40
return api.core().nodeFromPath(ctx, iface.IpfsPath(c)), nil
41
}
42
40
-func (api *ObjectAPI) Put(context.Context, io.Reader, ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
41
- panic("implement me")
43
+func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
44
+ options, err := caopts.ObjectPutOptions(opts...)
45
+ if err != nil {
46
+ return nil, err
47
+ }
48
+
49
+ var out objectOut
50
+ err = api.core().request("object/put").
51
+ Option("inputenc", options.InputEnc).
52
+ Option("datafieldenc", options.DataType).
53
+ Option("pin", options.Pin).
54
+ FileBody(r).
55
+ Exec(ctx, &out)
56
+ if err != nil {
57
+ return nil, err
58
+ }
59
+
60
+ c, err := cid.Parse(out.Hash)
61
+ if err != nil {
62
+ return nil, err
63
+ }
64
+
65
+ return iface.IpfsPath(c), nil
66
}
67
44
-func (api *ObjectAPI) Get(context.Context, iface.Path) (format.Node, error) {
45
- panic("implement me")
68
+func (api *ObjectAPI) Get(ctx context.Context, p iface.Path) (format.Node, error) {
69
+ r, err := api.core().Block().Get(ctx, p)
70
+ if err != nil {
71
+ return nil, err
72
+ }
73
+ b, err := ioutil.ReadAll(r)
74
+ if err != nil {
75
+ return nil, err
76
+ }
77
+
78
+ return merkledag.DecodeProtobuf(b)
79
}
80
48
-func (api *ObjectAPI) Data(context.Context, iface.Path) (io.Reader, error) {
49
- panic("implement me")
81
+func (api *ObjectAPI) Data(ctx context.Context, p iface.Path) (io.Reader, error) {
82
+ resp, err := api.core().request("object/data", p.String()).Send(ctx)
83
+ if err != nil {
84
+ return nil, err
85
+ }
86
+ if resp.Error != nil {
87
+ return nil, resp.Error
88
+ }
89
+
90
+ //TODO: make Data return ReadCloser to avoid copying
91
+ defer resp.Close()
92
+ b := new(bytes.Buffer)
93
+ if _, err := io.Copy(b, resp.Output); err != nil {
94
+ return nil, err
95
+ }
96
+
97
+ return b, nil
98
}
99
52
-func (api *ObjectAPI) Links(context.Context, iface.Path) ([]*format.Link, error) {
53
- panic("implement me")
100
+func (api *ObjectAPI) Links(ctx context.Context, p iface.Path) ([]*format.Link, error) {
101
+ var out struct {
102
+ Links []struct {
103
+ Name string
104
+ Hash string
105
+ Size uint64
106
+ }
107
+ }
108
+ if err := api.core().request("object/links", p.String()).Exec(ctx, &out); err != nil {
109
+ return nil, err
110
+ }
111
+ res := make([]*format.Link, len(out.Links))
112
+ for i, l := range out.Links {
113
+ c, err := cid.Parse(l.Hash)
114
+ if err != nil {
115
+ return nil, err
116
+ }
117
+
118
+ res[i] = &format.Link{
119
+ Cid: c,
120
+ Name: l.Name,
121
+ Size: l.Size,
122
+ }
123
+ }
124
+
125
+ return res, nil
126
}
127
56
-func (api *ObjectAPI) Stat(context.Context, iface.Path) (*iface.ObjectStat, error) {
57
- panic("implement me")
128
+func (api *ObjectAPI) Stat(ctx context.Context, p iface.Path) (*iface.ObjectStat, error) {
129
+ var out struct {
130
+ Hash string
131
+ NumLinks int
132
+ BlockSize int
133
+ LinksSize int
134
+ DataSize int
135
+ CumulativeSize int
136
+ }
137
+ if err := api.core().request("object/stat", p.String()).Exec(ctx, &out); err != nil {
138
+ return nil, err
139
+ }
140
+
141
+ c, err := cid.Parse(out.Hash)
142
+ if err != nil {
143
+ return nil, err
144
+ }
145
+
146
+ return &iface.ObjectStat{
147
+ Cid: c,
148
+ NumLinks: out.NumLinks,
149
+ BlockSize: out.BlockSize,
150
+ LinksSize: out.LinksSize,
151
+ DataSize: out.DataSize,
152
+ CumulativeSize: out.CumulativeSize,
153
+ }, nil
154
}
155
156
func (api *ObjectAPI) AddLink(ctx context.Context, base iface.Path, name string, child iface.Path, opts ...caopts.ObjectAddLinkOption) (iface.ResolvedPath, error) {
61
- panic("implement me")
157
+ options, err := caopts.ObjectAddLinkOptions(opts...)
158
+ if err != nil {
159
+ return nil, err
160
+ }
161
+
162
+ var out objectOut
163
+ err = api.core().request("object/patch/add-link", base.String(), name, child.String()).
164
+ Option("create", options.Create).
165
+ Exec(ctx, &out)
166
+ if err != nil {
167
+ return nil, err
168
+ }
169
+
170
+ c, err := cid.Parse(out.Hash)
171
+ if err != nil {
172
+ return nil, err
173
+ }
174
+
175
+ return iface.IpfsPath(c), nil
176
}
177
178
func (api *ObjectAPI) RmLink(ctx context.Context, base iface.Path, link string) (iface.ResolvedPath, error) {
65
- panic("implement me")
179
+ var out objectOut
180
+ err := api.core().request("object/patch/rm-link", base.String(), link).
181
+ Exec(ctx, &out)
182
+ if err != nil {
183
+ return nil, err
184
+ }
185
+
186
+ c, err := cid.Parse(out.Hash)
187
+ if err != nil {
188
+ return nil, err
189
+ }
190
+
191
+ return iface.IpfsPath(c), nil
192
+}
193
+
194
+func (api *ObjectAPI) AppendData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
195
+ var out objectOut
196
+ err := api.core().request("object/patch/append-data", p.String()).
197
+ FileBody(r).
198
+ Exec(ctx, &out)
199
+ if err != nil {
200
+ return nil, err
201
+ }
202
+
203
+ c, err := cid.Parse(out.Hash)
204
+ if err != nil {
205
+ return nil, err
206
+ }
207
+
208
+ return iface.IpfsPath(c), nil
209
}
210
68
-func (api *ObjectAPI) AppendData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
69
- panic("implement me")
211
+func (api *ObjectAPI) SetData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
212
+ var out objectOut
213
+ err := api.core().request("object/patch/set-data", p.String()).
214
+ FileBody(r).
215
+ Exec(ctx, &out)
216
+ if err != nil {
217
+ return nil, err
218
+ }
219
+
220
+ c, err := cid.Parse(out.Hash)
221
+ if err != nil {
222
+ return nil, err
223
+ }
224
+
225
+ return iface.IpfsPath(c), nil
226
}
227
72
-func (api *ObjectAPI) SetData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
73
- panic("implement me")
228
+type change struct {
229
+ Type iface.ChangeType
230
+ Path string
231
+ Before cid.Cid
232
+ After cid.Cid
233
}
234
76
-func (api *ObjectAPI) Diff(context.Context, iface.Path, iface.Path) ([]iface.ObjectChange, error) {
77
- panic("implement me")
235
+func (api *ObjectAPI) Diff(ctx context.Context, a iface.Path, b iface.Path) ([]iface.ObjectChange, error) {
236
+ var out struct {
237
+ Changes []change
238
+ }
239
+ if err := api.core().request("object/diff", a.String(), b.String()).Exec(ctx, &out); err != nil {
240
+ return nil, err
241
+ }
242
+ res := make([]iface.ObjectChange, len(out.Changes))
243
+ for i, ch := range out.Changes {
244
+ res[i] = iface.ObjectChange{
245
+ Type: ch.Type,
246
+ Path: ch.Path,
247
+ }
248
+ if ch.Before != cid.Undef {
249
+ res[i].Before = iface.IpfsPath(ch.Before)
250
+ }
251
+ if ch.After != cid.Undef {
252
+ res[i].After = iface.IpfsPath(ch.After)
253
+ }
254
+ }
255
+ return res, nil
256
}
257
258
func (api *ObjectAPI) core() *HttpApi {
client/httpapi/pin.go
+3
-3
@@ -83,8 +83,8 @@ func (api *PinAPI) Update(ctx context.Context, from iface.Path, to iface.Path, o
83
}
84
85
type pinVerifyRes struct {
86
- Cid string
87
- JOk bool `json:"Ok"`
86
+ Cid string
87
+ JOk bool `json:"Ok"`
88
JBadNodes []*badNode `json:"BadNodes,omitempty"`
89
}
90
@@ -101,7 +101,7 @@ func (r *pinVerifyRes) BadNodes() []iface.BadPinNode {
101
}
102
103
type badNode struct {
104
- Cid string
104
+ Cid string
105
JErr string `json:"Err"`
106
}
107