Skip to content

Commit

Permalink
refactor!: remove .Remainder, coreiface.ResolvePath returns remainder
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Oct 5, 2023
1 parent dc30a58 commit 48118e1
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 91 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The following emojis are used to highlight certain changes:
condensed the different path-related packages under a single one. Therefore, there
are many breaking changes. Please consult the [documentation](https://pkg.go.dev/github.com/ipfs/boxo/path)
for more details on how to use the new package.
* 🛠 The signature of `CoreAPI.ResolvePath` in `coreiface` has changed to now return
the remainder segments as a second return value, matching the signature of `resolver.ResolveToLastNode`.

### Removed

Expand Down
6 changes: 4 additions & 2 deletions coreiface/coreapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ type CoreAPI interface {
// Routing returns an implementation of Routing API
Routing() RoutingAPI

// ResolvePath resolves the path using Unixfs resolver
ResolvePath(context.Context, path.Path) (path.ImmutablePath, error)
// ResolvePath resolves the path using UnixFS resolver, and returns the resolved
// immutable path, and the remainder of the path segments that cannot be resolved
// within UnixFS.
ResolvePath(context.Context, path.Path) (path.ImmutablePath, []string, error)

// ResolveNode resolves the path (if not resolved already) using Unixfs
// resolver, gets and returns the resolved Node
Expand Down
2 changes: 1 addition & 1 deletion coreiface/tests/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (tp *TestSuite) TestBlockGet(t *testing.T) {

p := path.NewIPFSPath(res.Path().Cid())

rp, err := api.ResolvePath(ctx, p)
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion coreiface/tests/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (tp *TestSuite) TestDagPath(t *testing.T) {
t.Fatal(err)
}

rp, err := api.ResolvePath(ctx, p)
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
t.Fatal(err)
}
Expand Down
12 changes: 6 additions & 6 deletions coreiface/tests/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ func (tp *TestSuite) TestPathRemainder(t *testing.T) {
p, err := path.Join(path.NewIPFSPath(nd.Cid()), "foo", "bar")
require.NoError(t, err)

rp1, err := api.ResolvePath(ctx, p)
_, remainder, err := api.ResolvePath(ctx, p)
require.NoError(t, err)
require.Equal(t, "/foo/bar", rp1.Remainder())
require.Equal(t, "/foo/bar", path.SegmentsToString(remainder...))
}

func (tp *TestSuite) TestEmptyPathRemainder(t *testing.T) {
Expand All @@ -74,9 +74,9 @@ func (tp *TestSuite) TestEmptyPathRemainder(t *testing.T) {
err = api.Dag().Add(ctx, nd)
require.NoError(t, err)

rp1, err := api.ResolvePath(ctx, path.NewIPFSPath(nd.Cid()))
_, remainder, err := api.ResolvePath(ctx, path.NewIPFSPath(nd.Cid()))
require.NoError(t, err)
require.Empty(t, rp1.Remainder())
require.Empty(t, remainder)
}

func (tp *TestSuite) TestInvalidPathRemainder(t *testing.T) {
Expand All @@ -96,7 +96,7 @@ func (tp *TestSuite) TestInvalidPathRemainder(t *testing.T) {
p, err := path.Join(path.NewIPLDPath(nd.Cid()), "/bar/baz")
require.NoError(t, err)

_, err = api.ResolvePath(ctx, p)
_, _, err = api.ResolvePath(ctx, p)
require.NotNil(t, err)
require.ErrorContains(t, err, `no link named "bar"`)
}
Expand All @@ -122,7 +122,7 @@ func (tp *TestSuite) TestPathRoot(t *testing.T) {
p, err := path.Join(path.NewIPLDPath(nd.Cid()), "/foo")
require.NoError(t, err)

rp, err := api.ResolvePath(ctx, p)
rp, _, err := api.ResolvePath(ctx, p)
require.NoError(t, err)
require.Equal(t, rp.Cid().String(), blk.Path().Cid().String())
}
Expand Down
57 changes: 34 additions & 23 deletions gateway/blocks_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,14 +538,15 @@ func walkGatewaySimpleSelector(ctx context.Context, p path.ImmutablePath, params
}

func (bb *BlocksBackend) getNode(ctx context.Context, path path.ImmutablePath) (ContentPathMetadata, format.Node, error) {
roots, lastSeg, err := bb.getPathRoots(ctx, path)
roots, lastSeg, remainder, err := bb.getPathRoots(ctx, path)
if err != nil {
return ContentPathMetadata{}, nil, err
}

md := ContentPathMetadata{
PathSegmentRoots: roots,
LastSegment: lastSeg,
PathSegmentRoots: roots,
LastSegment: lastSeg,
LastSegmentRemainder: remainder,
}

lastRoot := lastSeg.Cid()
Expand All @@ -558,7 +559,7 @@ func (bb *BlocksBackend) getNode(ctx context.Context, path path.ImmutablePath) (
return md, nd, err
}

func (bb *BlocksBackend) getPathRoots(ctx context.Context, contentPath path.ImmutablePath) ([]cid.Cid, path.ImmutablePath, error) {
func (bb *BlocksBackend) getPathRoots(ctx context.Context, contentPath path.ImmutablePath) ([]cid.Cid, path.ImmutablePath, []string, error) {
/*
These are logical roots where each CID represent one path segment
and resolves to either a directory or the root block of a file.
Expand All @@ -582,7 +583,10 @@ func (bb *BlocksBackend) getPathRoots(ctx context.Context, contentPath path.Immu
contentPathStr := contentPath.String()
pathSegments := strings.Split(contentPathStr[6:], "/")
sp.WriteString(contentPathStr[:5]) // /ipfs or /ipns
var lastPath path.ImmutablePath
var (
lastPath path.ImmutablePath
remainder []string
)
for _, root := range pathSegments {
if root == "" {
continue
Expand All @@ -591,23 +595,24 @@ func (bb *BlocksBackend) getPathRoots(ctx context.Context, contentPath path.Immu
sp.WriteString(root)
p, err := path.NewPath(sp.String())
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
resolvedSubPath, err := bb.resolvePath(ctx, p)
resolvedSubPath, remainderSubPath, err := bb.resolvePath(ctx, p)
if err != nil {
// TODO: should we be more explicit here and is this part of the IPFSBackend contract?
// The issue here was that we returned datamodel.ErrWrongKind instead of this resolver error
if isErrNotFound(err) {
return nil, nil, &resolver.ErrNoLink{Name: root, Node: lastPath.Cid()}
return nil, nil, nil, &resolver.ErrNoLink{Name: root, Node: lastPath.Cid()}
}
return nil, nil, err
return nil, nil, nil, err
}
lastPath = resolvedSubPath
remainder = remainderSubPath
pathRoots = append(pathRoots, lastPath.Cid())
}

pathRoots = pathRoots[:len(pathRoots)-1]
return pathRoots, lastPath, nil
return pathRoots, lastPath, remainder, nil
}

func (bb *BlocksBackend) ResolveMutable(ctx context.Context, p path.Path) (path.ImmutablePath, error) {
Expand Down Expand Up @@ -658,7 +663,7 @@ func (bb *BlocksBackend) GetDNSLinkRecord(ctx context.Context, hostname string)
}

func (bb *BlocksBackend) IsCached(ctx context.Context, p path.Path) bool {
rp, err := bb.resolvePath(ctx, p)
rp, _, err := bb.resolvePath(ctx, p)
if err != nil {
return false
}
Expand All @@ -668,46 +673,52 @@ func (bb *BlocksBackend) IsCached(ctx context.Context, p path.Path) bool {
}

func (bb *BlocksBackend) ResolvePath(ctx context.Context, path path.ImmutablePath) (ContentPathMetadata, error) {
roots, lastSeg, err := bb.getPathRoots(ctx, path)
roots, lastSeg, remainder, err := bb.getPathRoots(ctx, path)
if err != nil {
return ContentPathMetadata{}, err
}
md := ContentPathMetadata{
PathSegmentRoots: roots,
LastSegment: lastSeg,
PathSegmentRoots: roots,
LastSegment: lastSeg,
LastSegmentRemainder: remainder,
}
return md, nil
}

func (bb *BlocksBackend) resolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, error) {
func (bb *BlocksBackend) resolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, []string, error) {
var err error
if p.Namespace() == path.IPNSNamespace {
p, err = resolve.ResolveIPNS(ctx, bb.namesys, p)
if err != nil {
return nil, err
return nil, nil, err
}
}

if p.Namespace() != path.IPFSNamespace {
return nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace())
return nil, nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace())
}

imPath, err := path.NewImmutablePath(p)
if err != nil {
return nil, err
return nil, nil, err
}

node, rest, err := bb.resolver.ResolveToLastNode(ctx, imPath)
node, remainder, err := bb.resolver.ResolveToLastNode(ctx, imPath)
if err != nil {
return nil, err
return nil, nil, err
}

p, err = path.Join(path.NewIPFSPath(node), rest...)
p, err = path.Join(path.NewIPFSPath(node), remainder...)
if err != nil {
return nil, err
return nil, nil, err
}

imPath, err = path.NewImmutablePath(p)
if err != nil {
return nil, nil, err
}

return path.NewImmutablePath(p)
return imPath, remainder, nil
}

type nodeGetterToCarExporer struct {
Expand Down
7 changes: 4 additions & 3 deletions gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,10 @@ func (d DuplicateBlocksPolicy) String() string {
}

type ContentPathMetadata struct {
PathSegmentRoots []cid.Cid
LastSegment path.ImmutablePath
ContentType string // Only used for UnixFS requests
PathSegmentRoots []cid.Cid
LastSegment path.ImmutablePath
LastSegmentRemainder []string
ContentType string // Only used for UnixFS requests
}

// ByteRange describes a range request within a UnixFS file. "From" and "To" mostly
Expand Down
7 changes: 4 additions & 3 deletions gateway/handler_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ func (i *handler) renderCodec(ctx context.Context, w http.ResponseWriter, r *htt
// If the resolved path still has some remainder, return error for now.
// TODO: handle this when we have IPLD Patch (https://ipld.io/specs/patch/) via HTTP PUT
// TODO: (depends on https://github.com/ipfs/kubo/issues/4801 and https://github.com/ipfs/kubo/issues/4782)
if resolvedPath.Remainder() != "" {
path := strings.TrimSuffix(resolvedPath.String(), resolvedPath.Remainder())
err := fmt.Errorf("%q of %q could not be returned: reading IPLD Kinds other than Links (CBOR Tag 42) is not implemented: try reading %q instead", resolvedPath.Remainder(), resolvedPath.String(), path)
if len(rq.pathMetadata.LastSegmentRemainder) != 0 {
remainderStr := path.SegmentsToString(rq.pathMetadata.LastSegmentRemainder...)
path := strings.TrimSuffix(resolvedPath.String(), remainderStr)
err := fmt.Errorf("%q of %q could not be returned: reading IPLD Kinds other than Links (CBOR Tag 42) is not implemented: try reading %q instead", remainderStr, resolvedPath.String(), path)
i.webError(w, r, err, http.StatusNotImplemented)
return false
}
Expand Down

0 comments on commit 48118e1

Please sign in to comment.