aboutsummaryrefslogtreecommitdiffstats
path: root/swarm/api/api.go
diff options
context:
space:
mode:
authorLewis Marshall <lewis@lmars.net>2017-04-07 06:22:22 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-04-07 06:22:22 +0800
commit71fdaa42386173da7bfa13f1728c394aeeb4eb01 (patch)
tree364a169f650982d3b2880c95e40e2c91cb27c86e /swarm/api/api.go
parent9aca9e6deb243b87cc75325be593a3b0c2f0a113 (diff)
downloaddexon-71fdaa42386173da7bfa13f1728c394aeeb4eb01.tar.gz
dexon-71fdaa42386173da7bfa13f1728c394aeeb4eb01.tar.zst
dexon-71fdaa42386173da7bfa13f1728c394aeeb4eb01.zip
swarm/api: refactor and improve HTTP API (#3773)
This PR deprecates the file related RPC calls in favour of an improved HTTP API. The main aim is to expose a simple to use API which can be consumed by thin clients (e.g. curl and HTML forms) without the need for complex logic (e.g. manipulating prefix trie manifests).
Diffstat (limited to 'swarm/api/api.go')
-rw-r--r--swarm/api/api.go104
1 files changed, 31 insertions, 73 deletions
diff --git a/swarm/api/api.go b/swarm/api/api.go
index 7af27208d..ba1156f7e 100644
--- a/swarm/api/api.go
+++ b/swarm/api/api.go
@@ -17,6 +17,7 @@
package api
import (
+ "errors"
"fmt"
"io"
"net/http"
@@ -70,86 +71,50 @@ func (self *Api) Store(data io.Reader, size int64, wg *sync.WaitGroup) (key stor
type ErrResolve error
// DNS Resolver
-func (self *Api) Resolve(hostPort string, nameresolver bool) (storage.Key, error) {
- log.Trace(fmt.Sprintf("Resolving : %v", hostPort))
- if hashMatcher.MatchString(hostPort) || self.dns == nil {
- log.Trace(fmt.Sprintf("host is a contentHash: '%v'", hostPort))
- return storage.Key(common.Hex2Bytes(hostPort)), nil
+func (self *Api) Resolve(uri *URI) (storage.Key, error) {
+ log.Trace(fmt.Sprintf("Resolving : %v", uri.Addr))
+ if hashMatcher.MatchString(uri.Addr) {
+ log.Trace(fmt.Sprintf("addr is a hash: %q", uri.Addr))
+ return storage.Key(common.Hex2Bytes(uri.Addr)), nil
}
- if !nameresolver {
- return nil, fmt.Errorf("'%s' is not a content hash value.", hostPort)
+ if uri.Immutable() {
+ return nil, errors.New("refusing to resolve immutable address")
}
- contentHash, err := self.dns.Resolve(hostPort)
- if err != nil {
- err = ErrResolve(err)
- log.Warn(fmt.Sprintf("DNS error : %v", err))
- }
- log.Trace(fmt.Sprintf("host lookup: %v -> %v", hostPort, contentHash))
- return contentHash[:], err
-}
-func Parse(uri string) (hostPort, path string) {
- if uri == "" {
- return
- }
- parts := slashes.Split(uri, 3)
- var i int
- if len(parts) == 0 {
- return
+ if self.dns == nil {
+ return nil, fmt.Errorf("unable to resolve addr %q, resolver not configured", uri.Addr)
}
- // beginning with slash is now optional
- for len(parts[i]) == 0 {
- i++
- }
- hostPort = parts[i]
- for i < len(parts)-1 {
- i++
- if len(path) > 0 {
- path = path + "/" + parts[i]
- } else {
- path = parts[i]
- }
+ hash, err := self.dns.Resolve(uri.Addr)
+ if err != nil {
+ log.Warn(fmt.Sprintf("DNS error resolving addr %q: %s", uri.Addr, err))
+ return nil, ErrResolve(err)
}
- log.Debug(fmt.Sprintf("host: '%s', path '%s' requested.", hostPort, path))
- return
-}
-
-func (self *Api) parseAndResolve(uri string, nameresolver bool) (key storage.Key, hostPort, path string, err error) {
- hostPort, path = Parse(uri)
- //resolving host and port
- contentHash, err := self.Resolve(hostPort, nameresolver)
- log.Debug(fmt.Sprintf("Resolved '%s' to contentHash: '%s', path: '%s'", uri, contentHash, path))
- return contentHash[:], hostPort, path, err
+ log.Trace(fmt.Sprintf("addr lookup: %v -> %v", uri.Addr, hash))
+ return hash[:], nil
}
// Put provides singleton manifest creation on top of dpa store
-func (self *Api) Put(content, contentType string) (string, error) {
+func (self *Api) Put(content, contentType string) (storage.Key, error) {
r := strings.NewReader(content)
wg := &sync.WaitGroup{}
key, err := self.dpa.Store(r, int64(len(content)), wg, nil)
if err != nil {
- return "", err
+ return nil, err
}
manifest := fmt.Sprintf(`{"entries":[{"hash":"%v","contentType":"%s"}]}`, key, contentType)
r = strings.NewReader(manifest)
key, err = self.dpa.Store(r, int64(len(manifest)), wg, nil)
if err != nil {
- return "", err
+ return nil, err
}
wg.Wait()
- return key.String(), nil
+ return key, nil
}
// Get uses iterative manifest retrieval and prefix matching
// to resolve path to content using dpa retrieve
// it returns a section reader, mimeType, status and an error
-func (self *Api) Get(uri string, nameresolver bool) (reader storage.LazySectionReader, mimeType string, status int, err error) {
- key, _, path, err := self.parseAndResolve(uri, nameresolver)
- if err != nil {
- return nil, "", 500, fmt.Errorf("can't resolve: %v", err)
- }
-
- quitC := make(chan bool)
- trie, err := loadManifest(self.dpa, key, quitC)
+func (self *Api) Get(key storage.Key, path string) (reader storage.LazySectionReader, mimeType string, status int, err error) {
+ trie, err := loadManifest(self.dpa, key, nil)
if err != nil {
log.Warn(fmt.Sprintf("loadManifestTrie error: %v", err))
return
@@ -173,32 +138,25 @@ func (self *Api) Get(uri string, nameresolver bool) (reader storage.LazySectionR
return
}
-func (self *Api) Modify(uri, contentHash, contentType string, nameresolver bool) (newRootHash string, err error) {
- root, _, path, err := self.parseAndResolve(uri, nameresolver)
- if err != nil {
- return "", fmt.Errorf("can't resolve: %v", err)
- }
-
+func (self *Api) Modify(key storage.Key, path, contentHash, contentType string) (storage.Key, error) {
quitC := make(chan bool)
- trie, err := loadManifest(self.dpa, root, quitC)
+ trie, err := loadManifest(self.dpa, key, quitC)
if err != nil {
- return
+ return nil, err
}
-
if contentHash != "" {
- entry := &manifestTrieEntry{
+ entry := newManifestTrieEntry(&ManifestEntry{
Path: path,
- Hash: contentHash,
ContentType: contentType,
- }
+ }, nil)
+ entry.Hash = contentHash
trie.addEntry(entry, quitC)
} else {
trie.deleteEntry(path, quitC)
}
- err = trie.recalcAndStore()
- if err != nil {
- return
+ if err := trie.recalcAndStore(); err != nil {
+ return nil, err
}
- return trie.hash.String(), nil
+ return trie.hash, nil
}