aboutsummaryrefslogtreecommitdiffstats
path: root/swarm/api
diff options
context:
space:
mode:
Diffstat (limited to 'swarm/api')
-rw-r--r--swarm/api/api.go10
-rw-r--r--swarm/api/client/client_test.go8
-rw-r--r--swarm/api/http/server.go8
-rw-r--r--swarm/api/http/server_test.go67
-rw-r--r--swarm/api/manifest.go2
5 files changed, 81 insertions, 14 deletions
diff --git a/swarm/api/api.go b/swarm/api/api.go
index 803265a3e..7d185ab3c 100644
--- a/swarm/api/api.go
+++ b/swarm/api/api.go
@@ -34,11 +34,7 @@ import (
"github.com/ethereum/go-ethereum/swarm/storage"
)
-var (
- hashMatcher = regexp.MustCompile("^[0-9A-Fa-f]{64}")
- slashes = regexp.MustCompile("/+")
- domainAndVersion = regexp.MustCompile("[@:;,]+")
-)
+var hashMatcher = regexp.MustCompile("^[0-9A-Fa-f]{64}")
type Resolver interface {
Resolve(string) (common.Hash, error)
@@ -335,7 +331,6 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte
}
func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storage.Key, manifestEntryMap map[string]*manifestTrieEntry, err error) {
-
uri, err := Parse("bzz:/" + mhash)
if err != nil {
return nil, nil, err
@@ -356,5 +351,8 @@ func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storag
manifestEntryMap[suffix] = entry
})
+ if err != nil {
+ return nil, nil, fmt.Errorf("list with prefix failed %v: %v", key.String(), err)
+ }
return key, manifestEntryMap, nil
}
diff --git a/swarm/api/client/client_test.go b/swarm/api/client/client_test.go
index 03d25049d..edf385dd0 100644
--- a/swarm/api/client/client_test.go
+++ b/swarm/api/client/client_test.go
@@ -89,8 +89,8 @@ func TestClientUploadDownloadFiles(t *testing.T) {
if file.Size != int64(len(expected)) {
t.Fatalf("expected downloaded file to be %d bytes, got %d", len(expected), file.Size)
}
- if file.ContentType != file.ContentType {
- t.Fatalf("expected downloaded file to have type %q, got %q", file.ContentType, file.ContentType)
+ if file.ContentType != "text/plain" {
+ t.Fatalf("expected downloaded file to have type %q, got %q", "text/plain", file.ContentType)
}
data, err := ioutil.ReadAll(file)
if err != nil {
@@ -235,9 +235,7 @@ func TestClientFileList(t *testing.T) {
t.Fatal(err)
}
paths := make([]string, 0, len(list.CommonPrefixes)+len(list.Entries))
- for _, prefix := range list.CommonPrefixes {
- paths = append(paths, prefix)
- }
+ paths = append(paths, list.CommonPrefixes...)
for _, entry := range list.Entries {
paths = append(paths, entry.Path)
}
diff --git a/swarm/api/http/server.go b/swarm/api/http/server.go
index 5f64f971b..0b4ec7e18 100644
--- a/swarm/api/http/server.go
+++ b/swarm/api/http/server.go
@@ -224,7 +224,7 @@ func (s *Server) handleMultipartUpload(req *Request, boundary string, mw *api.Ma
if err != nil {
return fmt.Errorf("error copying multipart content: %s", err)
}
- if _, err := tmp.Seek(0, os.SEEK_SET); err != nil {
+ if _, err := tmp.Seek(0, io.SeekStart); err != nil {
return fmt.Errorf("error copying multipart content: %s", err)
}
reader = tmp
@@ -522,6 +522,12 @@ func (s *Server) HandleGetList(w http.ResponseWriter, r *Request) {
// HandleGetFile handles a GET request to bzz://<manifest>/<path> and responds
// with the content of the file at <path> from the given <manifest>
func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
+ // ensure the root path has a trailing slash so that relative URLs work
+ if r.uri.Path == "" && !strings.HasSuffix(r.URL.Path, "/") {
+ http.Redirect(w, &r.Request, r.URL.Path+"/", http.StatusMovedPermanently)
+ return
+ }
+
key, err := s.api.Resolve(r.uri)
if err != nil {
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
diff --git a/swarm/api/http/server_test.go b/swarm/api/http/server_test.go
index 0b124a19a..d3374594b 100644
--- a/swarm/api/http/server_test.go
+++ b/swarm/api/http/server_test.go
@@ -18,12 +18,16 @@ package http_test
import (
"bytes"
+ "errors"
+ "fmt"
"io/ioutil"
"net/http"
"sync"
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/swarm/api"
+ swarm "github.com/ethereum/go-ethereum/swarm/api/client"
"github.com/ethereum/go-ethereum/swarm/storage"
"github.com/ethereum/go-ethereum/swarm/testutil"
)
@@ -93,7 +97,7 @@ func TestBzzrGetPath(t *testing.T) {
isexpectedfailrequest = true
}
}
- if isexpectedfailrequest == false {
+ if !isexpectedfailrequest {
t.Fatalf("Response body does not match, expected: %v, got %v", testmanifest[v], string(respbody))
}
}
@@ -122,9 +126,70 @@ func TestBzzrGetPath(t *testing.T) {
}
defer resp.Body.Close()
respbody, err = ioutil.ReadAll(resp.Body)
+ if err != nil {
+ t.Fatalf("ReadAll failed: %v", err)
+ }
if string(respbody) != nonhashresponses[i] {
t.Fatalf("Non-Hash response body does not match, expected: %v, got: %v", nonhashresponses[i], string(respbody))
}
}
}
+
+// TestBzzRootRedirect tests that getting the root path of a manifest without
+// a trailing slash gets redirected to include the trailing slash so that
+// relative URLs work as expected.
+func TestBzzRootRedirect(t *testing.T) {
+ srv := testutil.NewTestSwarmServer(t)
+ defer srv.Close()
+
+ // create a manifest with some data at the root path
+ client := swarm.NewClient(srv.URL)
+ data := []byte("data")
+ file := &swarm.File{
+ ReadCloser: ioutil.NopCloser(bytes.NewReader(data)),
+ ManifestEntry: api.ManifestEntry{
+ Path: "",
+ ContentType: "text/plain",
+ Size: int64(len(data)),
+ },
+ }
+ hash, err := client.Upload(file, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // define a CheckRedirect hook which ensures there is only a single
+ // redirect to the correct URL
+ redirected := false
+ httpClient := http.Client{
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
+ if redirected {
+ return errors.New("too many redirects")
+ }
+ redirected = true
+ expectedPath := "/bzz:/" + hash + "/"
+ if req.URL.Path != expectedPath {
+ return fmt.Errorf("expected redirect to %q, got %q", expectedPath, req.URL.Path)
+ }
+ return nil
+ },
+ }
+
+ // perform the GET request and assert the response
+ res, err := httpClient.Get(srv.URL + "/bzz:/" + hash)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if !redirected {
+ t.Fatal("expected GET /bzz:/<hash> to redirect to /bzz:/<hash>/ but it didn't")
+ }
+ gotData, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(gotData, data) {
+ t.Fatalf("expected response to equal %q, got %q", data, gotData)
+ }
+}
diff --git a/swarm/api/manifest.go b/swarm/api/manifest.go
index e251620a7..90f287677 100644
--- a/swarm/api/manifest.go
+++ b/swarm/api/manifest.go
@@ -63,7 +63,7 @@ func (a *Api) NewManifest() (storage.Key, error) {
if err != nil {
return nil, err
}
- return a.Store(bytes.NewReader(data), int64(len(data)), nil)
+ return a.Store(bytes.NewReader(data), int64(len(data)), &sync.WaitGroup{})
}
// ManifestWriter is used to add and remove entries from an underlying manifest