Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/ethersphere/bee/v2/pkg/pss"
"github.com/ethersphere/bee/v2/pkg/resolver"
"github.com/ethersphere/bee/v2/pkg/resolver/client/ens"
"github.com/ethersphere/bee/v2/pkg/resolver/multiresolver"
"github.com/ethersphere/bee/v2/pkg/sctx"
"github.com/ethersphere/bee/v2/pkg/settlement"
"github.com/ethersphere/bee/v2/pkg/settlement/swap"
Expand Down Expand Up @@ -109,9 +110,8 @@ const (
)

const (
multiPartFormData = "multipart/form-data"
contentTypeTar = "application/x-tar"
boolHeaderSetValue = "true"
multiPartFormData = "multipart/form-data"
contentTypeTar = "application/x-tar"
)

var (
Expand Down Expand Up @@ -449,6 +449,10 @@ func (s *Service) resolveNameOrAddress(str string) (swarm.Address, error) {
return addr, nil
}

if errors.Is(err, multiresolver.ErrResolverService) || errors.Is(err, resolver.ErrServiceNotAvailable) {
return swarm.ZeroAddress, err
}

return swarm.ZeroAddress, fmt.Errorf("%w: %w", errInvalidNameOrAddress, err)
}

Expand Down Expand Up @@ -651,13 +655,23 @@ func (s *Service) mapStructure(input, output interface{}) func(string, log.Logge
Message: msg,
Code: http.StatusBadRequest,
}
hasServiceUnavailable := false
for _, err := range merr.Errors {
if errors.Is(err, resolver.ErrServiceNotAvailable) {
hasServiceUnavailable = true
resp.Reasons = append(resp.Reasons, jsonhttp.Reason{
Field: "address",
Error: err.Error(),
})
continue
}
var perr *parseError
if errors.As(err, &perr) {
resp.Reasons = append(resp.Reasons, jsonhttp.Reason{
Field: perr.Entry,
Error: perr.Cause.Error(),
})
continue
}
var verr *validationError
if errors.As(err, &verr) {
Expand All @@ -667,7 +681,14 @@ func (s *Service) mapStructure(input, output interface{}) func(string, log.Logge
})
}
}
jsonhttp.BadRequest(w, resp)

if hasServiceUnavailable {
resp.Message = "service unavailable"
resp.Code = http.StatusServiceUnavailable
jsonhttp.ServiceUnavailable(w, resp)
} else {
jsonhttp.BadRequest(w, resp)
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions pkg/resolver/client/ens/ens.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ func wrapDial(endpoint, contractAddr string) (*ethclient.Client, *goens.Registry
}

func wrapResolve(registry *goens.Registry, _ common.Address, name string) (string, error) {
// Ensure the name is registered.
ownerAddress, err := registry.Owner(name)
// it returns error only if the service is not available
if err != nil {
return "", fmt.Errorf("owner: %w: %w", err, resolver.ErrNotFound)
return "", fmt.Errorf("%w: %w", resolver.ErrServiceNotAvailable, err)
}

// If the name is not registered, return an error.
Expand All @@ -181,12 +181,16 @@ func wrapResolve(registry *goens.Registry, _ common.Address, name string) (strin
// Obtain the resolver for this domain name.
ensR, err := registry.Resolver(name)
if err != nil {
return "", fmt.Errorf("resolver: %w: %w", err, resolver.ErrServiceNotAvailable)
return "", fmt.Errorf("%w: %w", resolver.ErrServiceNotAvailable, err)
}

// Try and read out the content hash record.
ch, err := ensR.Contenthash()
if err != nil {
// Check if it's a service error (rate limiting, network issues)
if strings.Contains(err.Error(), "429") || strings.Contains(err.Error(), "rate limit") {
return "", fmt.Errorf("%w: %w", resolver.ErrServiceNotAvailable, err)
}
return "", fmt.Errorf("contenthash: %w: %w", err, resolver.ErrInvalidContentHash)
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/resolver/multiresolver/multiresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/ethersphere/bee/v2/pkg/resolver"
"github.com/ethersphere/bee/v2/pkg/resolver/cidv1"
"github.com/ethersphere/bee/v2/pkg/resolver/client/ens"
"github.com/ethersphere/bee/v2/pkg/swarm"
"github.com/hashicorp/go-multierror"
)

Expand All @@ -35,6 +36,8 @@ var (
ErrResolverChainFailed = errors.New("resolver chain failed")
// ErrCloseFailed denotes that closing the multiresolver failed.
ErrCloseFailed = errors.New("close failed")
// ErrResolverService denotes that no resolver service is configured for the requested name or the resolver service is not available.
ErrResolverService = errors.New("cannot communicate with the resolver or no resolver service configured")
)

type resolverMap map[string][]resolver.Interface
Expand Down Expand Up @@ -160,6 +163,9 @@ func (mr *MultiResolver) Resolve(name string) (addr resolver.Address, err error)
// If no resolver chain is found, switch to the default chain.
if len(chain) == 0 {
chain = mr.resolvers[""]
if len(chain) == 1 && tld != "" { // only the CID resolver is defined
return swarm.ZeroAddress, resolver.ErrServiceNotAvailable
}
}

var errs *multierror.Error
Expand Down
2 changes: 1 addition & 1 deletion pkg/resolver/multiresolver/multiresolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func TestResolve(t *testing.T) {
},
{
// Switch to the default chain:
name: "this.empty",
name: "defaultChainIsCidTriggerItWithoutTld",
wantAdr: addr,
},
{
Expand Down
2 changes: 1 addition & 1 deletion pkg/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var (
// ErrNotFound denotes that given name was not found
ErrNotFound = errors.New("not found")
// ErrServiceNotAvailable denotes that remote ENS service is not available
ErrServiceNotAvailable = errors.New("not available")
ErrServiceNotAvailable = errors.New("ENS service is not available")
// ErrInvalidContentHash denotes that the value of the response contenthash record is not valid.
ErrInvalidContentHash = errors.New("invalid swarm content hash")
)
Expand Down
Loading