mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
swarm/api: Add contenttype contingent resolve manifest -> rsrc
This commit is contained in:
parent
a16d0af41d
commit
11c3b4cae1
4 changed files with 91 additions and 34 deletions
|
|
@ -365,7 +365,7 @@ func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storag
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up mutable resource updates at specific periods and versions
|
// Look up mutable resource updates at specific periods and versions
|
||||||
func (self *Api) DbLookup(key storage.Key, name string, period uint32, version uint32) (storage.Key, []byte, error) {
|
func (self *Api) DbLookup(name string, period uint32, version uint32) (storage.Key, []byte, error) {
|
||||||
var err error
|
var err error
|
||||||
if version != 0 {
|
if version != 0 {
|
||||||
if period == 0 {
|
if period == 0 {
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,8 @@ func (s *Server) HandleDelete(w http.ResponseWriter, r *Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
||||||
if r.ContentLength == 0 {
|
var outdata string
|
||||||
|
if r.uri.Path != "" {
|
||||||
frequency, err := strconv.ParseUint(r.uri.Path, 10, 64)
|
frequency, err := strconv.ParseUint(r.uri.Path, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.BadRequest(w, r, fmt.Sprintf("Cannot parse frequency parameter: %v", err))
|
s.BadRequest(w, r, fmt.Sprintf("Cannot parse frequency parameter: %v", err))
|
||||||
|
|
@ -303,7 +304,33 @@ func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
||||||
s.Error(w, r, fmt.Errorf("Resource creation failed: %v", err))
|
s.Error(w, r, fmt.Errorf("Resource creation failed: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
manifestKey, err := s.api.NewManifest()
|
||||||
|
if err != nil {
|
||||||
|
s.Error(w, r, fmt.Errorf("create manifest err: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newKey, err := s.updateManifest(manifestKey, func(mw *api.ManifestWriter) error {
|
||||||
|
key, err := mw.AddEntry(bytes.NewReader([]byte(r.uri.Addr)), &api.ManifestEntry{
|
||||||
|
Path: r.uri.Addr,
|
||||||
|
ContentType: api.ResourceContentType,
|
||||||
|
Mode: 0644,
|
||||||
|
Size: int64(len(r.uri.Addr)),
|
||||||
|
ModTime: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.logDebug("resource manifest for for %s stored", key.Log())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
s.Error(w, r, fmt.Errorf("update manifest err: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Debug("manifests", "new", newKey, "old", manifestKey)
|
||||||
|
outdata = fmt.Sprintf("%s", newKey)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
data, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
@ -311,12 +338,16 @@ func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
||||||
}
|
}
|
||||||
_, _, _, err = s.api.DbUpdate(r.uri.Addr, data)
|
_, _, _, err = s.api.DbUpdate(r.uri.Addr, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.Header().Add("Status", fmt.Sprintf("%d", http.StatusUnauthorized))
|
||||||
http.ServeContent(w, &r.Request, "", time.Now(), bytes.NewReader([]byte(err.Error())))
|
http.ServeContent(w, &r.Request, "", time.Now(), bytes.NewReader([]byte(err.Error())))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
if outdata != "" {
|
||||||
|
w.Header().Set("Content-type", "text/plain")
|
||||||
|
fmt.Fprintf(w, outdata)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve mutable resource updates:
|
// Retrieve mutable resource updates:
|
||||||
|
|
@ -325,13 +356,10 @@ func (s *Server) HandlePostDb(w http.ResponseWriter, r *Request) {
|
||||||
// bzz-db[-[immutable|-raw]]://<id>/<n>/<m> - get update version m of period n
|
// bzz-db[-[immutable|-raw]]://<id>/<n>/<m> - get update version m of period n
|
||||||
// <id> = ens name or hash
|
// <id> = ens name or hash
|
||||||
func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
|
s.handleGetDb(w, r, r.uri.Addr)
|
||||||
rootKey, err := s.api.Resolve(r.uri)
|
|
||||||
if err != nil {
|
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) handleGetDb(w http.ResponseWriter, r *Request, name string) {
|
||||||
var params []string
|
var params []string
|
||||||
if len(r.uri.Path) > 0 {
|
if len(r.uri.Path) > 0 {
|
||||||
params = strings.Split(r.uri.Path, "/")
|
params = strings.Split(r.uri.Path, "/")
|
||||||
|
|
@ -341,16 +369,18 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
var version uint64
|
var version uint64
|
||||||
var data []byte
|
var data []byte
|
||||||
var dataLength int
|
var dataLength int
|
||||||
|
var err error
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
log.Debug("handlegetdb", "name", name)
|
||||||
switch len(params) {
|
switch len(params) {
|
||||||
case 0:
|
case 0:
|
||||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, 0, 0)
|
updateKey, data, err = s.api.DbLookup(name, 0, 0)
|
||||||
case 2:
|
case 2:
|
||||||
version, err = strconv.ParseUint(params[1], 10, 32)
|
version, err = strconv.ParseUint(params[1], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, uint32(period), uint32(version))
|
updateKey, data, err = s.api.DbLookup(name, uint32(period), uint32(version))
|
||||||
case 1:
|
case 1:
|
||||||
version, err = strconv.ParseUint(params[1], 10, 32)
|
version, err = strconv.ParseUint(params[1], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -360,7 +390,7 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
updateKey, data, err = s.api.DbLookup(rootKey, r.uri.Addr, uint32(period), uint32(version))
|
updateKey, data, err = s.api.DbLookup(name, uint32(period), uint32(version))
|
||||||
default:
|
default:
|
||||||
s.BadRequest(w, r, fmt.Sprintf("Invalid mutable resource request"))
|
s.BadRequest(w, r, fmt.Sprintf("Invalid mutable resource request"))
|
||||||
return
|
return
|
||||||
|
|
@ -373,9 +403,9 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
} else {
|
} else {
|
||||||
entry := api.ManifestEntry{
|
entry := api.ManifestEntry{
|
||||||
Hash: rootKey.Hex(),
|
Hash: name,
|
||||||
Path: updateKey.Hex(),
|
Path: updateKey.Hex(),
|
||||||
ContentType: api.DbManifestType,
|
ContentType: api.ManifestType,
|
||||||
Size: int64(dataLength),
|
Size: int64(dataLength),
|
||||||
ModTime: now,
|
ModTime: now,
|
||||||
Status: http.StatusOK,
|
Status: http.StatusOK,
|
||||||
|
|
@ -395,7 +425,7 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
s.Error(w, r, fmt.Errorf("Could not convert manifest to json: %v", err))
|
s.Error(w, r, fmt.Errorf("Could not convert manifest to json: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", api.DbManifestType)
|
w.Header().Set("Content-Type", api.ManifestType)
|
||||||
data = []byte(manifestJson)
|
data = []byte(manifestJson)
|
||||||
}
|
}
|
||||||
http.ServeContent(w, &r.Request, "", now, bytes.NewReader(data))
|
http.ServeContent(w, &r.Request, "", now, bytes.NewReader(data))
|
||||||
|
|
@ -461,6 +491,17 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case r.uri.Raw():
|
case r.uri.Raw():
|
||||||
|
m := &api.Manifest{}
|
||||||
|
sz, _ := reader.Size(nil)
|
||||||
|
b := make([]byte, sz)
|
||||||
|
reader.Read(b)
|
||||||
|
err = json.Unmarshal(b, m)
|
||||||
|
if len(m.Entries) > 0 {
|
||||||
|
if m.Entries[0].ContentType == api.ResourceContentType {
|
||||||
|
s.handleGetDb(w, r, m.Entries[0].Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
// allow the request to overwrite the content type using a query
|
// allow the request to overwrite the content type using a query
|
||||||
// parameter
|
// parameter
|
||||||
contentType := "application/octet-stream"
|
contentType := "application/octet-stream"
|
||||||
|
|
@ -468,7 +509,6 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
|
||||||
contentType = typ
|
contentType = typ
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
|
|
||||||
http.ServeContent(w, &r.Request, "", time.Now(), reader)
|
http.ServeContent(w, &r.Request, "", time.Now(), reader)
|
||||||
case r.uri.Hash():
|
case r.uri.Hash():
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
|
|
|
||||||
|
|
@ -45,21 +45,27 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
keybytes := make([]byte, common.HashLength) // nearest we get to source of info
|
keybytes := make([]byte, common.HashLength) // nearest we get to source of info
|
||||||
_, err := rand.Read(keybytes)
|
copy(keybytes, []byte{42})
|
||||||
|
|
||||||
|
databytes := make([]byte, 42)
|
||||||
|
_, err := rand.Read(databytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/bzz-db:/%s/42", srv.URL, fmt.Sprintf("%x", keybytes))
|
url := fmt.Sprintf("%s/bzz-db:/%x/42", srv.URL, keybytes)
|
||||||
resp, err := http.Post(url, "application/octet-stream", nil)
|
resp, err := http.Post(url, "application/octet-stream", bytes.NewReader(databytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b, err := ioutil.ReadAll(resp.Body)
|
manifesthash, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Debug("Create", "status", resp.Status, "body", b)
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Fatalf("err %s", resp.Status)
|
||||||
|
}
|
||||||
|
log.Debug("Create", "status", resp.Status, "body", manifesthash)
|
||||||
|
|
||||||
url = fmt.Sprintf("%s/bzz-db:/%x", srv.URL, keybytes)
|
url = fmt.Sprintf("%s/bzz-db:/%x", srv.URL, keybytes)
|
||||||
data := []byte("foo")
|
data := []byte("foo")
|
||||||
|
|
@ -67,13 +73,13 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b, err = ioutil.ReadAll(resp.Body)
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Debug("Update", "status", resp.Status, "body", b)
|
log.Debug("Update", "status", resp.Status)
|
||||||
|
|
||||||
url = fmt.Sprintf("%s/bzz-db-raw:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
url = fmt.Sprintf("%s/bzz-raw:/%s", srv.URL, manifesthash)
|
||||||
resp, err = http.Get(url)
|
resp, err = http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -82,9 +88,9 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Debug("Get raw", "status", resp.Status, "body", b)
|
log.Debug("Manifest", "status", resp.Status, "body", fmt.Sprintf("%s", b))
|
||||||
|
|
||||||
url = fmt.Sprintf("%s/bzz-db:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
url = fmt.Sprintf("%s/bzz-db-raw:/%x", srv.URL, keybytes)
|
||||||
resp, err = http.Get(url)
|
resp, err = http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -93,7 +99,18 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Debug("Get manifest", "status", resp.Status, "body", b)
|
log.Debug("Get raw", "status", resp.Status)
|
||||||
|
|
||||||
|
url = fmt.Sprintf("%s/bzz-db:/%x", srv.URL, keybytes)
|
||||||
|
resp, err = http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Debug("Get manifest", "status", resp.Status)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ManifestType = "application/bzz-manifest+json"
|
ManifestType = "application/bzz-manifest+json"
|
||||||
DbManifestType = "application/bzz-db-manifest+json"
|
ResourceContentType = "application/bzz-resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manifest represents a swarm manifest
|
// Manifest represents a swarm manifest
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue