Skip to content

Commit

Permalink
refactor: do not assume namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Aug 11, 2023
1 parent 0e88cb9 commit e688ad9
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 43 deletions.
12 changes: 12 additions & 0 deletions namesys/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

opts "github.com/ipfs/boxo/coreiface/options/namesys"
path "github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
dns "github.com/miekg/dns"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
Expand Down Expand Up @@ -177,6 +178,11 @@ func workDomain(ctx context.Context, r *DNSResolver, name string, res chan looku
}

func parseEntry(txt string) (path.Path, error) {
if cid, err := cid.Decode(txt); err == nil {
// Support legacy DNSLink records that do not start with dnslink=
return path.NewIPFSPath(cid), nil
}

p, err := path.NewPath(txt) // bare IPFS multihashes
if err == nil {
return p, nil
Expand All @@ -188,6 +194,12 @@ func parseEntry(txt string) (path.Path, error) {
func tryParseDNSLink(txt string) (path.Path, error) {
parts := strings.SplitN(txt, "=", 2)
if len(parts) == 2 && parts[0] == "dnslink" {
if cid, err := cid.Decode(parts[1]); err == nil {
// Support legacy DNSLink records that do not contain a namespace
// at the beginning of the path.
return path.NewIPFSPath(cid), nil
}

return path.NewPath(parts[1])
}

Expand Down
4 changes: 2 additions & 2 deletions namesys/namesys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestPublishWithCache0(t *testing.T) {
}

// CID is arbitrary.
p, err := path.NewPath("QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
p, err := path.NewPath("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -159,7 +159,7 @@ func TestPublishWithTTL(t *testing.T) {
}

// CID is arbitrary.
p, err := path.NewPath("QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
p, err := path.NewPath("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
if err != nil {
t.Fatal(err)
}
Expand Down
46 changes: 9 additions & 37 deletions path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ func (ip ImmutablePath) Segments() []string {
return ip.path.Segments()
}

var _ Path = path{}

type path struct {
str string
root cid.Cid
Expand Down Expand Up @@ -133,6 +135,8 @@ func (p path) Segments() []string {
return strings.Split(str, "/")
}

var _ ResolvedPath = resolvedPath{}

type resolvedPath struct {
path
cid cid.Cid
Expand Down Expand Up @@ -174,6 +178,9 @@ func NewIPLDPath(cid cid.Cid) ResolvedPath {
}

// NewIPNSPath returns a new "/ipns" path with the provided CID.
// TODO: it is better to use [ipns.Name], but that leads to import cycle. Maybe
// this specific function could be moved to the iPNS package? It'sn an IPNS path
// after all.
func NewIPNSPath(cid cid.Cid) Path {
return &path{
str: fmt.Sprintf("/%s/%s", IPNSNamespace, cid.String()),
Expand All @@ -191,16 +198,8 @@ func NewDNSLinkPath(domain string) Path {
}

// NewPath returns a well-formed [Path]. The returned path will always be prefixed
// with a valid namespace (/ipfs, /ipld, or /ipns). The prefix will be added if not
// present in the given string. The rules are:
//
// 1. If the path has a single component (no slashes) ans it is a valid CID,
// an /ipfs path is returned. If the CID is encoded with the Libp2pKey codec,
// then a /ipns path is returned.
// 2. If the path has a valid CID root but does not have a namespace, the /ipfs
// namespace is automatically added.
//
// This function returns an error when the given string is not a valid path.
// with a valid namespace (/ipfs, /ipld, or /ipns). This function returns an error
// when the given string is not a valid path.
func NewPath(str string) (Path, error) {
cleaned := gopath.Clean(str)
components := strings.Split(cleaned, "/")
Expand All @@ -210,33 +209,6 @@ func NewPath(str string) (Path, error) {
cleaned += "/"
}

// If there's only one component, check if it's a CID, or Peer ID.
if len(components) == 1 {
c, err := cid.Decode(components[0])
if err == nil {
if c.Prefix().GetCodec() == cid.Libp2pKey {
return NewIPNSPath(c), nil
} else {
return NewIPFSPath(c), nil
}
}
}

// If the path doesn't begin with a "/", we expect it to start with a CID and
// be an IPFS Path.
if components[0] != "" {
root, err := cid.Decode(components[0])
if err != nil {
return nil, &ErrInvalidPath{error: err, path: str}
}

return &path{
str: cleaned,
root: root,
namespace: IPFSNamespace,
}, nil
}

if len(components) < 3 {
return nil, &ErrInvalidPath{error: fmt.Errorf("not enough path components"), path: str}
}
Expand Down
4 changes: 2 additions & 2 deletions path/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ func TestPathParsing(t *testing.T) {
"/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true,
"/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true,
"/ipns/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true,
"QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": true,
"QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": true,
"QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a/b/c/d/e/f": false,
"QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": false,
"/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n": false,
"/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n/a": false,
"/ipfs/foo": false,
Expand Down
4 changes: 2 additions & 2 deletions path/resolver/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func TestPathRemainder(t *testing.T) {
fetcherFactory := bsfetcher.NewFetcherConfig(bsrv)
resolver := resolver.NewBasicResolver(fetcherFactory)

newPath, err := path.NewPath(lnk.String() + "/foo/bar")
newPath, err := path.Join(path.NewIPFSPath(lnk), "foo", "bar")
require.NoError(t, err)

rp1, remainder, err := resolver.ResolveToLastNode(ctx, newPath)
Expand Down Expand Up @@ -288,7 +288,7 @@ func TestResolveToLastNode_MixedSegmentTypes(t *testing.T) {
fetcherFactory := bsfetcher.NewFetcherConfig(bsrv)
resolver := resolver.NewBasicResolver(fetcherFactory)

newPath, err := path.NewPath(lnk.String() + "/foo/bar/1/boom/3")
newPath, err := path.Join(path.NewIPFSPath(lnk), "foo", "bar", "1", "boom", "3")
require.NoError(t, err)

cid, remainder, err := resolver.ResolveToLastNode(ctx, newPath)
Expand Down

0 comments on commit e688ad9

Please sign in to comment.