mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
swarm/api: Add raw form to api+server WIP
This commit is contained in:
parent
81ec1f9694
commit
1bf4f4a37f
6 changed files with 105 additions and 50 deletions
|
|
@ -46,9 +46,9 @@ on top of the dpa
|
||||||
it is the public interface of the dpa which is included in the ethereum stack
|
it is the public interface of the dpa which is included in the ethereum stack
|
||||||
*/
|
*/
|
||||||
type Api struct {
|
type Api struct {
|
||||||
|
resource *storage.ResourceHandler
|
||||||
dpa *storage.DPA
|
dpa *storage.DPA
|
||||||
dns Resolver
|
dns Resolver
|
||||||
resource *storage.ResourceHandler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//the api constructor initialises
|
//the api constructor initialises
|
||||||
|
|
@ -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(name string, period uint32, version uint32) (io.ReadSeeker, error) {
|
func (self *Api) DbLookup(key storage.Key, name string, period uint32, version uint32) (io.ReadSeeker, error) {
|
||||||
var err error
|
var err error
|
||||||
if version != 0 {
|
if version != 0 {
|
||||||
if period == 0 {
|
if period == 0 {
|
||||||
|
|
@ -375,16 +375,20 @@ func (self *Api) DbLookup(name string, period uint32, version uint32) (io.ReadSe
|
||||||
}
|
}
|
||||||
period = self.resource.BlockToPeriod(name, currentblocknumber)
|
period = self.resource.BlockToPeriod(name, currentblocknumber)
|
||||||
}
|
}
|
||||||
_, err = self.resource.LookupVersion(name, period, version, true)
|
_, err = self.resource.LookupVersionByName(name, period, version, true)
|
||||||
} else if period != 0 {
|
} else if period != 0 {
|
||||||
_, err = self.resource.LookupHistorical(name, period, true)
|
_, err = self.resource.LookupHistoricalByName(name, period, true)
|
||||||
} else {
|
} else {
|
||||||
_, err = self.resource.LookupLatest(name, true)
|
_, err = self.resource.LookupLatestByName(name, true)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return bytes.NewReader(self.resource.GetData(name)), nil
|
data, err := self.resource.GetData(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bytes.NewReader(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Api) DbCreate(name string, frequency uint64) (err error) {
|
func (self *Api) DbCreate(name string, frequency uint64) (err error) {
|
||||||
|
|
@ -394,5 +398,11 @@ func (self *Api) DbCreate(name string, frequency uint64) (err error) {
|
||||||
|
|
||||||
func (self *Api) DbUpdate(name string, data []byte) (storage.Key, uint32, uint32, error) {
|
func (self *Api) DbUpdate(name string, data []byte) (storage.Key, uint32, uint32, error) {
|
||||||
key, err := self.resource.Update(name, data)
|
key, err := self.resource.Update(name, data)
|
||||||
return key, self.resource.GetLastPeriod(name), self.resource.GetVersion(name), err
|
period, _ := self.resource.GetLastPeriod(name)
|
||||||
|
version, _ := self.resource.GetVersion(name)
|
||||||
|
return key, period, version, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Api) DbHashSize() int {
|
||||||
|
return self.resource.HashSize()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,36 +332,42 @@ func (s *Server) HandleGetDb(w http.ResponseWriter, r *Request) {
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = key
|
|
||||||
|
|
||||||
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, "/")
|
||||||
}
|
}
|
||||||
|
var period uint64
|
||||||
|
var version uint64
|
||||||
|
var data io.ReadSeeker
|
||||||
switch len(params) {
|
switch len(params) {
|
||||||
case 0:
|
case 0:
|
||||||
data, err := s.api.DbLookup(r.uri.Addr)
|
data, err = s.api.DbLookup(key, r.uri.Addr, 0, 0)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
strconv.ParseUint(params[1], 10, 32)
|
version, err = strconv.ParseUint(params[1], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
strconv.ParseUint(params[0], 10, 32)
|
period, err = strconv.ParseUint(params[0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data, err = s.api.DbLookup(key, r.uri.Addr, uint32(period), uint32(version))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
err = "params 0-2"
|
err = fmt.Errorf("params 0-2")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wrappedData := wrapDbContent(data, s.uri.Scheme)
|
if !r.uri.DbRaw() {
|
||||||
|
|
||||||
|
}
|
||||||
http.ServeContent(w, &r.Request, "", time.Now(), data)
|
http.ServeContent(w, &r.Request, "", time.Now(), data)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrapDbContent(data io.Reader, scheme *string) io.Reader {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleGet handles a GET request to
|
// HandleGet handles a GET request to
|
||||||
|
|
@ -705,6 +711,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
s.HandleDelete(w, req)
|
s.HandleDelete(w, req)
|
||||||
|
|
||||||
case "GET":
|
case "GET":
|
||||||
|
|
||||||
|
if uri.Db() || uri.DbRaw() {
|
||||||
|
s.HandleGetDb(w, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if uri.Raw() || uri.Hash() || uri.DeprecatedRaw() {
|
if uri.Raw() || uri.Hash() || uri.DeprecatedRaw() {
|
||||||
s.HandleGet(w, req)
|
s.HandleGet(w, req)
|
||||||
return
|
return
|
||||||
|
|
@ -720,11 +732,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if uri.Db() {
|
|
||||||
s.HandleGetDb(w, req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.HandleGetFile(w, req)
|
s.HandleGetFile(w, req)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package http_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -43,7 +44,14 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
srv := testutil.NewTestSwarmServer(t)
|
srv := testutil.NewTestSwarmServer(t)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
url := srv.URL + "/bzz-db:/foo/42"
|
keybytes := make([]byte, common.HashLength) // nearest we get to source of info
|
||||||
|
_, err := rand.Read(keybytes)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("%s/bzz-db:/%s/42", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||||
resp, err := http.Post(url, "application/octet-stream", nil)
|
resp, err := http.Post(url, "application/octet-stream", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("err: %v\n", err)
|
fmt.Printf("err: %v\n", err)
|
||||||
|
|
@ -52,7 +60,7 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
b, err := ioutil.ReadAll(resp.Body)
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
fmt.Printf("Create: %s : %s\n", resp.Status, b)
|
fmt.Printf("Create: %s : %s\n", resp.Status, b)
|
||||||
|
|
||||||
url = srv.URL + "/bzz-db:/foo"
|
url = fmt.Sprintf("%s/bzz-db:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||||
data := []byte("foo")
|
data := []byte("foo")
|
||||||
resp, err = http.Post(url, "application/octet-stream", bytes.NewReader(data))
|
resp, err = http.Post(url, "application/octet-stream", bytes.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -62,7 +70,7 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
b, err = ioutil.ReadAll(resp.Body)
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
fmt.Printf("Update: %s : %s\n", resp.Status, b)
|
fmt.Printf("Update: %s : %s\n", resp.Status, b)
|
||||||
|
|
||||||
url = srv.URL + "/bzz-db:/foo"
|
url = fmt.Sprintf("%s/bzz-db-raw:/%s", srv.URL, fmt.Sprintf("%x", keybytes))
|
||||||
resp, err = http.Get(url)
|
resp, err = http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("err: %v\n", err)
|
fmt.Printf("err: %v\n", err)
|
||||||
|
|
@ -70,7 +78,6 @@ func TestBzzGetDb(t *testing.T) {
|
||||||
}
|
}
|
||||||
b, err = ioutil.ReadAll(resp.Body)
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
fmt.Printf("Get: %s : %s\n", resp.Status, b)
|
fmt.Printf("Get: %s : %s\n", resp.Status, b)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBzzGetPath(t *testing.T) {
|
func TestBzzGetPath(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ func (self *resource) isSynced() bool {
|
||||||
// Implement to activate validation of resource updates
|
// Implement to activate validation of resource updates
|
||||||
// Specifically signing data and verification of signatures
|
// Specifically signing data and verification of signatures
|
||||||
type ResourceValidator interface {
|
type ResourceValidator interface {
|
||||||
|
hashSize() int
|
||||||
checkAccess(string, common.Address) (bool, error)
|
checkAccess(string, common.Address) (bool, error)
|
||||||
nameHash(string) common.Hash // nameHashFunc
|
nameHash(string) common.Hash // nameHashFunc
|
||||||
sign(common.Hash) (Signature, error) // SignFunc
|
sign(common.Hash) (Signature, error) // SignFunc
|
||||||
|
|
@ -166,28 +167,34 @@ func NewResourceHandler(datadir string, cloudStore CloudStore, rpcClient *rpc.Cl
|
||||||
return rh, nil
|
return rh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ResourceHandler) GetData(name string) []byte {
|
func (self *ResourceHandler) HashSize() int {
|
||||||
rsrc := self.getResource(name)
|
return self.validator.hashSize()
|
||||||
if rsrc == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return rsrc.data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ResourceHandler) GetLastPeriod(name string) uint32 {
|
// get data from current resource
|
||||||
|
func (self *ResourceHandler) GetData(name string) ([]byte, error) {
|
||||||
rsrc := self.getResource(name)
|
rsrc := self.getResource(name)
|
||||||
if rsrc == nil {
|
if rsrc == nil || !rsrc.isSynced() {
|
||||||
return 0
|
return nil, fmt.Errorf("Resource does not exist or is not synced")
|
||||||
}
|
}
|
||||||
return rsrc.lastPeriod
|
return rsrc.data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ResourceHandler) GetVersion(name string) uint32 {
|
func (self *ResourceHandler) GetLastPeriod(name string) (uint32, error) {
|
||||||
rsrc := self.getResource(name)
|
rsrc := self.getResource(name)
|
||||||
if rsrc == nil {
|
|
||||||
return 0
|
if rsrc == nil || !rsrc.isSynced() {
|
||||||
|
return 0, fmt.Errorf("Resource does not exist or is not synced")
|
||||||
}
|
}
|
||||||
return rsrc.version
|
return rsrc.lastPeriod, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ResourceHandler) GetVersion(name string) (uint32, error) {
|
||||||
|
rsrc := self.getResource(name)
|
||||||
|
if rsrc == nil || !rsrc.isSynced() {
|
||||||
|
return 0, fmt.Errorf("Resource does not exist or is not synced")
|
||||||
|
}
|
||||||
|
return rsrc.version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// \TODO should be hashsize * branches from the chosen chunker, implement with dpa
|
// \TODO should be hashsize * branches from the chosen chunker, implement with dpa
|
||||||
|
|
@ -269,8 +276,14 @@ func (self *ResourceHandler) NewResource(name string, frequency uint64) (*resour
|
||||||
// root chunk.
|
// root chunk.
|
||||||
// It is the callers responsibility to make sure that this chunk exists (if the resource
|
// It is the callers responsibility to make sure that this chunk exists (if the resource
|
||||||
// update root data was retrieved externally, it typically doesn't)
|
// update root data was retrieved externally, it typically doesn't)
|
||||||
func (self *ResourceHandler) LookupVersion(name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
//
|
||||||
rsrc, err := self.loadResource(name, refresh)
|
//
|
||||||
|
func (self *ResourceHandler) LookupVersionByName(name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||||
|
return self.LookupVersion(self.nameHash(name), name, period, version, refresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ResourceHandler) LookupVersion(nameHash common.Hash, name string, period uint32, version uint32, refresh bool) (*resource, error) {
|
||||||
|
rsrc, err := self.loadResource(nameHash, name, refresh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -285,8 +298,12 @@ func (self *ResourceHandler) LookupVersion(name string, period uint32, version u
|
||||||
// and returned.
|
// and returned.
|
||||||
//
|
//
|
||||||
// See also (*ResourceHandler).LookupVersion
|
// See also (*ResourceHandler).LookupVersion
|
||||||
func (self *ResourceHandler) LookupHistorical(name string, period uint32, refresh bool) (*resource, error) {
|
func (self *ResourceHandler) LookupHistoricalByName(name string, period uint32, refresh bool) (*resource, error) {
|
||||||
rsrc, err := self.loadResource(name, refresh)
|
return self.LookupHistorical(self.nameHash(name), name, period, refresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ResourceHandler) LookupHistorical(nameHash common.Hash, name string, period uint32, refresh bool) (*resource, error) {
|
||||||
|
rsrc, err := self.loadResource(nameHash, name, refresh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -303,10 +320,14 @@ func (self *ResourceHandler) LookupHistorical(name string, period uint32, refres
|
||||||
// Version iteration is done as in (*ResourceHandler).LookupHistorical
|
// Version iteration is done as in (*ResourceHandler).LookupHistorical
|
||||||
//
|
//
|
||||||
// See also (*ResourceHandler).LookupHistorical
|
// See also (*ResourceHandler).LookupHistorical
|
||||||
func (self *ResourceHandler) LookupLatest(name string, refresh bool) (*resource, error) {
|
func (self *ResourceHandler) LookupLatestByName(name string, refresh bool) (*resource, error) {
|
||||||
|
return self.LookupLatest(self.nameHash(name), name, refresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ResourceHandler) LookupLatest(nameHash common.Hash, name string, refresh bool) (*resource, error) {
|
||||||
|
|
||||||
// get our blockheight at this time and the next block of the update period
|
// get our blockheight at this time and the next block of the update period
|
||||||
rsrc, err := self.loadResource(name, refresh)
|
rsrc, err := self.loadResource(nameHash, name, refresh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +383,11 @@ func (self *ResourceHandler) lookup(rsrc *resource, period uint32, version uint3
|
||||||
}
|
}
|
||||||
|
|
||||||
// load existing mutable resource into resource struct
|
// load existing mutable resource into resource struct
|
||||||
func (self *ResourceHandler) loadResource(name string, refresh bool) (*resource, error) {
|
func (self *ResourceHandler) loadResource(nameHash common.Hash, name string, refresh bool) (*resource, error) {
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
name = nameHash.Hex()
|
||||||
|
}
|
||||||
|
|
||||||
// if the resource is not known to this session we must load it
|
// if the resource is not known to this session we must load it
|
||||||
// if refresh is set, we force load
|
// if refresh is set, we force load
|
||||||
|
|
@ -374,7 +399,7 @@ func (self *ResourceHandler) loadResource(name string, refresh bool) (*resource,
|
||||||
return nil, fmt.Errorf("Invalid name '%s'", name)
|
return nil, fmt.Errorf("Invalid name '%s'", name)
|
||||||
}
|
}
|
||||||
rsrc.name = &name
|
rsrc.name = &name
|
||||||
rsrc.nameHash = self.nameHash(name)
|
rsrc.nameHash = nameHash
|
||||||
|
|
||||||
// get the root info chunk and update the cached value
|
// get the root info chunk and update the cached value
|
||||||
chunk, err := self.Get(Key(rsrc.nameHash[:]))
|
chunk, err := self.Get(Key(rsrc.nameHash[:]))
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
type baseValidator struct {
|
type baseValidator struct {
|
||||||
signFunc SignFunc
|
signFunc SignFunc
|
||||||
|
hashsize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *baseValidator) sign(datahash common.Hash) (signature Signature, err error) {
|
func (b *baseValidator) sign(datahash common.Hash) (signature Signature, err error) {
|
||||||
|
|
@ -19,6 +20,10 @@ func (b *baseValidator) sign(datahash common.Hash) (signature Signature, err err
|
||||||
return b.signFunc(datahash)
|
return b.signFunc(datahash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *baseValidator) hashSize() int {
|
||||||
|
return b.hashsize
|
||||||
|
}
|
||||||
|
|
||||||
// ENS validation of mutable resource owners
|
// ENS validation of mutable resource owners
|
||||||
type ENSValidator struct {
|
type ENSValidator struct {
|
||||||
*baseValidator
|
*baseValidator
|
||||||
|
|
@ -30,6 +35,7 @@ func NewENSValidator(contractaddress common.Address, backend bind.ContractBacken
|
||||||
validator := &ENSValidator{
|
validator := &ENSValidator{
|
||||||
baseValidator: &baseValidator{
|
baseValidator: &baseValidator{
|
||||||
signFunc: signFunc,
|
signFunc: signFunc,
|
||||||
|
hashsize: common.HashLength,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
validator.api, err = ens.NewENS(transactOpts, contractaddress, backend)
|
validator.api, err = ens.NewENS(transactOpts, contractaddress, backend)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ func NewTestSwarmServer(t *testing.T) *TestSwarmServer {
|
||||||
Server: srv,
|
Server: srv,
|
||||||
Dpa: dpa,
|
Dpa: dpa,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
hasher: storage.MakeHashFunc("SHA3")(),
|
hasher: storage.MakeHashFunc(storage.SHA3Hash)(),
|
||||||
cleanup: func() {
|
cleanup: func() {
|
||||||
rh.Close()
|
rh.Close()
|
||||||
rpcClean()
|
rpcClean()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue