aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLewis Marshall <lewis@lmars.net>2017-05-13 08:02:25 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-05-13 08:02:25 +0800
commitb0d0fafd68f526ceed98e59a423b6470f2327a21 (patch)
tree48e0f7286e0b2811e6e1bc5f319abea82012dcee
parent90c7155ef41900babc5fd736224127f048e5c883 (diff)
downloaddexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar.gz
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar.bz2
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar.lz
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar.xz
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.tar.zst
dexon-b0d0fafd68f526ceed98e59a423b6470f2327a21.zip
swarm/api: fix error reporting in api.Resolve (#14464)
Previously, resolve errors were being swallowed and the returned error was a generic "not a content hash" which isn't helpful. This updates the Resolve function to fail fast rather than only returning an error at the end, and also adds test coverage.
-rw-r--r--swarm/api/api.go43
-rw-r--r--swarm/api/api_test.go120
-rw-r--r--swarm/api/http/server_test.go6
3 files changed, 148 insertions, 21 deletions
diff --git a/swarm/api/api.go b/swarm/api/api.go
index 26a9445d5..803265a3e 100644
--- a/swarm/api/api.go
+++ b/swarm/api/api.go
@@ -25,12 +25,13 @@ import (
"sync"
"bytes"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/swarm/storage"
"mime"
"path/filepath"
"time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/swarm/storage"
)
var (
@@ -84,27 +85,33 @@ type ErrResolve error
func (self *Api) Resolve(uri *URI) (storage.Key, error) {
log.Trace(fmt.Sprintf("Resolving : %v", uri.Addr))
- var err error
- if !uri.Immutable() {
- if self.dns != nil {
- resolved, err := self.dns.Resolve(uri.Addr)
- if err == nil {
- return resolved[:], nil
- }
- } else {
- err = fmt.Errorf("no DNS to resolve name")
+ // if the URI is immutable, check if the address is a hash
+ isHash := hashMatcher.MatchString(uri.Addr)
+ if uri.Immutable() {
+ if !isHash {
+ return nil, fmt.Errorf("immutable address not a content hash: %q", uri.Addr)
}
+ return common.Hex2Bytes(uri.Addr), nil
}
- if hashMatcher.MatchString(uri.Addr) {
- return storage.Key(common.Hex2Bytes(uri.Addr)), nil
+
+ // if DNS is not configured, check if the address is a hash
+ if self.dns == nil {
+ if !isHash {
+ return nil, fmt.Errorf("no DNS to resolve name: %q", uri.Addr)
+ }
+ return common.Hex2Bytes(uri.Addr), nil
}
- if err != nil {
- return nil, fmt.Errorf("'%s' does not resolve: %v but is not a content hash", uri.Addr, err)
+
+ // try and resolve the address
+ resolved, err := self.dns.Resolve(uri.Addr)
+ if err == nil {
+ return resolved[:], nil
+ } else if !isHash {
+ return nil, err
}
- return nil, fmt.Errorf("'%s' is not a content hash", uri.Addr)
+ return common.Hex2Bytes(uri.Addr), nil
}
-
// Put provides singleton manifest creation on top of dpa store
func (self *Api) Put(content, contentType string) (storage.Key, error) {
r := strings.NewReader(content)
diff --git a/swarm/api/api_test.go b/swarm/api/api_test.go
index c2d78c2dc..f9caed27f 100644
--- a/swarm/api/api_test.go
+++ b/swarm/api/api_test.go
@@ -17,6 +17,7 @@
package api
import (
+ "errors"
"fmt"
"io"
"io/ioutil"
@@ -117,3 +118,122 @@ func TestApiPut(t *testing.T) {
checkResponse(t, resp, exp)
})
}
+
+// testResolver implements the Resolver interface and either returns the given
+// hash if it is set, or returns a "name not found" error
+type testResolver struct {
+ hash *common.Hash
+}
+
+func newTestResolver(addr string) *testResolver {
+ r := &testResolver{}
+ if addr != "" {
+ hash := common.HexToHash(addr)
+ r.hash = &hash
+ }
+ return r
+}
+
+func (t *testResolver) Resolve(addr string) (common.Hash, error) {
+ if t.hash == nil {
+ return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
+ }
+ return *t.hash, nil
+}
+
+// TestAPIResolve tests resolving URIs which can either contain content hashes
+// or ENS names
+func TestAPIResolve(t *testing.T) {
+ ensAddr := "swarm.eth"
+ hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
+ resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
+ doesResolve := newTestResolver(resolvedAddr)
+ doesntResolve := newTestResolver("")
+
+ type test struct {
+ desc string
+ dns Resolver
+ addr string
+ immutable bool
+ result string
+ expectErr error
+ }
+
+ tests := []*test{
+ {
+ desc: "DNS not configured, hash address, returns hash address",
+ dns: nil,
+ addr: hashAddr,
+ result: hashAddr,
+ },
+ {
+ desc: "DNS not configured, ENS address, returns error",
+ dns: nil,
+ addr: ensAddr,
+ expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
+ },
+ {
+ desc: "DNS configured, hash address, hash resolves, returns resolved address",
+ dns: doesResolve,
+ addr: hashAddr,
+ result: resolvedAddr,
+ },
+ {
+ desc: "DNS configured, immutable hash address, hash resolves, returns hash address",
+ dns: doesResolve,
+ addr: hashAddr,
+ immutable: true,
+ result: hashAddr,
+ },
+ {
+ desc: "DNS configured, hash address, hash doesn't resolve, returns hash address",
+ dns: doesntResolve,
+ addr: hashAddr,
+ result: hashAddr,
+ },
+ {
+ desc: "DNS configured, ENS address, name resolves, returns resolved address",
+ dns: doesResolve,
+ addr: ensAddr,
+ result: resolvedAddr,
+ },
+ {
+ desc: "DNS configured, immutable ENS address, name resolves, returns error",
+ dns: doesResolve,
+ addr: ensAddr,
+ immutable: true,
+ expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
+ },
+ {
+ desc: "DNS configured, ENS address, name doesn't resolve, returns error",
+ dns: doesntResolve,
+ addr: ensAddr,
+ expectErr: errors.New(`DNS name not found: "swarm.eth"`),
+ },
+ }
+ for _, x := range tests {
+ t.Run(x.desc, func(t *testing.T) {
+ api := &Api{dns: x.dns}
+ uri := &URI{Addr: x.addr, Scheme: "bzz"}
+ if x.immutable {
+ uri.Scheme = "bzzi"
+ }
+ res, err := api.Resolve(uri)
+ if err == nil {
+ if x.expectErr != nil {
+ t.Fatalf("expected error %q, got result %q", x.expectErr, res)
+ }
+ if res.String() != x.result {
+ t.Fatalf("expected result %q, got %q", x.result, res)
+ }
+ } else {
+ if x.expectErr == nil {
+ t.Fatalf("expected no error, got %q", err)
+ }
+ if err.Error() != x.expectErr.Error() {
+ t.Fatalf("expected error %q, got %q", x.expectErr, err)
+ }
+ }
+ })
+ }
+}
diff --git a/swarm/api/http/server_test.go b/swarm/api/http/server_test.go
index ceb8db75b..0b124a19a 100644
--- a/swarm/api/http/server_test.go
+++ b/swarm/api/http/server_test.go
@@ -106,9 +106,9 @@ func TestBzzrGetPath(t *testing.T) {
}
nonhashresponses := []string{
- "error resolving name: 'name' does not resolve: no DNS to resolve name but is not a content hash\n",
- "error resolving nonhash: 'nonhash' is not a content hash\n",
- "error resolving nonhash: 'nonhash' does not resolve: no DNS to resolve name but is not a content hash\n",
+ "error resolving name: no DNS to resolve name: \"name\"\n",
+ "error resolving nonhash: immutable address not a content hash: \"nonhash\"\n",
+ "error resolving nonhash: no DNS to resolve name: \"nonhash\"\n",
}
for i, url := range nonhashtests {