diff --git a/coreiface/tests/unixfs.go b/coreiface/tests/unixfs.go index e0c37fce4..31ac1b5c9 100644 --- a/coreiface/tests/unixfs.go +++ b/coreiface/tests/unixfs.go @@ -408,7 +408,7 @@ func (tp *TestSuite) TestAdd(t *testing.T) { t.Errorf("Event.Name didn't match, %s != %s", expected[0].Name, event.Name) } - if expected[0].Path != nil && event.Path != nil { + if (expected[0].Path != path.ImmutablePath{} && event.Path != path.ImmutablePath{}) { if expected[0].Path.RootCid().String() != event.Path.RootCid().String() { t.Errorf("Event.Hash didn't match, %s != %s", expected[0].Path, event.Path) } diff --git a/gateway/blocks_backend.go b/gateway/blocks_backend.go index 6868d3247..db5f68924 100644 --- a/gateway/blocks_backend.go +++ b/gateway/blocks_backend.go @@ -595,16 +595,16 @@ 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, nil, err + return nil, path.ImmutablePath{}, nil, err } 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, nil, &resolver.ErrNoLink{Name: root, Node: lastPath.RootCid()} + return nil, path.ImmutablePath{}, nil, &resolver.ErrNoLink{Name: root, Node: lastPath.RootCid()} } - return nil, nil, nil, err + return nil, path.ImmutablePath{}, nil, err } lastPath = resolvedSubPath remainder = remainderSubPath @@ -620,13 +620,13 @@ func (bb *BlocksBackend) ResolveMutable(ctx context.Context, p path.Path) (path. case path.IPNSNamespace: p, err := resolve.ResolveIPNS(ctx, bb.namesys, p) if err != nil { - return nil, err + return path.ImmutablePath{}, err } return path.NewImmutablePath(p) case path.IPFSNamespace: return path.NewImmutablePath(p) default: - return nil, NewErrorStatusCode(fmt.Errorf("unsupported path namespace: %s", p.Namespace()), http.StatusNotImplemented) + return path.ImmutablePath{}, NewErrorStatusCode(fmt.Errorf("unsupported path namespace: %s", p.Namespace()), http.StatusNotImplemented) } } @@ -690,32 +690,32 @@ func (bb *BlocksBackend) resolvePath(ctx context.Context, p path.Path) (path.Imm if p.Namespace() == path.IPNSNamespace { p, err = resolve.ResolveIPNS(ctx, bb.namesys, p) if err != nil { - return nil, nil, err + return path.ImmutablePath{}, nil, err } } if p.Namespace() != path.IPFSNamespace { - return nil, nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace()) + return path.ImmutablePath{}, nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace()) } imPath, err := path.NewImmutablePath(p) if err != nil { - return nil, nil, err + return path.ImmutablePath{}, nil, err } node, remainder, err := bb.resolver.ResolveToLastNode(ctx, imPath) if err != nil { - return nil, nil, err + return path.ImmutablePath{}, nil, err } p, err = path.Join(path.FromCid(node), remainder...) if err != nil { - return nil, nil, err + return path.ImmutablePath{}, nil, err } imPath, err = path.NewImmutablePath(p) if err != nil { - return nil, nil, err + return path.ImmutablePath{}, nil, err } return imPath, remainder, nil diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index 775a4e24b..d3a4ac9b5 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -736,7 +736,7 @@ func (mb *errorMockBackend) GetCAR(ctx context.Context, path path.ImmutablePath, } func (mb *errorMockBackend) ResolveMutable(ctx context.Context, p path.Path) (path.ImmutablePath, error) { - return nil, mb.err + return path.ImmutablePath{}, mb.err } func (mb *errorMockBackend) GetIPNSRecord(ctx context.Context, c cid.Cid) ([]byte, error) { diff --git a/gateway/handler.go b/gateway/handler.go index 6bcd515f9..7e3ccbf48 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -745,14 +745,14 @@ func (i *handler) handleWebRequestErrors(w http.ResponseWriter, r *http.Request, if errors.Is(err, ErrServiceUnavailable) { err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) i.webError(w, r, err, http.StatusServiceUnavailable) - return nil, false + return path.ImmutablePath{}, false } // If the error is not an IPLD traversal error then we should not be looking for _redirects or legacy 404s if !isErrNotFound(err) { err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false + return path.ImmutablePath{}, false } // If we have origin isolation (subdomain gw, DNSLink website), @@ -774,12 +774,12 @@ func (i *handler) handleWebRequestErrors(w http.ResponseWriter, r *http.Request, // follow https://docs.ipfs.tech/how-to/websites-on-ipfs/redirects-and-custom-404s/ instead. if i.serveLegacy404IfPresent(w, r, immutableContentPath, logger) { logger.Debugw("served legacy 404") - return nil, false + return path.ImmutablePath{}, false } err = fmt.Errorf("failed to resolve %s: %w", debugStr(contentPath.String()), err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false + return path.ImmutablePath{}, false } // Detect 'Cache-Control: only-if-cached' in request and return data if it is already in the local datastore. diff --git a/gateway/handler_unixfs__redirects.go b/gateway/handler_unixfs__redirects.go index 6b63a793a..6d1f40c25 100644 --- a/gateway/handler_unixfs__redirects.go +++ b/gateway/handler_unixfs__redirects.go @@ -42,28 +42,28 @@ func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request if err != nil { err = fmt.Errorf("trouble processing _redirects path %q: %w", immutableContentPath.String(), err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } redirectsPath, err := path.Join(rootPath, "_redirects") if err != nil { err = fmt.Errorf("trouble processing _redirects path %q: %w", rootPath.String(), err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } imRedirectsPath, err := path.NewImmutablePath(redirectsPath) if err != nil { err = fmt.Errorf("trouble processing _redirects path %q: %w", redirectsPath, err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } foundRedirect, redirectRules, err := i.getRedirectRules(r, imRedirectsPath) if err != nil { err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsPath, err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } if foundRedirect { @@ -71,11 +71,11 @@ func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request if err != nil { err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsPath, err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } if redirected { - return nil, false, true + return path.ImmutablePath{}, false, true } // 200 is treated as a rewrite, so update the path and continue @@ -85,13 +85,13 @@ func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request if err != nil { err = fmt.Errorf("could not use _redirects file to %q: %w", p, err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } imPath, err := path.NewImmutablePath(p) if err != nil { err = fmt.Errorf("could not use _redirects file to %q: %w", p, err) i.webError(w, r, err, http.StatusInternalServerError) - return nil, false, true + return path.ImmutablePath{}, false, true } return imPath, true, true } diff --git a/gateway/utilities_test.go b/gateway/utilities_test.go index 89f955cbc..bba66d94d 100644 --- a/gateway/utilities_test.go +++ b/gateway/utilities_test.go @@ -186,18 +186,18 @@ func (mb *mockBackend) resolvePathNoRootsReturned(ctx context.Context, ip path.P if ip.Mutable() { imPath, err = mb.ResolveMutable(ctx, ip) if err != nil { - return nil, err + return path.ImmutablePath{}, err } } else { imPath, err = path.NewImmutablePath(ip) if err != nil { - return nil, err + return path.ImmutablePath{}, err } } md, err := mb.ResolvePath(ctx, imPath) if err != nil { - return nil, err + return path.ImmutablePath{}, err } return md.LastSegment, nil } diff --git a/path/path.go b/path/path.go index 5e39eea3a..8b67af4d0 100644 --- a/path/path.go +++ b/path/path.go @@ -73,58 +73,50 @@ func (p path) Segments() []string { } // ImmutablePath is a [Path] which is guaranteed to have an immutable [Namespace]. -type ImmutablePath interface { - Path - - // RootCid returns the [cid.Cid] of the root object of the path. - RootCid() cid.Cid -} - -var _ Path = immutablePath{} -var _ ImmutablePath = immutablePath{} - -type immutablePath struct { +type ImmutablePath struct { path Path rootCid cid.Cid } +var _ Path = ImmutablePath{} + func NewImmutablePath(p Path) (ImmutablePath, error) { if p.Mutable() { - return nil, &ErrInvalidPath{err: ErrExpectedImmutable, path: p.String()} + return ImmutablePath{}, &ErrInvalidPath{err: ErrExpectedImmutable, path: p.String()} } segments := p.Segments() cid, err := cid.Decode(segments[1]) if err != nil { - return nil, &ErrInvalidPath{err: err, path: p.String()} + return ImmutablePath{}, &ErrInvalidPath{err: err, path: p.String()} } - return immutablePath{path: p, rootCid: cid}, nil + return ImmutablePath{path: p, rootCid: cid}, nil } -func (ip immutablePath) String() string { +func (ip ImmutablePath) String() string { return ip.path.String() } -func (ip immutablePath) Namespace() string { +func (ip ImmutablePath) Namespace() string { return ip.path.Namespace() } -func (ip immutablePath) Mutable() bool { +func (ip ImmutablePath) Mutable() bool { return false } -func (ip immutablePath) Segments() []string { +func (ip ImmutablePath) Segments() []string { return ip.path.Segments() } -func (ip immutablePath) RootCid() cid.Cid { +func (ip ImmutablePath) RootCid() cid.Cid { return ip.rootCid } // FromCid returns a new "/ipfs" path with the provided CID. func FromCid(cid cid.Cid) ImmutablePath { - return immutablePath{ + return ImmutablePath{ path: path{ str: fmt.Sprintf("/%s/%s", IPFSNamespace, cid.String()), namespace: IPFSNamespace, @@ -161,7 +153,7 @@ func NewPath(str string) (Path, error) { return nil, &ErrInvalidPath{err: err, path: str} } - return immutablePath{ + return ImmutablePath{ path: path{ str: cleaned, namespace: segments[0], diff --git a/path/path_test.go b/path/path_test.go index 2f944e39e..b432f11a9 100644 --- a/path/path_test.go +++ b/path/path_test.go @@ -9,7 +9,7 @@ import ( ) func newIPLDPath(cid cid.Cid) ImmutablePath { - return immutablePath{ + return ImmutablePath{ path: path{ str: fmt.Sprintf("/%s/%s", IPLDNamespace, cid.String()), namespace: IPLDNamespace, @@ -134,7 +134,7 @@ func TestNewPath(t *testing.T) { for _, testCase := range testCases { p, err := NewPath(testCase.src) assert.NoError(t, err) - assert.IsType(t, immutablePath{}, p) + assert.IsType(t, ImmutablePath{}, p) } }) } @@ -149,7 +149,7 @@ func TestFromCid(t *testing.T) { assert.NoError(t, err) p := FromCid(c) - assert.IsType(t, immutablePath{}, p) + assert.IsType(t, ImmutablePath{}, p) assert.Equal(t, "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n", p.String()) assert.Equal(t, c, p.RootCid()) }) @@ -161,7 +161,7 @@ func TestFromCid(t *testing.T) { assert.NoError(t, err) p := FromCid(c) - assert.IsType(t, immutablePath{}, p) + assert.IsType(t, ImmutablePath{}, p) assert.Equal(t, "/ipfs/bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku", p.String()) assert.Equal(t, c, p.RootCid()) }) @@ -171,7 +171,7 @@ func TestFromCid(t *testing.T) { assert.NoError(t, err) p := newIPLDPath(c) - assert.IsType(t, immutablePath{}, p) + assert.IsType(t, ImmutablePath{}, p) assert.Equal(t, "/ipld/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n", p.String()) assert.Equal(t, c, p.RootCid()) @@ -180,7 +180,7 @@ func TestFromCid(t *testing.T) { assert.NoError(t, err) p = newIPLDPath(c) - assert.IsType(t, immutablePath{}, p) + assert.IsType(t, ImmutablePath{}, p) assert.Equal(t, "/ipld/bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku", p.String()) assert.Equal(t, c, p.RootCid()) })