@cryptotaxi247 / kubo / commits / ddd36645b

feat: update the error parsing for go-ipld-format to v0.4.0

This commit was moved from ipfs/go-ipfs-http-client@296534fd1647a1ec9cae08314daf41ec96d55763

Jorropo committed Mar 31, 2022 at 23:43 UTC ddd36645b25c97651deb81c092c7669efabd959e
2 files changed +44 -24
client/httpapi/errors.go
+33 -21
@@ -45,6 +45,18 @@ func parseIPLDNotFoundWithFallbackToError(msg error) error {
45 return msg
46 }
47
48 +// Use a string to move it into RODATA
49 +// print("".join("\\x01" if chr(i) not in string.ascii_letters + string.digits else "\\x00" for i in range(ord('z')+1)))
50 +const notAsciiLetterOrDigitsLUT = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
51 +
52 +func notAsciiLetterOrDigits(r rune) bool {
53 + if r > 'z' {
54 + return true
55 + }
56 +
57 + return notAsciiLetterOrDigitsLUT[r] > 0
58 +}
59 +
60 // This file handle parsing and returning the correct ABI based errors from error messages
61 //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
62 func parseIPLDNotFound(msg string) (error, bool) {
@@ -53,46 +65,46 @@ func parseIPLDNotFound(msg string) (error, bool) {
65 }
66
67 // 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")
68 + const ipldErrNotFoundKey = "ipld: could not find " /*CID*/
69 + // We try to parse the CID, if it's invalid we give up and return a simple text error.
70 + // We also accept "node" in place of the CID because that means it's an Undefined CID.
71
61 - if notFoundIndex == -1 {
62 - // Unknown, ot found not found
72 + keyIndex := strings.Index(msg, ipldErrNotFoundKey)
73 +
74 + if keyIndex < 0 { // Unknown error
75 return nil, false
76 }
77
66 - preNotFound := msg[:notFoundIndex]
78 + cidStart := keyIndex + len(ipldErrNotFoundKey)
79
80 + msgPostKey := msg[cidStart:]
81 var c cid.Cid
69 - var preIndex int
70 - if strings.HasSuffix(preNotFound, "node") {
82 + var postIndex int
83 + if strings.HasPrefix(msgPostKey, "node") {
84 // Fallback case
85 c = cid.Undef
73 - preIndex = notFoundIndex - len("node")
86 + postIndex = len("node")
87 } 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++
88 + // Assume that CIDs only contain a-zA-Z0-9 characters.
89 + // This is true because go-ipld-format use go-cid#Cid.String which use base{3{2,6},58}.
90 + postIndex = strings.IndexFunc(msgPostKey, notAsciiLetterOrDigits)
91 + if postIndex < 0 {
92 + postIndex = len(msgPostKey)
93 + }
94 +
95 var err error
80 - c, err = cid.Decode(preNotFound[preIndex:])
96 + c, err = cid.Decode(msgPostKey[:postIndex])
97 if err != nil {
98 // Unknown
99 return nil, false
100 }
101 }
102
87 - postIndex := notFoundIndex + len(" not found")
88 -
103 err := ipld.ErrNotFound{Cid: c}
90 -
91 - pre := msg[:preIndex]
92 - post := msg[postIndex:]
104 + pre := msg[:keyIndex]
105 + post := msgPostKey[postIndex:]
106
107 if len(pre) > 0 || len(post) > 0 {
95 - // We have some text to wrap arround the ErrNotFound one
108 return prePostWrappedNotFoundError{
109 pre: pre,
110 post: post,
client/httpapi/errors_test.go
+11 -3
@@ -3,6 +3,7 @@ package httpapi
3 import (
4 "errors"
5 "fmt"
6 + "strings"
7 "testing"
8
9 "github.com/ipfs/go-cid"
@@ -42,9 +43,8 @@ func TestParseIPLDNotFound(t *testing.T) {
43 "%w is wrong",
44 } {
45 for _, err := range [...]error{
45 - errors.New("file not found"),
46 - errors.New(" not found"),
47 - errors.New("Bad_CID not found"),
46 + errors.New("ipld: could not find "),
47 + errors.New("ipld: could not find Bad_CID"),
48 errors.New("network connection timeout"),
49 ipld.ErrNotFound{Cid: cid.Undef},
50 ipld.ErrNotFound{Cid: cid.NewCidV0(randomSha256MH)},
@@ -58,3 +58,11 @@ func TestParseIPLDNotFound(t *testing.T) {
58 }
59 }
60 }
61 +
62 +func TestNotAsciiLetterOrDigits(t *testing.T) {
63 + for i := rune(0); i <= 256; i++ {
64 + if notAsciiLetterOrDigits(i) != !strings.ContainsAny(string(i), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {
65 + t.Errorf("%q is incorrectly identified", i)
66 + }
67 + }
68 +}