mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 20:56:42 +00:00
Interpreting manifest files (no recursion).
This commit is contained in:
parent
ce53889384
commit
fc8358a261
1 changed files with 52 additions and 1 deletions
|
|
@ -4,6 +4,7 @@ A simple http server interface to Swarm
|
||||||
package bzz
|
package bzz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -17,7 +18,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
uriMatcher = regexp.MustCompile("^/raw/[0-9A-Fa-f]{64}$")
|
uriMatcher = regexp.MustCompile("^/raw/[0-9A-Fa-f]{64}$")
|
||||||
|
manifestMatcher = regexp.MustCompile("^/[0-9A-Fa-f]{64}")
|
||||||
|
hashMatcher = regexp.MustCompile("^[0-9A-Fa-f]{64}$")
|
||||||
)
|
)
|
||||||
|
|
||||||
type sequentialReader struct {
|
type sequentialReader struct {
|
||||||
|
|
@ -26,6 +29,13 @@ type sequentialReader struct {
|
||||||
ahead map[int64](chan bool)
|
ahead map[int64](chan bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type manifestEntry struct {
|
||||||
|
Path string
|
||||||
|
Hash string
|
||||||
|
Content_type string
|
||||||
|
Status int16
|
||||||
|
}
|
||||||
|
|
||||||
func (self *sequentialReader) ReadAt(target []byte, off int64) (n int, err error) {
|
func (self *sequentialReader) ReadAt(target []byte, off int64) (n int, err error) {
|
||||||
if self.pos != off {
|
if self.pos != off {
|
||||||
dpaLogger.Debugf("Swarm: deferred read in POST at position %d, offset %d.",
|
dpaLogger.Debugf("Swarm: deferred read in POST at position %d, offset %d.",
|
||||||
|
|
@ -83,6 +93,47 @@ func handler(w http.ResponseWriter, r *http.Request, dpa *DPA) {
|
||||||
name := uri[5:]
|
name := uri[5:]
|
||||||
key := ethutil.Hex2Bytes(name)
|
key := ethutil.Hex2Bytes(name)
|
||||||
http.ServeContent(w, r, name+".bin", time.Unix(0, 0), dpa.Retrieve(key))
|
http.ServeContent(w, r, name+".bin", time.Unix(0, 0), dpa.Retrieve(key))
|
||||||
|
} else if manifestMatcher.MatchString(uri) {
|
||||||
|
name := uri[1:65]
|
||||||
|
path := uri[65:]
|
||||||
|
key := ethutil.Hex2Bytes(name)
|
||||||
|
manifestReader := dpa.Retrieve(key)
|
||||||
|
// TODO check size for oversized manifests
|
||||||
|
manifest := make([]byte, manifestReader.Size())
|
||||||
|
manifestReader.Read(manifest)
|
||||||
|
manifestEntries := make([]manifestEntry, 0)
|
||||||
|
json.Unmarshal(manifest, &manifestEntries)
|
||||||
|
var hash []byte
|
||||||
|
var mimeType string
|
||||||
|
prefix := 0
|
||||||
|
status := int16(404)
|
||||||
|
for i, entry := range manifestEntries {
|
||||||
|
if !hashMatcher.MatchString(entry.Hash) {
|
||||||
|
// hash is mandatory
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if entry.Content_type == "" {
|
||||||
|
// content type defaults to manifest
|
||||||
|
entry.Content_type = "application/bzz-manifest+json"
|
||||||
|
}
|
||||||
|
if entry.Status == 0 {
|
||||||
|
// status defaults to 200
|
||||||
|
entry.Status = 200
|
||||||
|
}
|
||||||
|
pathLen := len(entry.Path)
|
||||||
|
if len(path) >= pathLen && path[:pathLen] == entry.Path && prefix < pathLen {
|
||||||
|
prefix = pathLen
|
||||||
|
hash = ethutil.Hex2Bytes(entry.Hash)
|
||||||
|
mimeType = entry.Content_type
|
||||||
|
status = entry.Status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hash == nil {
|
||||||
|
http.Error(w, "Object "+uri+" not found.", http.StatusNotFound)
|
||||||
|
} else {
|
||||||
|
w.Header().Set("Content-Type", mimeType)
|
||||||
|
http.ServeContent(w, r, "", time.Unix(0, 0), dpa.Retrieve(hash))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
http.Error(w, "Object "+uri+" not found.", http.StatusNotFound)
|
http.Error(w, "Object "+uri+" not found.", http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue