diff --git a/bzz/api.go b/bzz/api.go index 4646aafe89..d9fd7a6d7a 100644 --- a/bzz/api.go +++ b/bzz/api.go @@ -124,7 +124,7 @@ func (self *Api) Put(content, contentType string) (string, error) { func (self *Api) Modify(rootHash, path, contentHash, contentType string) (newRootHash string, err error) { root := common.Hex2Bytes(rootHash) - trie, err := loadManifestTrie(self.dpa, root) + trie, err := loadManifest(self.dpa, root) if err != nil { return } @@ -313,9 +313,9 @@ func (self *Api) getPath(uri string) (reader SectionReader, mimeType string, sta return } - trie, err := loadManifestTrie(self.dpa, key) + trie, err := loadManifest(self.dpa, key) if err != nil { - dpaLogger.Debugf("Swarm: loadManifestTrie error: %v", err) + dpaLogger.Debugf("Swarm: loadManifest error: %v", err) return } diff --git a/bzz/httpaccess.go b/bzz/httpaccess.go index 8707baee27..b8f49f9865 100644 --- a/bzz/httpaccess.go +++ b/bzz/httpaccess.go @@ -7,6 +7,7 @@ import ( "bytes" "io" "net/http" + "net/url" "regexp" "sync" "time" @@ -21,7 +22,8 @@ const ( var ( rawUrl = regexp.MustCompile("^/+raw/*") trailingSlashes = regexp.MustCompile("/+$") - forever = time.Unix(0, 0) + // forever = time.Unix(0, 0) + forever = time.Now() ) type sequentialReader struct { @@ -43,6 +45,14 @@ func startHttpServer(api *Api, port string) { func handler(w http.ResponseWriter, r *http.Request, api *Api) { requestURL := r.URL + if requestURL.Host == "" { + var err error + requestURL, err = url.Parse(r.Referer() + requestURL.String()) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + } dpaLogger.Debugf("Swarm: HTTP request URL: '%s', Host: '%s', Path: '%s', Referer: '%s', Accept: '%s'", r.RequestURI, requestURL.Host, requestURL.Path, r.Referer(), r.Header.Get("Accept")) uri := requestURL.Path var raw bool diff --git a/bzz/manifest_trie.go b/bzz/manifest.go similarity index 94% rename from bzz/manifest_trie.go rename to bzz/manifest.go index 1cff3cad40..015716201e 100644 --- a/bzz/manifest_trie.go +++ b/bzz/manifest.go @@ -32,11 +32,16 @@ type manifestTrieEntry struct { subtrie *manifestTrie } -func loadManifestTrie(dpa *DPA, hash Key) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand +func loadManifest(dpa *DPA, hash Key) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand dpaLogger.Debugf("Swarm: manifest lookup key: '%064x'.", hash) // retrieve manifest via DPA manifestReader := dpa.Retrieve(hash) + return readManifest(manifestReader, hash, dpa) +} + +func readManifest(manifestReader SectionReader, hash Key, dpa *DPA) (trie *manifestTrie, err error) { // non-recursive, subtrees are downloaded on-demand + // TODO check size for oversized manifests manifestData := make([]byte, manifestReader.Size()) var size int @@ -198,7 +203,7 @@ func (self *manifestTrie) recalcAndStore() error { func (self *manifestTrie) loadSubTrie(entry *manifestTrieEntry) (err error) { if entry.subtrie == nil { hash := common.Hex2Bytes(entry.Hash) - entry.subtrie, err = loadManifestTrie(self.dpa, hash) + entry.subtrie, err = loadManifest(self.dpa, hash) entry.Hash = "" // might not match, should be recalculated } return diff --git a/bzz/manifest_test.go b/bzz/manifest_test.go new file mode 100644 index 0000000000..07ed8bc2fa --- /dev/null +++ b/bzz/manifest_test.go @@ -0,0 +1,67 @@ +package bzz + +import ( + // "encoding/json" + "fmt" + "io" + "strings" + "testing" +) + +func manifest(paths ...string) (manifestReader SectionReader) { + var entries []string + for _, path := range paths { + entry := fmt.Sprintf(`{"path":"%s"}`, path) + entries = append(entries, entry) + } + manifest := fmt.Sprintf(`{"entries":[%s]}`, strings.Join(entries, ",")) + return io.NewSectionReader(strings.NewReader(manifest), 0, int64(len(manifest))) +} + +func testGetEntry(t *testing.T, path, match string, paths ...string) *manifestTrie { + trie, err := readManifest(manifest(paths...), nil, nil) + if err != nil { + t.Errorf("unexpected error making manifest: %v", err) + } + checkEntry(t, path, match, trie) + return trie +} + +func checkEntry(t *testing.T, path, match string, trie *manifestTrie) { + entry, _ := trie.getEntry(path) + if match == "-" && entry != nil { + t.Errorf("expected no match for '%s', got '%s'", path, entry.Path) + } else if entry == nil { + t.Errorf("expected entry '%s' to match '%s', got no match", match, path) + } else if entry.Path != match { + t.Errorf("incorrect entry retrieved for '%s'. expected path '%v', got '%s'", path, match, entry.Path) + } +} + +func TestGetEntry(t *testing.T) { + testGetEntry(t, "a", "a", "a") + testGetEntry(t, "b", "-", "a") + testGetEntry(t, "/a", "/a", "/a") + testGetEntry(t, "/a", "///a", "///a") + testGetEntry(t, "/a", "a", "a") + // fallback + testGetEntry(t, "/a", "/", "/") + testGetEntry(t, "a", "/", "/") + testGetEntry(t, "/a", "", "") + // longest/deepest math + testGetEntry(t, "a/b", "a/b", "a///", "a/b") + // trailing slash + testGetEntry(t, "", "", "/", "") + testGetEntry(t, "/", "/", "/", "") + testGetEntry(t, "a", "a", "a", "a/") + testGetEntry(t, "a/", "a/", "a/", "a") + // prefix match + testGetEntry(t, "a", "a", "a", "ab") + testGetEntry(t, "ab", "", "a", "") + testGetEntry(t, "a", "a", "a", "ab") + testGetEntry(t, "a/b", "a", "a", "ab") +} + +func TestDeleteEntry(t *testing.T) { + +}