* swarm/api: url scheme bzz-hash to get hashes of swarm content (#15238) Update URI to support bzz-hash scheme and handle such HTTP requests by responding with hash of the content as a text/plain response. * swarm/api: return hash of the content for bzz-hash:// requests * swarm/api: revert "return hash of the content for bzz-hash:// requests" Return hashes of the content that would be returned by bzz-raw request. * swarm/api/http: handle error in TestBzzGetPath * swarm/api: remove extra blank line in comment
This commit is contained in:
parent
5258785c81
commit
542d51895f
@ -290,9 +290,12 @@ func (s *Server) HandleDelete(w http.ResponseWriter, r *Request) {
|
|||||||
fmt.Fprint(w, newKey)
|
fmt.Fprint(w, newKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleGetRaw handles a GET request to bzz-raw://<key> and responds with
|
// HandleGet handles a GET request to
|
||||||
// the raw content stored at the given storage key
|
// - bzz-raw://<key> and responds with the raw content stored at the
|
||||||
func (s *Server) HandleGetRaw(w http.ResponseWriter, r *Request) {
|
// given storage key
|
||||||
|
// - bzz-hash://<key> and responds with the hash of the content stored
|
||||||
|
// at the given storage key as a text/plain response
|
||||||
|
func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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))
|
||||||
@ -345,6 +348,8 @@ func (s *Server) HandleGetRaw(w http.ResponseWriter, r *Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case r.uri.Raw():
|
||||||
// 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"
|
||||||
@ -354,6 +359,11 @@ func (s *Server) HandleGetRaw(w http.ResponseWriter, r *Request) {
|
|||||||
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():
|
||||||
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprint(w, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleGetFiles handles a GET request to bzz:/<manifest> with an Accept
|
// HandleGetFiles handles a GET request to bzz:/<manifest> with an Accept
|
||||||
@ -619,8 +629,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.HandleDelete(w, req)
|
s.HandleDelete(w, req)
|
||||||
|
|
||||||
case "GET":
|
case "GET":
|
||||||
if uri.Raw() || uri.DeprecatedRaw() {
|
if uri.Raw() || uri.Hash() || uri.DeprecatedRaw() {
|
||||||
s.HandleGetRaw(w, req)
|
s.HandleGet(w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/swarm/testutil"
|
"github.com/ethereum/go-ethereum/swarm/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBzzrGetPath(t *testing.T) {
|
func TestBzzGetPath(t *testing.T) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -104,6 +104,38 @@ func TestBzzrGetPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range testrequests {
|
||||||
|
var resp *http.Response
|
||||||
|
var respbody []byte
|
||||||
|
|
||||||
|
url := srv.URL + "/bzz-hash:/"
|
||||||
|
if k[:] != "" {
|
||||||
|
url += common.ToHex(key[0])[2:] + "/" + k[1:]
|
||||||
|
}
|
||||||
|
resp, err = http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Request failed: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Read request body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(respbody) != key[v].String() {
|
||||||
|
isexpectedfailrequest := false
|
||||||
|
|
||||||
|
for _, r := range expectedfailrequests {
|
||||||
|
if k[:] == r {
|
||||||
|
isexpectedfailrequest = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isexpectedfailrequest {
|
||||||
|
t.Fatalf("Response body does not match, expected: %v, got %v", key[v], string(respbody))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, c := range []struct {
|
for _, c := range []struct {
|
||||||
path string
|
path string
|
||||||
json string
|
json string
|
||||||
@ -197,6 +229,7 @@ func TestBzzrGetPath(t *testing.T) {
|
|||||||
srv.URL + "/bzz-immutable:/nonhash",
|
srv.URL + "/bzz-immutable:/nonhash",
|
||||||
srv.URL + "/bzz-raw:/nonhash",
|
srv.URL + "/bzz-raw:/nonhash",
|
||||||
srv.URL + "/bzz-list:/nonhash",
|
srv.URL + "/bzz-list:/nonhash",
|
||||||
|
srv.URL + "/bzz-hash:/nonhash",
|
||||||
}
|
}
|
||||||
|
|
||||||
nonhashresponses := []string{
|
nonhashresponses := []string{
|
||||||
@ -204,6 +237,7 @@ func TestBzzrGetPath(t *testing.T) {
|
|||||||
"error resolving nonhash: immutable address not a content hash: "nonhash"",
|
"error resolving nonhash: immutable address not a content hash: "nonhash"",
|
||||||
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
||||||
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
||||||
|
"error resolving nonhash: no DNS to resolve name: "nonhash"",
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, url := range nonhashtests {
|
for i, url := range nonhashtests {
|
||||||
|
@ -36,6 +36,8 @@ type URI struct {
|
|||||||
// * bzzr - raw swarm content
|
// * bzzr - raw swarm content
|
||||||
// * bzzi - immutable URI of an entry in a swarm manifest
|
// * bzzi - immutable URI of an entry in a swarm manifest
|
||||||
// (address is not resolved)
|
// (address is not resolved)
|
||||||
|
// * bzz-hash - hash of swarm content
|
||||||
|
//
|
||||||
Scheme string
|
Scheme string
|
||||||
|
|
||||||
// Addr is either a hexadecimal storage key or it an address which
|
// Addr is either a hexadecimal storage key or it an address which
|
||||||
@ -56,7 +58,7 @@ type URI struct {
|
|||||||
// * <scheme>://<addr>
|
// * <scheme>://<addr>
|
||||||
// * <scheme>://<addr>/<path>
|
// * <scheme>://<addr>/<path>
|
||||||
//
|
//
|
||||||
// with scheme one of bzz, bzz-raw, bzz-immutable or bzz-list
|
// with scheme one of bzz, bzz-raw, bzz-immutable, bzz-list or bzz-hash
|
||||||
// or deprecated ones bzzr and bzzi
|
// or deprecated ones bzzr and bzzi
|
||||||
func Parse(rawuri string) (*URI, error) {
|
func Parse(rawuri string) (*URI, error) {
|
||||||
u, err := url.Parse(rawuri)
|
u, err := url.Parse(rawuri)
|
||||||
@ -67,7 +69,7 @@ func Parse(rawuri string) (*URI, error) {
|
|||||||
|
|
||||||
// check the scheme is valid
|
// check the scheme is valid
|
||||||
switch uri.Scheme {
|
switch uri.Scheme {
|
||||||
case "bzz", "bzz-raw", "bzz-immutable", "bzz-list", "bzzr", "bzzi":
|
case "bzz", "bzz-raw", "bzz-immutable", "bzz-list", "bzz-hash", "bzzr", "bzzi":
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown scheme %q", u.Scheme)
|
return nil, fmt.Errorf("unknown scheme %q", u.Scheme)
|
||||||
}
|
}
|
||||||
@ -110,6 +112,10 @@ func (u *URI) DeprecatedImmutable() bool {
|
|||||||
return u.Scheme == "bzzi"
|
return u.Scheme == "bzzi"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *URI) Hash() bool {
|
||||||
|
return u.Scheme == "bzz-hash"
|
||||||
|
}
|
||||||
|
|
||||||
func (u *URI) String() string {
|
func (u *URI) String() string {
|
||||||
return u.Scheme + ":/" + u.Addr + "/" + u.Path
|
return u.Scheme + ":/" + u.Addr + "/" + u.Path
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ func TestParseURI(t *testing.T) {
|
|||||||
expectRaw bool
|
expectRaw bool
|
||||||
expectImmutable bool
|
expectImmutable bool
|
||||||
expectList bool
|
expectList bool
|
||||||
|
expectHash bool
|
||||||
expectDeprecatedRaw bool
|
expectDeprecatedRaw bool
|
||||||
expectDeprecatedImmutable bool
|
expectDeprecatedImmutable bool
|
||||||
}
|
}
|
||||||
@ -98,6 +99,16 @@ func TestParseURI(t *testing.T) {
|
|||||||
uri: "bzz://abc123/path/to/entry",
|
uri: "bzz://abc123/path/to/entry",
|
||||||
expectURI: &URI{Scheme: "bzz", Addr: "abc123", Path: "path/to/entry"},
|
expectURI: &URI{Scheme: "bzz", Addr: "abc123", Path: "path/to/entry"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
uri: "bzz-hash:",
|
||||||
|
expectURI: &URI{Scheme: "bzz-hash"},
|
||||||
|
expectHash: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: "bzz-hash:/",
|
||||||
|
expectURI: &URI{Scheme: "bzz-hash"},
|
||||||
|
expectHash: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
uri: "bzz-list:",
|
uri: "bzz-list:",
|
||||||
expectURI: &URI{Scheme: "bzz-list"},
|
expectURI: &URI{Scheme: "bzz-list"},
|
||||||
@ -152,6 +163,9 @@ func TestParseURI(t *testing.T) {
|
|||||||
if actual.List() != x.expectList {
|
if actual.List() != x.expectList {
|
||||||
t.Fatalf("expected %s list to be %t, got %t", x.uri, x.expectList, actual.List())
|
t.Fatalf("expected %s list to be %t, got %t", x.uri, x.expectList, actual.List())
|
||||||
}
|
}
|
||||||
|
if actual.Hash() != x.expectHash {
|
||||||
|
t.Fatalf("expected %s hash to be %t, got %t", x.uri, x.expectHash, actual.Hash())
|
||||||
|
}
|
||||||
if actual.DeprecatedRaw() != x.expectDeprecatedRaw {
|
if actual.DeprecatedRaw() != x.expectDeprecatedRaw {
|
||||||
t.Fatalf("expected %s deprecated raw to be %t, got %t", x.uri, x.expectDeprecatedRaw, actual.DeprecatedRaw())
|
t.Fatalf("expected %s deprecated raw to be %t, got %t", x.uri, x.expectDeprecatedRaw, actual.DeprecatedRaw())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user