Commit 35509564 authored by mortelli's avatar mortelli Committed by GitHub

manifest, jsonmanifest, api, node: add encoding marshaling to manifest interface (#495)

manifest, jsonmanifest, api, node: remove parser from jsonmanifest and replace with binary marshalling
parent bbea5abd
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"net/http" "net/http"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/manifest"
m "github.com/ethersphere/bee/pkg/metrics" m "github.com/ethersphere/bee/pkg/metrics"
"github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/tags" "github.com/ethersphere/bee/pkg/tags"
...@@ -29,7 +28,6 @@ type server struct { ...@@ -29,7 +28,6 @@ type server struct {
type Options struct { type Options struct {
Tags *tags.Tags Tags *tags.Tags
Storer storage.Storer Storer storage.Storer
ManifestParser manifest.Parser
CORSAllowedOrigins []string CORSAllowedOrigins []string
Logger logging.Logger Logger logging.Logger
Tracer *tracing.Tracer Tracer *tracing.Tracer
......
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
"github.com/ethersphere/bee/pkg/api" "github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/pingpong" "github.com/ethersphere/bee/pkg/pingpong"
"github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/tags" "github.com/ethersphere/bee/pkg/tags"
...@@ -21,11 +20,10 @@ import ( ...@@ -21,11 +20,10 @@ import (
) )
type testServerOptions struct { type testServerOptions struct {
Pingpong pingpong.Interface Pingpong pingpong.Interface
Storer storage.Storer Storer storage.Storer
ManifestParser manifest.Parser Tags *tags.Tags
Tags *tags.Tags Logger logging.Logger
Logger logging.Logger
} }
func newTestServer(t *testing.T, o testServerOptions) *http.Client { func newTestServer(t *testing.T, o testServerOptions) *http.Client {
...@@ -33,10 +31,9 @@ func newTestServer(t *testing.T, o testServerOptions) *http.Client { ...@@ -33,10 +31,9 @@ func newTestServer(t *testing.T, o testServerOptions) *http.Client {
o.Logger = logging.New(ioutil.Discard, 0) o.Logger = logging.New(ioutil.Discard, 0)
} }
s := api.New(api.Options{ s := api.New(api.Options{
Tags: o.Tags, Tags: o.Tags,
Storer: o.Storer, Storer: o.Storer,
ManifestParser: o.ManifestParser, Logger: o.Logger,
Logger: o.Logger,
}) })
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
t.Cleanup(ts.Close) t.Cleanup(ts.Close)
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"github.com/ethersphere/bee/pkg/file" "github.com/ethersphere/bee/pkg/file"
"github.com/ethersphere/bee/pkg/file/joiner" "github.com/ethersphere/bee/pkg/file/joiner"
"github.com/ethersphere/bee/pkg/jsonhttp" "github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/manifest/jsonmanifest"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
...@@ -98,7 +99,8 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) { ...@@ -98,7 +99,8 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
jsonhttp.NotFound(w, nil) jsonhttp.NotFound(w, nil)
return return
} }
manifest, err := s.ManifestParser.Parse(buf.Bytes()) manifest := jsonmanifest.NewManifest()
err = manifest.UnmarshalBinary(buf.Bytes())
if err != nil { if err != nil {
s.Logger.Debugf("bzz download: unmarshal manifest %s: %v", address, err) s.Logger.Debugf("bzz download: unmarshal manifest %s: %v", address, err)
s.Logger.Errorf("bzz download: unmarshal manifest %s", address) s.Logger.Errorf("bzz download: unmarshal manifest %s", address)
...@@ -106,7 +108,7 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) { ...@@ -106,7 +108,7 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
me, err := manifest.FindEntry(path) me, err := manifest.Entry(path)
if err != nil { if err != nil {
s.Logger.Debugf("bzz download: invalid path %s/%s: %v", address, path, err) s.Logger.Debugf("bzz download: invalid path %s/%s: %v", address, path, err)
s.Logger.Error("bzz download: invalid path") s.Logger.Error("bzz download: invalid path")
...@@ -114,20 +116,20 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) { ...@@ -114,20 +116,20 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
manifestEntryAddress := me.GetReference() manifestEntryAddress := me.Reference()
var additionalHeaders http.Header var additionalHeaders http.Header
// copy headers from manifest // copy headers from manifest
if me.GetHeaders() != nil { if me.Headers() != nil {
additionalHeaders = me.GetHeaders().Clone() additionalHeaders = me.Headers().Clone()
} else { } else {
additionalHeaders = http.Header{} additionalHeaders = http.Header{}
} }
// include filename // include filename
if me.GetName() != "" { if me.Name() != "" {
additionalHeaders.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", me.GetName())) additionalHeaders.Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"", me.Name()))
} }
// read file entry // read file entry
......
...@@ -34,10 +34,9 @@ func TestBzz(t *testing.T) { ...@@ -34,10 +34,9 @@ func TestBzz(t *testing.T) {
storer = smock.NewStorer() storer = smock.NewStorer()
sp = splitter.NewSimpleSplitter(storer) sp = splitter.NewSimpleSplitter(storer)
client = newTestServer(t, testServerOptions{ client = newTestServer(t, testServerOptions{
Storer: storer, Storer: storer,
ManifestParser: jsonmanifest.NewParser(), Tags: tags.NewTags(),
Tags: tags.NewTags(), Logger: logging.New(ioutil.Discard, 5),
Logger: logging.New(ioutil.Discard, 5),
}) })
) )
...@@ -93,15 +92,10 @@ func TestBzz(t *testing.T) { ...@@ -93,15 +92,10 @@ func TestBzz(t *testing.T) {
jsonManifest := jsonmanifest.NewManifest() jsonManifest := jsonmanifest.NewManifest()
jsonManifest.Add(filePath, jsonmanifest.JSONEntry{ e := jsonmanifest.NewEntry(fileReference, fileName, http.Header{"Content-Type": {"text/html", "charset=utf-8"}})
Reference: fileReference, jsonManifest.Add(filePath, e)
Name: fileName,
Headers: http.Header{
"Content-Type": {"text/html", "charset=utf-8"},
},
})
manifestFileBytes, err := jsonManifest.Serialize() manifestFileBytes, err := jsonManifest.MarshalBinary()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -117,11 +117,7 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, logge ...@@ -117,11 +117,7 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, logge
// create manifest entry for uploaded file // create manifest entry for uploaded file
headers := http.Header{} headers := http.Header{}
headers.Set("Content-Type", contentType) headers.Set("Content-Type", contentType)
fileEntry := &jsonmanifest.JSONEntry{ fileEntry := jsonmanifest.NewEntry(fileReference, fileName, headers)
Reference: fileReference,
Name: fileName,
Headers: headers,
}
// add entry to dir manifest // add entry to dir manifest
dirManifest.Add(filePath, fileEntry) dirManifest.Add(filePath, fileEntry)
...@@ -134,7 +130,7 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, logge ...@@ -134,7 +130,7 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, logge
// upload manifest // upload manifest
// first, serialize into byte array // first, serialize into byte array
b, err := dirManifest.Serialize() b, err := dirManifest.MarshalBinary()
if err != nil { if err != nil {
return swarm.ZeroAddress, fmt.Errorf("manifest serialize error: %w", err) return swarm.ZeroAddress, fmt.Errorf("manifest serialize error: %w", err)
} }
......
...@@ -146,15 +146,11 @@ func TestDirs(t *testing.T) { ...@@ -146,15 +146,11 @@ func TestDirs(t *testing.T) {
// create expected manifest // create expected manifest
expectedManifest := jsonmanifest.NewManifest() expectedManifest := jsonmanifest.NewManifest()
for _, file := range tc.files { for _, file := range tc.files {
e := &jsonmanifest.JSONEntry{ e := jsonmanifest.NewEntry(file.reference, file.name, file.headers)
Reference: file.reference,
Name: file.name,
Headers: file.headers,
}
expectedManifest.Add(path.Join(file.dir, file.name), e) expectedManifest.Add(path.Join(file.dir, file.name), e)
} }
b, err := expectedManifest.Serialize() b, err := expectedManifest.MarshalBinary()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package jsonmanifest
import (
"encoding/json"
"net/http"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/swarm"
)
// verify JSONEntry implements manifest.Entry.
var _ manifest.Entry = (*JSONEntry)(nil)
// JSONEntry is a JSON representation of a single manifest entry for a JSONManifest.
type JSONEntry struct {
reference swarm.Address
name string
headers http.Header
}
// NewEntry creates a new JSONEntry struct and returns it.
func NewEntry(reference swarm.Address, name string, headers http.Header) *JSONEntry {
return &JSONEntry{
reference: reference,
name: name,
headers: headers,
}
}
// Reference returns the address of the file in the entry.
func (me *JSONEntry) Reference() swarm.Address {
return me.reference
}
// Name returns the name of the file in the entry.
func (me *JSONEntry) Name() string {
return me.name
}
// Headers returns the headers for the file in the manifest entry.
func (me *JSONEntry) Headers() http.Header {
return me.headers
}
// exportEntry is a struct used for marshaling and unmarshaling JSONEntry structs.
type exportEntry struct {
Reference swarm.Address `json:"reference"`
Name string `json:"name"`
Headers http.Header `json:"headers"`
}
// MarshalJSON implements the json.Marshaler interface.
func (me *JSONEntry) MarshalJSON() ([]byte, error) {
return json.Marshal(exportEntry{
Reference: me.reference,
Name: me.name,
Headers: me.headers,
})
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (me *JSONEntry) UnmarshalJSON(b []byte) error {
e := exportEntry{}
if err := json.Unmarshal(b, &e); err != nil {
return err
}
me.reference = e.Reference
me.name = e.Name
me.headers = e.Headers
return nil
}
...@@ -6,52 +6,38 @@ package jsonmanifest ...@@ -6,52 +6,38 @@ package jsonmanifest
import ( import (
"encoding/json" "encoding/json"
"net/http"
"github.com/ethersphere/bee/pkg/manifest" "github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/swarm"
) )
var _ manifest.Parser = (*JSONParser)(nil) // verify JSONManifest implements manifest.Interface.
type JSONParser struct{}
func NewParser() *JSONParser {
return &JSONParser{}
}
func (m *JSONParser) Parse(bytes []byte) (manifest.Interface, error) {
mi := &JSONManifest{}
err := json.Unmarshal(bytes, mi)
return mi, err
}
var _ manifest.Interface = (*JSONManifest)(nil) var _ manifest.Interface = (*JSONManifest)(nil)
// JSONManifest is a JSON representation of a manifest.
// It stores manifest entries in a map based on string keys.
type JSONManifest struct { type JSONManifest struct {
Entries map[string]JSONEntry `json:"entries,omitempty"` Entries map[string]*JSONEntry `json:"entries,omitempty"`
} }
// NewManifest creates a new JSONManifest struct and returns a pointer to it.
func NewManifest() *JSONManifest { func NewManifest() *JSONManifest {
return &JSONManifest{ return &JSONManifest{
Entries: make(map[string]JSONEntry), Entries: make(map[string]*JSONEntry),
} }
} }
// Add adds a manifest entry to the specified path.
func (m *JSONManifest) Add(path string, entry manifest.Entry) { func (m *JSONManifest) Add(path string, entry manifest.Entry) {
m.Entries[path] = JSONEntry{ m.Entries[path] = NewEntry(entry.Reference(), entry.Name(), entry.Headers())
Reference: entry.GetReference(),
Name: entry.GetName(),
Headers: entry.GetHeaders(),
}
} }
// Remove removes a manifest entry on the specified path.
func (m *JSONManifest) Remove(path string) { func (m *JSONManifest) Remove(path string) {
delete(m.Entries, path) delete(m.Entries, path)
} }
func (m *JSONManifest) FindEntry(path string) (manifest.Entry, error) { // Entry returns a manifest entry if one is found in the specified path.
func (m *JSONManifest) Entry(path string) (manifest.Entry, error) {
if entry, ok := m.Entries[path]; ok { if entry, ok := m.Entries[path]; ok {
return entry, nil return entry, nil
} }
...@@ -59,26 +45,12 @@ func (m *JSONManifest) FindEntry(path string) (manifest.Entry, error) { ...@@ -59,26 +45,12 @@ func (m *JSONManifest) FindEntry(path string) (manifest.Entry, error) {
return nil, manifest.ErrNotFound return nil, manifest.ErrNotFound
} }
func (m *JSONManifest) Serialize() ([]byte, error) { // MarshalBinary implements encoding.BinaryMarshaler.
func (m *JSONManifest) MarshalBinary() (data []byte, err error) {
return json.Marshal(m) return json.Marshal(m)
} }
var _ manifest.Entry = (*JSONEntry)(nil) // UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (m *JSONManifest) UnmarshalBinary(data []byte) error {
type JSONEntry struct { return json.Unmarshal(data, m)
Reference swarm.Address `json:"reference"`
Name string `json:"name"`
Headers http.Header `json:"headers"`
}
func (me JSONEntry) GetReference() swarm.Address {
return me.Reference
}
func (me JSONEntry) GetName() string {
return me.Name
}
func (me JSONEntry) GetHeaders() http.Header {
return me.Headers
} }
...@@ -5,38 +5,34 @@ ...@@ -5,38 +5,34 @@
package manifest package manifest
import ( import (
"encoding"
"errors" "errors"
"net/http" "net/http"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
) )
// ErrNotFound is returned when an Entry is not found in the manifest.
var ErrNotFound = errors.New("manifest: not found") var ErrNotFound = errors.New("manifest: not found")
// Parser for manifest // Interface for operations with manifest.
type Parser interface {
// Parse parses the encoded manifest data and returns the result
Parse(bytes []byte) (Interface, error)
}
// Interface for operations with manifest
type Interface interface { type Interface interface {
// Add a manifest entry to specified path // Add a manifest entry to the specified path.
Add(string, Entry) Add(string, Entry)
// Remove reference from file on specified path // Remove a manifest entry on the specified path.
Remove(string) Remove(string)
// FindEntry returns manifest entry if one is found on specified path // Entry returns a manifest entry if one is found in the specified path.
FindEntry(string) (Entry, error) Entry(string) (Entry, error)
// Serialize return encoded manifest encoding.BinaryMarshaler
Serialize() ([]byte, error) encoding.BinaryUnmarshaler
} }
// Entry represents single manifest entry // Entry represents a single manifest entry.
type Entry interface { type Entry interface {
// GetReference returns address of the entry file // Reference returns the address of the file in the entry.
GetReference() swarm.Address Reference() swarm.Address
// GetName returns the name of the file for the entry, if added // Name returns the name of the file in the entry.
GetName() string Name() string
// GetHeaders returns the headers for manifest entry, if configured // Headers returns the headers for the file in the manifest entry.
GetHeaders() http.Header Headers() http.Header
} }
...@@ -29,7 +29,6 @@ import ( ...@@ -29,7 +29,6 @@ import (
memkeystore "github.com/ethersphere/bee/pkg/keystore/mem" memkeystore "github.com/ethersphere/bee/pkg/keystore/mem"
"github.com/ethersphere/bee/pkg/localstore" "github.com/ethersphere/bee/pkg/localstore"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/manifest/jsonmanifest"
"github.com/ethersphere/bee/pkg/metrics" "github.com/ethersphere/bee/pkg/metrics"
"github.com/ethersphere/bee/pkg/netstore" "github.com/ethersphere/bee/pkg/netstore"
"github.com/ethersphere/bee/pkg/p2p" "github.com/ethersphere/bee/pkg/p2p"
...@@ -302,15 +301,12 @@ func NewBee(o Options) (*Bee, error) { ...@@ -302,15 +301,12 @@ func NewBee(o Options) (*Bee, error) {
b.pullerCloser = puller b.pullerCloser = puller
manifestParser := jsonmanifest.NewParser()
var apiService api.Service var apiService api.Service
if o.APIAddr != "" { if o.APIAddr != "" {
// API server // API server
apiService = api.New(api.Options{ apiService = api.New(api.Options{
Tags: tagg, Tags: tagg,
Storer: ns, Storer: ns,
ManifestParser: manifestParser,
CORSAllowedOrigins: o.CORSAllowedOrigins, CORSAllowedOrigins: o.CORSAllowedOrigins,
Logger: logger, Logger: logger,
Tracer: tracer, Tracer: tracer,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment