diff options
Diffstat (limited to 'swarm/api')
-rw-r--r-- | swarm/api/api.go | 10 | ||||
-rw-r--r-- | swarm/api/client/client_test.go | 8 | ||||
-rw-r--r-- | swarm/api/http/server.go | 8 | ||||
-rw-r--r-- | swarm/api/http/server_test.go | 67 | ||||
-rw-r--r-- | swarm/api/manifest.go | 2 |
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 |