Skip to content

Commit

Permalink
path: replace ImmutablePath interface with struct
Browse files Browse the repository at this point in the history
Let's not repeat ipfs/go-block-format#45 interface for struct with one implementation and no value added.
  • Loading branch information
Jorropo authored and hacdias committed Oct 9, 2023
1 parent 85c180e commit 45c797e
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 55 deletions.
2 changes: 1 addition & 1 deletion coreiface/tests/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
22 changes: 11 additions & 11 deletions gateway/blocks_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 4 additions & 4 deletions gateway/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions gateway/handler_unixfs__redirects.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,40 +42,40 @@ 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 {
redirected, newPath, err := i.handleRedirectsFileRules(w, r, immutableContentPath, contentPath, redirectRules, logger)
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
Expand All @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions gateway/utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
34 changes: 13 additions & 21 deletions path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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],
Expand Down
12 changes: 6 additions & 6 deletions path/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}
})
}
Expand All @@ -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())
})
Expand All @@ -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())
})
Expand All @@ -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())

Expand All @@ -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())
})
Expand Down

0 comments on commit 45c797e

Please sign in to comment.