Implement Object API

This commit was moved from ipfs/go-ipfs-http-client@38149e46c8
This commit is contained in:
Łukasz Magiera 2019-01-15 16:31:07 +01:00
parent 9d647d011e
commit eaa19388d4
5 changed files with 208 additions and 31 deletions

View File

@ -67,7 +67,7 @@ func (api *BlockAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.BlockP
}
func (api *BlockAPI) Get(ctx context.Context, p iface.Path) (io.Reader, error) {
resp, err := api.core().request("block/get", p.String()).Send(context.Background())
resp, err := api.core().request("block/get", p.String()).Send(ctx)
if err != nil {
return nil, err
}

View File

@ -3,7 +3,6 @@ package httpapi
import (
"context"
"errors"
"fmt"
"io/ioutil"
"strconv"
@ -20,11 +19,11 @@ type ipldNode struct {
api *HttpApi
}
func (a *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
func (api *HttpApi) nodeFromPath(ctx context.Context, p iface.ResolvedPath) ipld.Node {
return &ipldNode{
ctx: ctx,
path: p,
api: a,
api: api,
}
}
@ -47,7 +46,7 @@ func (n *ipldNode) Cid() cid.Cid {
}
func (n *ipldNode) String() string {
return fmt.Sprintf("[Block %s]", n.Cid())
return n.Cid().String()
}
func (n *ipldNode) Loggable() map[string]interface{} {

View File

@ -59,10 +59,10 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
return nil, false, err
}
var out struct{
Was string
Now string
Id string
var out struct {
Was string
Now string
Id string
Overwrite bool
}
err = api.core().request("key/rename", oldName, newName).

View File

@ -1,14 +1,17 @@
package httpapi
import (
"bytes"
"context"
"github.com/ipfs/go-cid"
"io"
"io/ioutil"
"github.com/ipfs/go-ipfs/core/coreapi/interface"
caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-merkledag"
)
type ObjectAPI HttpApi
@ -37,44 +40,219 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (
return api.core().nodeFromPath(ctx, iface.IpfsPath(c)), nil
}
func (api *ObjectAPI) Put(context.Context, io.Reader, ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
panic("implement me")
func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (iface.ResolvedPath, error) {
options, err := caopts.ObjectPutOptions(opts...)
if err != nil {
return nil, err
}
var out objectOut
err = api.core().request("object/put").
Option("inputenc", options.InputEnc).
Option("datafieldenc", options.DataType).
Option("pin", options.Pin).
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return iface.IpfsPath(c), nil
}
func (api *ObjectAPI) Get(context.Context, iface.Path) (format.Node, error) {
panic("implement me")
func (api *ObjectAPI) Get(ctx context.Context, p iface.Path) (format.Node, error) {
r, err := api.core().Block().Get(ctx, p)
if err != nil {
return nil, err
}
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
return merkledag.DecodeProtobuf(b)
}
func (api *ObjectAPI) Data(context.Context, iface.Path) (io.Reader, error) {
panic("implement me")
func (api *ObjectAPI) Data(ctx context.Context, p iface.Path) (io.Reader, error) {
resp, err := api.core().request("object/data", p.String()).Send(ctx)
if err != nil {
return nil, err
}
if resp.Error != nil {
return nil, resp.Error
}
//TODO: make Data return ReadCloser to avoid copying
defer resp.Close()
b := new(bytes.Buffer)
if _, err := io.Copy(b, resp.Output); err != nil {
return nil, err
}
return b, nil
}
func (api *ObjectAPI) Links(context.Context, iface.Path) ([]*format.Link, error) {
panic("implement me")
func (api *ObjectAPI) Links(ctx context.Context, p iface.Path) ([]*format.Link, error) {
var out struct {
Links []struct {
Name string
Hash string
Size uint64
}
}
if err := api.core().request("object/links", p.String()).Exec(ctx, &out); err != nil {
return nil, err
}
res := make([]*format.Link, len(out.Links))
for i, l := range out.Links {
c, err := cid.Parse(l.Hash)
if err != nil {
return nil, err
}
res[i] = &format.Link{
Cid: c,
Name: l.Name,
Size: l.Size,
}
}
return res, nil
}
func (api *ObjectAPI) Stat(context.Context, iface.Path) (*iface.ObjectStat, error) {
panic("implement me")
func (api *ObjectAPI) Stat(ctx context.Context, p iface.Path) (*iface.ObjectStat, error) {
var out struct {
Hash string
NumLinks int
BlockSize int
LinksSize int
DataSize int
CumulativeSize int
}
if err := api.core().request("object/stat", p.String()).Exec(ctx, &out); err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return &iface.ObjectStat{
Cid: c,
NumLinks: out.NumLinks,
BlockSize: out.BlockSize,
LinksSize: out.LinksSize,
DataSize: out.DataSize,
CumulativeSize: out.CumulativeSize,
}, nil
}
func (api *ObjectAPI) AddLink(ctx context.Context, base iface.Path, name string, child iface.Path, opts ...caopts.ObjectAddLinkOption) (iface.ResolvedPath, error) {
panic("implement me")
options, err := caopts.ObjectAddLinkOptions(opts...)
if err != nil {
return nil, err
}
var out objectOut
err = api.core().request("object/patch/add-link", base.String(), name, child.String()).
Option("create", options.Create).
Exec(ctx, &out)
if err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return iface.IpfsPath(c), nil
}
func (api *ObjectAPI) RmLink(ctx context.Context, base iface.Path, link string) (iface.ResolvedPath, error) {
panic("implement me")
var out objectOut
err := api.core().request("object/patch/rm-link", base.String(), link).
Exec(ctx, &out)
if err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return iface.IpfsPath(c), nil
}
func (api *ObjectAPI) AppendData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
panic("implement me")
func (api *ObjectAPI) AppendData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
var out objectOut
err := api.core().request("object/patch/append-data", p.String()).
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return iface.IpfsPath(c), nil
}
func (api *ObjectAPI) SetData(context.Context, iface.Path, io.Reader) (iface.ResolvedPath, error) {
panic("implement me")
func (api *ObjectAPI) SetData(ctx context.Context, p iface.Path, r io.Reader) (iface.ResolvedPath, error) {
var out objectOut
err := api.core().request("object/patch/set-data", p.String()).
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
}
return iface.IpfsPath(c), nil
}
func (api *ObjectAPI) Diff(context.Context, iface.Path, iface.Path) ([]iface.ObjectChange, error) {
panic("implement me")
type change struct {
Type iface.ChangeType
Path string
Before cid.Cid
After cid.Cid
}
func (api *ObjectAPI) Diff(ctx context.Context, a iface.Path, b iface.Path) ([]iface.ObjectChange, error) {
var out struct {
Changes []change
}
if err := api.core().request("object/diff", a.String(), b.String()).Exec(ctx, &out); err != nil {
return nil, err
}
res := make([]iface.ObjectChange, len(out.Changes))
for i, ch := range out.Changes {
res[i] = iface.ObjectChange{
Type: ch.Type,
Path: ch.Path,
}
if ch.Before != cid.Undef {
res[i].Before = iface.IpfsPath(ch.Before)
}
if ch.After != cid.Undef {
res[i].After = iface.IpfsPath(ch.After)
}
}
return res, nil
}
func (api *ObjectAPI) core() *HttpApi {

View File

@ -83,8 +83,8 @@ func (api *PinAPI) Update(ctx context.Context, from iface.Path, to iface.Path, o
}
type pinVerifyRes struct {
Cid string
JOk bool `json:"Ok"`
Cid string
JOk bool `json:"Ok"`
JBadNodes []*badNode `json:"BadNodes,omitempty"`
}
@ -101,7 +101,7 @@ func (r *pinVerifyRes) BadNodes() []iface.BadPinNode {
}
type badNode struct {
Cid string
Cid string
JErr string `json:"Err"`
}