Skip to content
This repository was archived by the owner on Oct 5, 2023. It is now read-only.

Commit 647592e

Browse files
committed
fix: make Block().* return correct ABI based ipld.ErrNotFound errors
1 parent 0675169 commit 647592e

File tree

5 files changed

+418
-32
lines changed

5 files changed

+418
-32
lines changed

abyfy_errors.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package httpapi
2+
3+
import (
4+
"errors"
5+
"strings"
6+
7+
"github.com/ipfs/go-cid"
8+
ipld "github.com/ipfs/go-ipld-format"
9+
)
10+
11+
type prePostWrappedNotFoundError struct {
12+
pre string
13+
post string
14+
15+
wrapped ipld.ErrNotFound
16+
}
17+
18+
func (e prePostWrappedNotFoundError) String() string {
19+
return e.Error()
20+
}
21+
22+
func (e prePostWrappedNotFoundError) Error() string {
23+
return e.pre + e.wrapped.Error() + e.post
24+
}
25+
26+
func (e prePostWrappedNotFoundError) Unwrap() error {
27+
return e.wrapped
28+
}
29+
30+
func abyfyIpldNotFoundFallbackToMSG(msg string) error {
31+
err, handled := abyfyIpldNotFound(msg)
32+
if handled {
33+
return err
34+
}
35+
36+
return errors.New(msg)
37+
}
38+
39+
func abyfyIpldNotFoundFallbackToError(msg error) error {
40+
err, handled := abyfyIpldNotFound(msg.Error())
41+
if handled {
42+
return err
43+
}
44+
45+
return err
46+
}
47+
48+
// This file handle parsing and returning the correct ABI based errors from error messages
49+
//lint: ignore ST1008 this function is not using the error as a mean to return failure but it massages it to return the correct type
50+
func abyfyIpldNotFound(msg string) (error, bool) {
51+
if msg == "" {
52+
return nil, true // Fast path
53+
}
54+
55+
// The patern we search for is:
56+
// node not found (fallback)
57+
// or
58+
// CID not found (here we parse the CID)
59+
notFoundIndex := strings.LastIndex(msg, " not found")
60+
61+
if notFoundIndex == -1 {
62+
// Unknown, ot found not found
63+
return nil, false
64+
}
65+
66+
preNotFound := msg[:notFoundIndex]
67+
68+
var c cid.Cid
69+
var preIndex int
70+
if strings.HasSuffix(preNotFound, "node") {
71+
// Fallback case
72+
c = cid.Undef
73+
preIndex = notFoundIndex - len("node")
74+
} else {
75+
// Assume that CIDs does not include whitespace to pull out the CID
76+
preIndex = strings.LastIndexByte(preNotFound, ' ')
77+
// + 1 is to normalise not founds to zeros and point to the start of the CID, not the previous space
78+
preIndex++
79+
var err error
80+
c, err = cid.Decode(preNotFound[preIndex:])
81+
if err != nil {
82+
// Unknown
83+
return nil, false
84+
}
85+
}
86+
87+
postIndex := notFoundIndex + len(" not found")
88+
89+
err := ipld.ErrNotFound{Cid: c}
90+
91+
pre := msg[:preIndex]
92+
post := msg[postIndex:]
93+
94+
if len(pre) > 0 || len(post) > 0 {
95+
// We have some text to wrap arround the ErrNotFound one
96+
return prePostWrappedNotFoundError{
97+
pre: pre,
98+
post: post,
99+
wrapped: err,
100+
}, true
101+
}
102+
103+
return err, true
104+
}

abyfy_errors_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package httpapi
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/ipfs/go-cid"
9+
ipld "github.com/ipfs/go-ipld-format"
10+
mh "github.com/multiformats/go-multihash"
11+
)
12+
13+
var randomSha256MH = mh.Multihash{0x12, 0x20, 0x88, 0x82, 0x73, 0x37, 0x7c, 0xc1, 0xc9, 0x96, 0xad, 0xee, 0xd, 0x26, 0x84, 0x2, 0xc9, 0xc9, 0x5c, 0xf9, 0x5c, 0x4d, 0x9b, 0xc3, 0x3f, 0xfb, 0x4a, 0xd8, 0xaf, 0x28, 0x6b, 0xca, 0x1a, 0xf2}
14+
15+
func doAbyfyIpldNotFoundTest(t *testing.T, original error) {
16+
originalMsg := original.Error()
17+
18+
rebuilt := abyfyIpldNotFoundFallbackToMSG(originalMsg)
19+
20+
rebuiltMsg := rebuilt.Error()
21+
22+
if originalMsg != rebuiltMsg {
23+
t.Errorf("expected message to be %q; got %q", originalMsg, rebuiltMsg)
24+
}
25+
26+
originalNotFound := ipld.IsNotFound(original)
27+
rebuiltNotFound := ipld.IsNotFound(original)
28+
if originalNotFound != rebuiltNotFound {
29+
t.Errorf("expected Ipld.IsNotFound to be %t; got %t", originalNotFound, rebuiltNotFound)
30+
}
31+
}
32+
33+
func TestAbyfyIpldNotFound(t *testing.T) {
34+
if err := abyfyIpldNotFoundFallbackToMSG(""); err != nil {
35+
t.Errorf("expected empty string to give no error; got %T %q", err, err.Error())
36+
}
37+
38+
for _, wrap := range [...]string{
39+
"",
40+
"merkledag: %w",
41+
"testing: %w the test",
42+
"%w is wrong",
43+
} {
44+
for _, err := range [...]error{
45+
errors.New("file not found"),
46+
errors.New(" not found"),
47+
errors.New("Bad_CID not found"),
48+
errors.New("network connection timeout"),
49+
ipld.ErrNotFound{Cid: cid.Undef},
50+
ipld.ErrNotFound{Cid: cid.NewCidV0(randomSha256MH)},
51+
ipld.ErrNotFound{Cid: cid.NewCidV1(cid.Raw, randomSha256MH)},
52+
} {
53+
if wrap != "" {
54+
err = fmt.Errorf(wrap, err)
55+
}
56+
57+
doAbyfyIpldNotFoundTest(t, err)
58+
}
59+
}
60+
}

block.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package httpapi
33
import (
44
"bytes"
55
"context"
6-
"errors"
76
"fmt"
87
"io"
98

@@ -67,7 +66,7 @@ func (api *BlockAPI) Get(ctx context.Context, p path.Path) (io.Reader, error) {
6766
return nil, err
6867
}
6968
if resp.Error != nil {
70-
return nil, resp.Error
69+
return nil, abyfyIpldNotFoundFallbackToError(resp.Error)
7170
}
7271

7372
//TODO: make get return ReadCloser to avoid copying
@@ -99,18 +98,14 @@ func (api *BlockAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.BlockRm
9998
return err
10099
}
101100

102-
if removedBlock.Error != "" {
103-
return errors.New(removedBlock.Error)
104-
}
105-
106-
return nil
101+
return abyfyIpldNotFoundFallbackToMSG(removedBlock.Error)
107102
}
108103

109104
func (api *BlockAPI) Stat(ctx context.Context, p path.Path) (iface.BlockStat, error) {
110105
var out blockStat
111106
err := api.core().Request("block/stat", p.String()).Exec(ctx, &out)
112107
if err != nil {
113-
return nil, err
108+
return nil, abyfyIpldNotFoundFallbackToError(err)
114109
}
115110
out.cid, err = cid.Parse(out.Key)
116111
if err != nil {

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ require (
55
github.com/ipfs/go-cid v0.0.7
66
github.com/ipfs/go-ipfs-cmds v0.6.0
77
github.com/ipfs/go-ipfs-files v0.0.8
8-
github.com/ipfs/go-ipld-format v0.2.0
9-
github.com/ipfs/go-merkledag v0.4.0
8+
github.com/ipfs/go-ipld-format v0.3.1
9+
github.com/ipfs/go-merkledag v0.6.0
1010
github.com/ipfs/go-path v0.1.1
1111
github.com/ipfs/go-unixfs v0.2.5
12-
github.com/ipfs/interface-go-ipfs-core v0.5.2
12+
github.com/ipfs/interface-go-ipfs-core v0.6.1
1313
github.com/ipfs/iptb v1.4.0
1414
github.com/ipfs/iptb-plugins v0.3.0
1515
github.com/libp2p/go-libp2p-core v0.8.6

0 commit comments

Comments
 (0)