kubo/client/httpapi/errors.go

105 lines
2.2 KiB
Go

package httpapi
import (
"errors"
"strings"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
type prePostWrappedNotFoundError struct {
pre string
post string
wrapped ipld.ErrNotFound
}
func (e prePostWrappedNotFoundError) String() string {
return e.Error()
}
func (e prePostWrappedNotFoundError) Error() string {
return e.pre + e.wrapped.Error() + e.post
}
func (e prePostWrappedNotFoundError) Unwrap() error {
return e.wrapped
}
func parseIPLDNotFoundWithFallbackToMSG(msg string) error {
err, handled := parseIPLDNotFound(msg)
if handled {
return err
}
return errors.New(msg)
}
func parseIPLDNotFoundWithFallbackToError(msg error) error {
err, handled := parseIPLDNotFound(msg.Error())
if handled {
return err
}
return msg
}
// This file handle parsing and returning the correct ABI based errors from error messages
//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
func parseIPLDNotFound(msg string) (error, bool) {
if msg == "" {
return nil, true // Fast path
}
// The patern we search for is:
// node not found (fallback)
// or
// CID not found (here we parse the CID)
notFoundIndex := strings.LastIndex(msg, " not found")
if notFoundIndex == -1 {
// Unknown, ot found not found
return nil, false
}
preNotFound := msg[:notFoundIndex]
var c cid.Cid
var preIndex int
if strings.HasSuffix(preNotFound, "node") {
// Fallback case
c = cid.Undef
preIndex = notFoundIndex - len("node")
} else {
// Assume that CIDs does not include whitespace to pull out the CID
preIndex = strings.LastIndexByte(preNotFound, ' ')
// + 1 is to normalise not founds to zeros and point to the start of the CID, not the previous space
preIndex++
var err error
c, err = cid.Decode(preNotFound[preIndex:])
if err != nil {
// Unknown
return nil, false
}
}
postIndex := notFoundIndex + len(" not found")
err := ipld.ErrNotFound{Cid: c}
pre := msg[:preIndex]
post := msg[postIndex:]
if len(pre) > 0 || len(post) > 0 {
// We have some text to wrap arround the ErrNotFound one
return prePostWrappedNotFoundError{
pre: pre,
post: post,
wrapped: err,
}, true
}
return err, true
}