Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
298a5386
Unverified
Commit
298a5386
authored
Sep 24, 2020
by
Nemanja Zbiljić
Committed by
GitHub
Sep 24, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for manifest metadata (#713)
parent
3c321e9d
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
298 additions
and
57 deletions
+298
-57
go.mod
go.mod
+1
-1
go.sum
go.sum
+2
-2
api.go
pkg/api/api.go
+5
-4
api_test.go
pkg/api/api_test.go
+15
-8
bzz.go
pkg/api/bzz.go
+100
-7
bzz_test.go
pkg/api/bzz_test.go
+3
-4
dirs.go
pkg/api/dirs.go
+29
-15
dirs_test.go
pkg/api/dirs_test.go
+106
-9
export_test.go
pkg/api/export_test.go
+6
-0
manifest.go
pkg/manifest/manifest.go
+11
-1
mantaray.go
pkg/manifest/mantaray.go
+14
-4
simple.go
pkg/manifest/simple.go
+6
-2
No files found.
go.mod
View file @
298a5386
...
@@ -9,7 +9,7 @@ require (
...
@@ -9,7 +9,7 @@ require (
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/ethereum/go-ethereum v1.9.20
github.com/ethereum/go-ethereum v1.9.20
github.com/ethersphere/bmt v0.1.2
github.com/ethersphere/bmt v0.1.2
github.com/ethersphere/manifest v0.
2
.0
github.com/ethersphere/manifest v0.
3
.0
github.com/ethersphere/sw3-bindings/v2 v2.0.0
github.com/ethersphere/sw3-bindings/v2 v2.0.0
github.com/gogo/protobuf v1.3.1
github.com/gogo/protobuf v1.3.1
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
...
...
go.sum
View file @
298a5386
...
@@ -165,8 +165,8 @@ github.com/ethereum/go-ethereum v1.9.20 h1:kk/J5OIoaoz3DRrCXznz3RGi212mHHXwzXlY/
...
@@ -165,8 +165,8 @@ github.com/ethereum/go-ethereum v1.9.20 h1:kk/J5OIoaoz3DRrCXznz3RGi212mHHXwzXlY/
github.com/ethereum/go-ethereum v1.9.20/go.mod h1:JSSTypSMTkGZtAdAChH2wP5dZEvPGh3nUTuDpH+hNrg=
github.com/ethereum/go-ethereum v1.9.20/go.mod h1:JSSTypSMTkGZtAdAChH2wP5dZEvPGh3nUTuDpH+hNrg=
github.com/ethersphere/bmt v0.1.2 h1:FEuvQY9xuK+rDp3VwDVyde8T396Matv/u9PdtKa2r9Q=
github.com/ethersphere/bmt v0.1.2 h1:FEuvQY9xuK+rDp3VwDVyde8T396Matv/u9PdtKa2r9Q=
github.com/ethersphere/bmt v0.1.2/go.mod h1:fqRBDmYwn3lX2MH4lkImXQgFWeNP8ikLkS/hgi/HRws=
github.com/ethersphere/bmt v0.1.2/go.mod h1:fqRBDmYwn3lX2MH4lkImXQgFWeNP8ikLkS/hgi/HRws=
github.com/ethersphere/manifest v0.
2.0 h1:HD2ufiIaw/5Vgrl4XyeGduDJ5tn50wIhqMQoWdT2GME
=
github.com/ethersphere/manifest v0.
3.0 h1:+QRXY/AQ17mg0x3e20gvn4aAOHsZpm3rzi930bsOlro
=
github.com/ethersphere/manifest v0.
2
.0/go.mod h1:ygAx0KLhXYmKqsjUab95RCbXf8UcO7yMDjyfP0lY76Y=
github.com/ethersphere/manifest v0.
3
.0/go.mod h1:ygAx0KLhXYmKqsjUab95RCbXf8UcO7yMDjyfP0lY76Y=
github.com/ethersphere/sw3-bindings/v2 v2.0.0 h1:uc+wBqEMMq7c4NWj+MSkKkkpObgrUYxfAxz6FYJWkI4=
github.com/ethersphere/sw3-bindings/v2 v2.0.0 h1:uc+wBqEMMq7c4NWj+MSkKkkpObgrUYxfAxz6FYJWkI4=
github.com/ethersphere/sw3-bindings/v2 v2.0.0/go.mod h1:OA34yk7ludjNag+yBDY9Gp3czWoFUVMsiK7gUXnZ26U=
github.com/ethersphere/sw3-bindings/v2 v2.0.0/go.mod h1:OA34yk7ludjNag+yBDY9Gp3czWoFUVMsiK7gUXnZ26U=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
...
...
pkg/api/api.go
View file @
298a5386
...
@@ -28,7 +28,8 @@ const (
...
@@ -28,7 +28,8 @@ const (
SwarmPinHeader
=
"Swarm-Pin"
SwarmPinHeader
=
"Swarm-Pin"
SwarmTagUidHeader
=
"Swarm-Tag-Uid"
SwarmTagUidHeader
=
"Swarm-Tag-Uid"
SwarmEncryptHeader
=
"Swarm-Encrypt"
SwarmEncryptHeader
=
"Swarm-Encrypt"
SwarmIndextHeader
=
"Swarm-Index"
SwarmIndexDocumentHeader
=
"Swarm-Index-Document"
SwarmErrorDocumentHeader
=
"Swarm-Error-Document"
)
)
var
(
var
(
...
...
pkg/api/api_test.go
View file @
298a5386
...
@@ -34,6 +34,7 @@ type testServerOptions struct {
...
@@ -34,6 +34,7 @@ type testServerOptions struct {
GatewayMode
bool
GatewayMode
bool
WsPingPeriod
time
.
Duration
WsPingPeriod
time
.
Duration
Logger
logging
.
Logger
Logger
logging
.
Logger
PreventRedirect
bool
}
}
func
newTestServer
(
t
*
testing
.
T
,
o
testServerOptions
)
(
*
http
.
Client
,
*
websocket
.
Conn
,
string
)
{
func
newTestServer
(
t
*
testing
.
T
,
o
testServerOptions
)
(
*
http
.
Client
,
*
websocket
.
Conn
,
string
)
{
...
@@ -74,8 +75,14 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket.
...
@@ -74,8 +75,14 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket.
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"dial: %v. url %v"
,
err
,
u
.
String
())
t
.
Fatalf
(
"dial: %v. url %v"
,
err
,
u
.
String
())
}
}
}
if
o
.
PreventRedirect
{
httpClient
.
CheckRedirect
=
func
(
req
*
http
.
Request
,
via
[]
*
http
.
Request
)
error
{
return
http
.
ErrUseLastResponse
}
}
}
return
httpClient
,
conn
,
ts
.
Listener
.
Addr
()
.
String
()
return
httpClient
,
conn
,
ts
.
Listener
.
Addr
()
.
String
()
}
}
...
...
pkg/api/bzz.go
View file @
298a5386
...
@@ -10,6 +10,7 @@ import (
...
@@ -10,6 +10,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"net/http"
"net/http"
"path"
"strings"
"strings"
"github.com/gorilla/mux"
"github.com/gorilla/mux"
...
@@ -20,6 +21,7 @@ import (
...
@@ -20,6 +21,7 @@ import (
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/tracing"
"github.com/ethersphere/bee/pkg/tracing"
)
)
...
@@ -30,8 +32,12 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -30,8 +32,12 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
ctx
:=
r
.
Context
()
ctx
:=
r
.
Context
()
nameOrHex
:=
mux
.
Vars
(
r
)[
"address"
]
nameOrHex
:=
mux
.
Vars
(
r
)[
"address"
]
path
:=
mux
.
Vars
(
r
)[
"path"
]
pathVar
:=
mux
.
Vars
(
r
)[
"path"
]
path
=
strings
.
TrimRight
(
path
,
"/"
)
if
strings
.
HasSuffix
(
pathVar
,
"/"
)
{
pathVar
=
strings
.
TrimRight
(
pathVar
,
"/"
)
// NOTE: leave one slash if there was some
pathVar
+=
"/"
}
address
,
err
:=
s
.
resolveNameOrAddress
(
nameOrHex
)
address
,
err
:=
s
.
resolveNameOrAddress
(
nameOrHex
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -96,12 +102,76 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -96,12 +102,76 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
me
,
err
:=
m
.
Lookup
(
path
)
if
pathVar
==
""
{
logger
.
Tracef
(
"bzz download: handle empty path %s"
,
address
)
if
indexDocumentSuffixKey
,
ok
:=
manifestMetadataLoad
(
m
,
manifestRootPath
,
manifestWebsiteIndexDocumentSuffixKey
);
ok
{
pathWithIndex
:=
path
.
Join
(
pathVar
,
indexDocumentSuffixKey
)
indexDocumentManifestEntry
,
err
:=
m
.
Lookup
(
pathWithIndex
)
if
err
==
nil
{
// index document exists
logger
.
Debugf
(
"bzz download: serving path: %s"
,
pathWithIndex
)
s
.
serveManifestEntry
(
w
,
r
,
j
,
address
,
indexDocumentManifestEntry
.
Reference
())
return
}
}
}
me
,
err
:=
m
.
Lookup
(
pathVar
)
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Debugf
(
"bzz download: invalid path %s/%s: %v"
,
address
,
path
,
err
)
logger
.
Debugf
(
"bzz download: invalid path %s/%s: %v"
,
address
,
path
Var
,
err
)
logger
.
Error
(
"bzz download: invalid path"
)
logger
.
Error
(
"bzz download: invalid path"
)
if
errors
.
Is
(
err
,
manifest
.
ErrNotFound
)
{
if
errors
.
Is
(
err
,
manifest
.
ErrNotFound
)
{
if
!
strings
.
HasPrefix
(
pathVar
,
"/"
)
{
// check for directory
dirPath
:=
pathVar
+
"/"
exists
,
err
:=
m
.
HasPrefix
(
dirPath
)
if
err
==
nil
&&
exists
{
// redirect to directory
u
:=
r
.
URL
u
.
Path
+=
"/"
redirectURL
:=
u
.
String
()
logger
.
Debugf
(
"bzz download: redirecting to %s: %v"
,
redirectURL
,
err
)
http
.
Redirect
(
w
,
r
,
redirectURL
,
http
.
StatusPermanentRedirect
)
return
}
}
// check index suffix path
if
indexDocumentSuffixKey
,
ok
:=
manifestMetadataLoad
(
m
,
manifestRootPath
,
manifestWebsiteIndexDocumentSuffixKey
);
ok
{
if
!
strings
.
HasSuffix
(
pathVar
,
indexDocumentSuffixKey
)
{
// check if path is directory with index
pathWithIndex
:=
path
.
Join
(
pathVar
,
indexDocumentSuffixKey
)
indexDocumentManifestEntry
,
err
:=
m
.
Lookup
(
pathWithIndex
)
if
err
==
nil
{
// index document exists
logger
.
Debugf
(
"bzz download: serving path: %s"
,
pathWithIndex
)
s
.
serveManifestEntry
(
w
,
r
,
j
,
address
,
indexDocumentManifestEntry
.
Reference
())
return
}
}
}
// check if error document is to be shown
if
errorDocumentPath
,
ok
:=
manifestMetadataLoad
(
m
,
manifestRootPath
,
manifestWebsiteErrorDocumentPathKey
);
ok
{
if
pathVar
!=
errorDocumentPath
{
errorDocumentManifestEntry
,
err
:=
m
.
Lookup
(
errorDocumentPath
)
if
err
==
nil
{
// error document exists
logger
.
Debugf
(
"bzz download: serving path: %s"
,
errorDocumentPath
)
s
.
serveManifestEntry
(
w
,
r
,
j
,
address
,
errorDocumentManifestEntry
.
Reference
())
return
}
}
}
jsonhttp
.
NotFound
(
w
,
"path address not found"
)
jsonhttp
.
NotFound
(
w
,
"path address not found"
)
}
else
{
}
else
{
jsonhttp
.
BadRequest
(
w
,
"invalid path address"
)
jsonhttp
.
BadRequest
(
w
,
"invalid path address"
)
...
@@ -109,11 +179,17 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -109,11 +179,17 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
manifestEntryAddress
:=
me
.
Reference
()
// serve requested path
s
.
serveManifestEntry
(
w
,
r
,
j
,
address
,
me
.
Reference
())
}
func
(
s
*
server
)
serveManifestEntry
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
j
file
.
JoinSeeker
,
address
,
manifestEntryAddress
swarm
.
Address
)
{
logger
:=
tracing
.
NewLoggerWithTraceID
(
r
.
Context
(),
s
.
Logger
)
ctx
:=
r
.
Context
()
// read file entry
// read file entry
buf
=
bytes
.
NewBuffer
(
nil
)
buf
:
=
bytes
.
NewBuffer
(
nil
)
_
,
err
=
file
.
JoinReadAll
(
ctx
,
j
,
manifestEntryAddress
,
buf
)
_
,
err
:
=
file
.
JoinReadAll
(
ctx
,
j
,
manifestEntryAddress
,
buf
)
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Debugf
(
"bzz download: read file entry %s: %v"
,
address
,
err
)
logger
.
Debugf
(
"bzz download: read file entry %s: %v"
,
address
,
err
)
logger
.
Errorf
(
"bzz download: read file entry %s"
,
address
)
logger
.
Errorf
(
"bzz download: read file entry %s"
,
address
)
...
@@ -156,3 +232,20 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -156,3 +232,20 @@ func (s *server) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
s
.
downloadHandler
(
w
,
r
,
fileEntryAddress
,
additionalHeaders
)
s
.
downloadHandler
(
w
,
r
,
fileEntryAddress
,
additionalHeaders
)
}
}
// manifestMetadataLoad returns the value for a key stored in the metadata of
// manifest path, or empty string if no value is present.
// The ok result indicates whether value was found in the metadata.
func
manifestMetadataLoad
(
manifest
manifest
.
Interface
,
path
,
metadataKey
string
)
(
string
,
bool
)
{
me
,
err
:=
manifest
.
Lookup
(
path
)
if
err
!=
nil
{
return
""
,
false
}
manifestRootMetadata
:=
me
.
Metadata
()
if
val
,
ok
:=
manifestRootMetadata
[
metadataKey
];
ok
{
return
val
,
ok
}
return
""
,
false
}
pkg/api/bzz_test.go
View file @
298a5386
...
@@ -16,14 +16,13 @@ import (
...
@@ -16,14 +16,13 @@ import (
"strings"
"strings"
"testing"
"testing"
"github.com/ethersphere/bee/pkg/file/pipeline/builder"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/collection/entry"
"github.com/ethersphere/bee/pkg/collection/entry"
"github.com/ethersphere/bee/pkg/file/pipeline/builder"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/manifest"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/storage"
smock
"github.com/ethersphere/bee/pkg/storage/mock"
smock
"github.com/ethersphere/bee/pkg/storage/mock"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/swarm"
...
@@ -104,7 +103,7 @@ func TestBzz(t *testing.T) {
...
@@ -104,7 +103,7 @@ func TestBzz(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
e
:=
manifest
.
NewEntry
(
fileReference
)
e
:=
manifest
.
NewEntry
(
fileReference
,
nil
)
err
=
m
.
Add
(
filePath
,
e
)
err
=
m
.
Add
(
filePath
,
e
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
pkg/api/dirs.go
View file @
298a5386
...
@@ -33,6 +33,12 @@ const (
...
@@ -33,6 +33,12 @@ const (
contentTypeTar
=
"application/x-tar"
contentTypeTar
=
"application/x-tar"
)
)
const
(
manifestRootPath
=
"/"
manifestWebsiteIndexDocumentSuffixKey
=
"website-index-document"
manifestWebsiteErrorDocumentPathKey
=
"website-error-document"
)
// dirUploadHandler uploads a directory supplied as a tar in an HTTP request
// dirUploadHandler uploads a directory supplied as a tar in an HTTP request
func
(
s
*
server
)
dirUploadHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
s
*
server
)
dirUploadHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
logger
:=
tracing
.
NewLoggerWithTraceID
(
r
.
Context
(),
s
.
Logger
)
logger
:=
tracing
.
NewLoggerWithTraceID
(
r
.
Context
(),
s
.
Logger
)
...
@@ -55,7 +61,7 @@ func (s *server) dirUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -55,7 +61,7 @@ func (s *server) dirUploadHandler(w http.ResponseWriter, r *http.Request) {
// Add the tag to the context
// Add the tag to the context
ctx
:=
sctx
.
SetTag
(
r
.
Context
(),
tag
)
ctx
:=
sctx
.
SetTag
(
r
.
Context
(),
tag
)
reference
,
err
:=
storeDir
(
ctx
,
r
.
Body
,
s
.
Storer
,
requestModePut
(
r
),
s
.
Logger
,
requestEncrypt
(
r
),
r
.
Header
.
Get
(
SwarmIndextHeader
))
reference
,
err
:=
storeDir
(
ctx
,
r
.
Body
,
s
.
Storer
,
requestModePut
(
r
),
s
.
Logger
,
requestEncrypt
(
r
),
r
.
Header
.
Get
(
SwarmIndex
DocumentHeader
),
r
.
Header
.
Get
(
SwarmErrorDocumen
tHeader
))
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Debugf
(
"dir upload: store dir err: %v"
,
err
)
logger
.
Debugf
(
"dir upload: store dir err: %v"
,
err
)
logger
.
Errorf
(
"dir upload: store dir"
)
logger
.
Errorf
(
"dir upload: store dir"
)
...
@@ -95,7 +101,7 @@ func validateRequest(r *http.Request) error {
...
@@ -95,7 +101,7 @@ func validateRequest(r *http.Request) error {
// storeDir stores all files recursively contained in the directory given as a tar
// storeDir stores all files recursively contained in the directory given as a tar
// it returns the hash for the uploaded manifest corresponding to the uploaded dir
// it returns the hash for the uploaded manifest corresponding to the uploaded dir
func
storeDir
(
ctx
context
.
Context
,
reader
io
.
ReadCloser
,
s
storage
.
Storer
,
mode
storage
.
ModePut
,
log
logging
.
Logger
,
encrypt
bool
,
indexFilename
string
)
(
swarm
.
Address
,
error
)
{
func
storeDir
(
ctx
context
.
Context
,
reader
io
.
ReadCloser
,
s
storage
.
Storer
,
mode
storage
.
ModePut
,
log
logging
.
Logger
,
encrypt
bool
,
indexFilename
string
,
errorFilename
string
)
(
swarm
.
Address
,
error
)
{
logger
:=
tracing
.
NewLoggerWithTraceID
(
ctx
,
log
)
logger
:=
tracing
.
NewLoggerWithTraceID
(
ctx
,
log
)
dirManifest
,
err
:=
manifest
.
NewDefaultManifest
(
encrypt
,
s
)
dirManifest
,
err
:=
manifest
.
NewDefaultManifest
(
encrypt
,
s
)
...
@@ -103,6 +109,10 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
...
@@ -103,6 +109,10 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
return
swarm
.
ZeroAddress
,
err
return
swarm
.
ZeroAddress
,
err
}
}
if
indexFilename
!=
""
&&
strings
.
ContainsRune
(
indexFilename
,
'/'
)
{
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"index document suffix must not include slash character"
)
}
// set up HTTP body reader
// set up HTTP body reader
tarReader
:=
tar
.
NewReader
(
reader
)
tarReader
:=
tar
.
NewReader
(
reader
)
defer
reader
.
Close
()
defer
reader
.
Close
()
...
@@ -143,23 +153,11 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
...
@@ -143,23 +153,11 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
logger
.
Tracef
(
"uploaded dir file %v with reference %v"
,
filePath
,
fileReference
)
logger
.
Tracef
(
"uploaded dir file %v with reference %v"
,
filePath
,
fileReference
)
// add file entry to dir manifest
// add file entry to dir manifest
err
=
dirManifest
.
Add
(
filePath
,
manifest
.
NewEntry
(
fileReference
))
err
=
dirManifest
.
Add
(
filePath
,
manifest
.
NewEntry
(
fileReference
,
nil
))
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"add to manifest: %w"
,
err
)
}
if
indexFilename
!=
""
&&
filePath
==
indexFilename
||
strings
.
HasSuffix
(
filePath
,
"/"
+
indexFilename
)
{
filePath
:=
strings
.
TrimSuffix
(
filePath
,
indexFilename
)
filePath
=
strings
.
TrimRight
(
filePath
,
"/"
)
// add file entry to dir manifest
err
=
dirManifest
.
Add
(
filePath
,
manifest
.
NewEntry
(
fileReference
))
if
err
!=
nil
{
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"add to manifest: %w"
,
err
)
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"add to manifest: %w"
,
err
)
}
}
}
filesAdded
++
filesAdded
++
}
}
...
@@ -168,6 +166,22 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
...
@@ -168,6 +166,22 @@ func storeDir(ctx context.Context, reader io.ReadCloser, s storage.Storer, mode
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"no files in tar"
)
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"no files in tar"
)
}
}
// store website information
if
indexFilename
!=
""
||
errorFilename
!=
""
{
metadata
:=
map
[
string
]
string
{}
if
indexFilename
!=
""
{
metadata
[
manifestWebsiteIndexDocumentSuffixKey
]
=
indexFilename
}
if
errorFilename
!=
""
{
metadata
[
manifestWebsiteErrorDocumentPathKey
]
=
errorFilename
}
rootManifestEntry
:=
manifest
.
NewEntry
(
swarm
.
ZeroAddress
,
metadata
)
err
=
dirManifest
.
Add
(
manifestRootPath
,
rootManifestEntry
)
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
fmt
.
Errorf
(
"add to manifest: %w"
,
err
)
}
}
// save manifest
// save manifest
manifestBytesReference
,
err
:=
dirManifest
.
Store
(
ctx
,
mode
)
manifestBytesReference
,
err
:=
dirManifest
.
Store
(
ctx
,
mode
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
pkg/api/dirs_test.go
View file @
298a5386
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"bytes"
"bytes"
"context"
"context"
"encoding/json"
"encoding/json"
"fmt"
"io/ioutil"
"io/ioutil"
"net/http"
"net/http"
"path"
"path"
...
@@ -32,6 +33,7 @@ func TestDirs(t *testing.T) {
...
@@ -32,6 +33,7 @@ func TestDirs(t *testing.T) {
var
(
var
(
dirUploadResource
=
"/dirs"
dirUploadResource
=
"/dirs"
fileDownloadResource
=
func
(
addr
string
)
string
{
return
"/files/"
+
addr
}
fileDownloadResource
=
func
(
addr
string
)
string
{
return
"/files/"
+
addr
}
bzzDownloadResource
=
func
(
addr
,
path
string
)
string
{
return
"/bzz/"
+
addr
+
"/"
+
path
}
storer
=
mock
.
NewStorer
()
storer
=
mock
.
NewStorer
()
mockStatestore
=
statestore
.
NewStateStore
()
mockStatestore
=
statestore
.
NewStateStore
()
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
...
@@ -39,6 +41,7 @@ func TestDirs(t *testing.T) {
...
@@ -39,6 +41,7 @@ func TestDirs(t *testing.T) {
Storer
:
storer
,
Storer
:
storer
,
Tags
:
tags
.
NewTags
(
mockStatestore
,
logger
),
Tags
:
tags
.
NewTags
(
mockStatestore
,
logger
),
Logger
:
logging
.
New
(
ioutil
.
Discard
,
5
),
Logger
:
logging
.
New
(
ioutil
.
Discard
,
5
),
PreventRedirect
:
true
,
})
})
)
)
...
@@ -87,7 +90,9 @@ func TestDirs(t *testing.T) {
...
@@ -87,7 +90,9 @@ func TestDirs(t *testing.T) {
for
_
,
tc
:=
range
[]
struct
{
for
_
,
tc
:=
range
[]
struct
{
name
string
name
string
wantIndexFilename
string
wantIndexFilename
string
wantErrorFilename
string
indexFilenameOption
jsonhttptest
.
Option
indexFilenameOption
jsonhttptest
.
Option
errorFilenameOption
jsonhttptest
.
Option
files
[]
f
// files in dir for test case
files
[]
f
// files in dir for test case
}{
}{
{
{
...
@@ -162,7 +167,7 @@ func TestDirs(t *testing.T) {
...
@@ -162,7 +167,7 @@ func TestDirs(t *testing.T) {
{
{
name
:
"explicit index filename"
,
name
:
"explicit index filename"
,
wantIndexFilename
:
"index.html"
,
wantIndexFilename
:
"index.html"
,
indexFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmIndextHeader
,
"index.html"
),
indexFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmIndex
Documen
tHeader
,
"index.html"
),
files
:
[]
f
{
files
:
[]
f
{
{
{
data
:
[]
byte
(
"<h1>Swarm"
),
data
:
[]
byte
(
"<h1>Swarm"
),
...
@@ -178,7 +183,7 @@ func TestDirs(t *testing.T) {
...
@@ -178,7 +183,7 @@ func TestDirs(t *testing.T) {
{
{
name
:
"nested index filename"
,
name
:
"nested index filename"
,
wantIndexFilename
:
"index.html"
,
wantIndexFilename
:
"index.html"
,
indexFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmIndextHeader
,
"index.html"
),
indexFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmIndex
Documen
tHeader
,
"index.html"
),
files
:
[]
f
{
files
:
[]
f
{
{
{
data
:
[]
byte
(
"<h1>Swarm"
),
data
:
[]
byte
(
"<h1>Swarm"
),
...
@@ -191,6 +196,33 @@ func TestDirs(t *testing.T) {
...
@@ -191,6 +196,33 @@ func TestDirs(t *testing.T) {
},
},
},
},
},
},
{
name
:
"explicit index and error filename"
,
wantIndexFilename
:
"index.html"
,
wantErrorFilename
:
"error.html"
,
indexFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmIndexDocumentHeader
,
"index.html"
),
errorFilenameOption
:
jsonhttptest
.
WithRequestHeader
(
api
.
SwarmErrorDocumentHeader
,
"error.html"
),
files
:
[]
f
{
{
data
:
[]
byte
(
"<h1>Swarm"
),
name
:
"index.html"
,
dir
:
""
,
reference
:
swarm
.
MustParseHexAddress
(
"bcb1bfe15c36f1a529a241f4d0c593e5648aa6d40859790894c6facb41a6ef28"
),
header
:
http
.
Header
{
"Content-Type"
:
{
"text/html; charset=utf-8"
},
},
},
{
data
:
[]
byte
(
"<h2>404"
),
name
:
"error.html"
,
dir
:
""
,
reference
:
swarm
.
MustParseHexAddress
(
"b1f309c095d650521b75760b23122a9c59c2b581af28fc6daaf9c58da86a204d"
),
header
:
http
.
Header
{
"Content-Type"
:
{
"text/html; charset=utf-8"
},
},
},
},
},
}
{
}
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
// tar all the test case files
// tar all the test case files
...
@@ -206,6 +238,9 @@ func TestDirs(t *testing.T) {
...
@@ -206,6 +238,9 @@ func TestDirs(t *testing.T) {
if
tc
.
indexFilenameOption
!=
nil
{
if
tc
.
indexFilenameOption
!=
nil
{
options
=
append
(
options
,
tc
.
indexFilenameOption
)
options
=
append
(
options
,
tc
.
indexFilenameOption
)
}
}
if
tc
.
errorFilenameOption
!=
nil
{
options
=
append
(
options
,
tc
.
errorFilenameOption
)
}
// verify directory tar upload response
// verify directory tar upload response
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
dirUploadResource
,
http
.
StatusOK
,
options
...
)
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
dirUploadResource
,
http
.
StatusOK
,
options
...
)
...
@@ -271,15 +306,77 @@ func TestDirs(t *testing.T) {
...
@@ -271,15 +306,77 @@ func TestDirs(t *testing.T) {
)
)
}
}
validateIsPermanentRedirect
:=
func
(
t
*
testing
.
T
,
fromPath
,
toPath
string
)
{
t
.
Helper
()
expectedResponse
:=
fmt
.
Sprintf
(
"<a href=
\"
%s
\"
>Permanent Redirect</a>.
\n\n
"
,
bzzDownloadResource
(
resp
.
Reference
.
String
(),
toPath
))
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodGet
,
bzzDownloadResource
(
resp
.
Reference
.
String
(),
fromPath
),
http
.
StatusPermanentRedirect
,
jsonhttptest
.
WithExpectedResponse
([]
byte
(
expectedResponse
)),
)
}
validateBzzPath
:=
func
(
t
*
testing
.
T
,
fromPath
,
toPath
string
)
{
t
.
Helper
()
toEntry
,
err
:=
verifyManifest
.
Lookup
(
toPath
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
var
respBytes
[]
byte
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodGet
,
fileDownloadResource
(
toEntry
.
Reference
()
.
String
()),
http
.
StatusOK
,
jsonhttptest
.
WithPutResponseBody
(
&
respBytes
),
)
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodGet
,
bzzDownloadResource
(
resp
.
Reference
.
String
(),
fromPath
),
http
.
StatusOK
,
jsonhttptest
.
WithExpectedResponse
(
respBytes
),
)
}
// check if each file can be located and read
// check if each file can be located and read
for
_
,
file
:=
range
tc
.
files
{
for
_
,
file
:=
range
tc
.
files
{
validateFile
(
t
,
file
,
path
.
Join
(
file
.
dir
,
file
.
name
))
validateFile
(
t
,
file
,
path
.
Join
(
file
.
dir
,
file
.
name
))
}
// if there is an index filename to be tested
// check index filename
// try to download it using only the directory as the path
if
tc
.
wantIndexFilename
!=
""
{
if
file
.
name
==
tc
.
wantIndexFilename
{
entry
,
err
:=
verifyManifest
.
Lookup
(
api
.
ManifestRootPath
)
validateFile
(
t
,
file
,
file
.
dir
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
manifestRootMetadata
:=
entry
.
Metadata
()
indexDocumentSuffixPath
,
ok
:=
manifestRootMetadata
[
api
.
ManifestWebsiteIndexDocumentSuffixKey
]
if
!
ok
{
t
.
Fatalf
(
"expected index filename '%s', did not find any"
,
tc
.
wantIndexFilename
)
}
// check index suffix for each dir
for
_
,
file
:=
range
tc
.
files
{
if
file
.
dir
!=
""
{
validateIsPermanentRedirect
(
t
,
file
.
dir
,
file
.
dir
+
"/"
)
validateBzzPath
(
t
,
file
.
dir
+
"/"
,
path
.
Join
(
file
.
dir
,
indexDocumentSuffixPath
))
}
}
}
// check error filename
if
tc
.
wantErrorFilename
!=
""
{
entry
,
err
:=
verifyManifest
.
Lookup
(
api
.
ManifestRootPath
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
manifestRootMetadata
:=
entry
.
Metadata
()
errorDocumentPath
,
ok
:=
manifestRootMetadata
[
api
.
ManifestWebsiteErrorDocumentPathKey
]
if
!
ok
{
t
.
Fatalf
(
"expected error filename '%s', did not find any"
,
tc
.
wantErrorFilename
)
}
// check error document
validateBzzPath
(
t
,
"_non_existent_file_path_"
,
errorDocumentPath
)
}
}
})
})
...
...
pkg/api/export_test.go
View file @
298a5386
...
@@ -21,6 +21,12 @@ var (
...
@@ -21,6 +21,12 @@ var (
ContentTypeTar
=
contentTypeTar
ContentTypeTar
=
contentTypeTar
)
)
var
(
ManifestRootPath
=
manifestRootPath
ManifestWebsiteIndexDocumentSuffixKey
=
manifestWebsiteIndexDocumentSuffixKey
ManifestWebsiteErrorDocumentPathKey
=
manifestWebsiteErrorDocumentPathKey
)
var
(
var
(
ErrNoResolver
=
errNoResolver
ErrNoResolver
=
errNoResolver
ErrInvalidNameOrAddress
=
errInvalidNameOrAddress
ErrInvalidNameOrAddress
=
errInvalidNameOrAddress
...
...
pkg/manifest/manifest.go
View file @
298a5386
...
@@ -33,6 +33,8 @@ type Interface interface {
...
@@ -33,6 +33,8 @@ type Interface interface {
Remove
(
string
)
error
Remove
(
string
)
error
// Lookup returns a manifest entry if one is found in the specified path.
// Lookup returns a manifest entry if one is found in the specified path.
Lookup
(
string
)
(
Entry
,
error
)
Lookup
(
string
)
(
Entry
,
error
)
// HasPrefix tests whether the specified prefix path exists.
HasPrefix
(
string
)
(
bool
,
error
)
// Store stores the manifest, returning the resulting address.
// Store stores the manifest, returning the resulting address.
Store
(
context
.
Context
,
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
Store
(
context
.
Context
,
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
}
}
...
@@ -41,6 +43,8 @@ type Interface interface {
...
@@ -41,6 +43,8 @@ type Interface interface {
type
Entry
interface
{
type
Entry
interface
{
// Reference returns the address of the file.
// Reference returns the address of the file.
Reference
()
swarm
.
Address
Reference
()
swarm
.
Address
// Metadata returns the metadata of the file.
Metadata
()
map
[
string
]
string
}
}
// NewDefaultManifest creates a new manifest with default type.
// NewDefaultManifest creates a new manifest with default type.
...
@@ -87,15 +91,21 @@ func NewManifestReference(
...
@@ -87,15 +91,21 @@ func NewManifestReference(
type
manifestEntry
struct
{
type
manifestEntry
struct
{
reference
swarm
.
Address
reference
swarm
.
Address
metadata
map
[
string
]
string
}
}
// NewEntry creates a new manifest entry.
// NewEntry creates a new manifest entry.
func
NewEntry
(
reference
swarm
.
Address
)
Entry
{
func
NewEntry
(
reference
swarm
.
Address
,
metadata
map
[
string
]
string
)
Entry
{
return
&
manifestEntry
{
return
&
manifestEntry
{
reference
:
reference
,
reference
:
reference
,
metadata
:
metadata
,
}
}
}
}
func
(
e
*
manifestEntry
)
Reference
()
swarm
.
Address
{
func
(
e
*
manifestEntry
)
Reference
()
swarm
.
Address
{
return
e
.
reference
return
e
.
reference
}
}
func
(
e
*
manifestEntry
)
Metadata
()
map
[
string
]
string
{
return
e
.
metadata
}
pkg/manifest/mantaray.go
View file @
298a5386
...
@@ -68,7 +68,7 @@ func (m *mantarayManifest) Add(path string, entry Entry) error {
...
@@ -68,7 +68,7 @@ func (m *mantarayManifest) Add(path string, entry Entry) error {
p
:=
[]
byte
(
path
)
p
:=
[]
byte
(
path
)
e
:=
entry
.
Reference
()
.
Bytes
()
e
:=
entry
.
Reference
()
.
Bytes
()
return
m
.
trie
.
Add
(
p
,
e
,
m
.
loader
)
return
m
.
trie
.
Add
(
p
,
e
,
entry
.
Metadata
(),
m
.
loader
)
}
}
func
(
m
*
mantarayManifest
)
Remove
(
path
string
)
error
{
func
(
m
*
mantarayManifest
)
Remove
(
path
string
)
error
{
...
@@ -88,18 +88,28 @@ func (m *mantarayManifest) Remove(path string) error {
...
@@ -88,18 +88,28 @@ func (m *mantarayManifest) Remove(path string) error {
func
(
m
*
mantarayManifest
)
Lookup
(
path
string
)
(
Entry
,
error
)
{
func
(
m
*
mantarayManifest
)
Lookup
(
path
string
)
(
Entry
,
error
)
{
p
:=
[]
byte
(
path
)
p
:=
[]
byte
(
path
)
ref
,
err
:=
m
.
trie
.
Lookup
(
p
,
m
.
loader
)
node
,
err
:=
m
.
trie
.
LookupNode
(
p
,
m
.
loader
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
ErrNotFound
return
nil
,
ErrNotFound
}
}
address
:=
swarm
.
NewAddress
(
ref
)
if
!
node
.
IsValueType
()
{
return
nil
,
ErrNotFound
}
address
:=
swarm
.
NewAddress
(
node
.
Entry
())
entry
:=
NewEntry
(
address
)
entry
:=
NewEntry
(
address
,
node
.
Metadata
()
)
return
entry
,
nil
return
entry
,
nil
}
}
func
(
m
*
mantarayManifest
)
HasPrefix
(
prefix
string
)
(
bool
,
error
)
{
p
:=
[]
byte
(
prefix
)
return
m
.
trie
.
HasPrefix
(
p
,
m
.
loader
)
}
func
(
m
*
mantarayManifest
)
Store
(
ctx
context
.
Context
,
mode
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
{
func
(
m
*
mantarayManifest
)
Store
(
ctx
context
.
Context
,
mode
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
{
saver
:=
newMantaraySaver
(
ctx
,
m
.
encrypted
,
m
.
storer
,
mode
)
saver
:=
newMantaraySaver
(
ctx
,
m
.
encrypted
,
m
.
storer
,
mode
)
...
...
pkg/manifest/simple.go
View file @
298a5386
...
@@ -66,7 +66,7 @@ func (m *simpleManifest) Type() string {
...
@@ -66,7 +66,7 @@ func (m *simpleManifest) Type() string {
func
(
m
*
simpleManifest
)
Add
(
path
string
,
entry
Entry
)
error
{
func
(
m
*
simpleManifest
)
Add
(
path
string
,
entry
Entry
)
error
{
e
:=
entry
.
Reference
()
.
String
()
e
:=
entry
.
Reference
()
.
String
()
return
m
.
manifest
.
Add
(
path
,
e
)
return
m
.
manifest
.
Add
(
path
,
e
,
entry
.
Metadata
()
)
}
}
func
(
m
*
simpleManifest
)
Remove
(
path
string
)
error
{
func
(
m
*
simpleManifest
)
Remove
(
path
string
)
error
{
...
@@ -94,11 +94,15 @@ func (m *simpleManifest) Lookup(path string) (Entry, error) {
...
@@ -94,11 +94,15 @@ func (m *simpleManifest) Lookup(path string) (Entry, error) {
return
nil
,
fmt
.
Errorf
(
"parse swarm address: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"parse swarm address: %w"
,
err
)
}
}
entry
:=
NewEntry
(
address
)
entry
:=
NewEntry
(
address
,
n
.
Metadata
()
)
return
entry
,
nil
return
entry
,
nil
}
}
func
(
m
*
simpleManifest
)
HasPrefix
(
prefix
string
)
(
bool
,
error
)
{
return
m
.
manifest
.
HasPrefix
(
prefix
),
nil
}
func
(
m
*
simpleManifest
)
Store
(
ctx
context
.
Context
,
mode
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
{
func
(
m
*
simpleManifest
)
Store
(
ctx
context
.
Context
,
mode
storage
.
ModePut
)
(
swarm
.
Address
,
error
)
{
data
,
err
:=
m
.
manifest
.
MarshalBinary
()
data
,
err
:=
m
.
manifest
.
MarshalBinary
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment