Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
张蕾
Geth-Modification
Commits
f7d3678c
Commit
f7d3678c
authored
Jul 12, 2018
by
Anton Evangelatov
Committed by
Balint Gabor
Jul 12, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
swarm/api/http: http package refactoring 1/5 and 2/5 (#17164)
parent
facf1bc9
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
579 additions
and
381 deletions
+579
-381
api.go
swarm/api/api.go
+243
-16
client_test.go
swarm/api/client/client_test.go
+1
-1
error_test.go
swarm/api/http/error_test.go
+0
-1
server.go
swarm/api/http/server.go
+207
-358
server_test.go
swarm/api/http/server_test.go
+125
-1
swarm.go
swarm/swarm.go
+3
-4
No files found.
swarm/api/api.go
View file @
f7d3678c
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
api
package
api
import
(
import
(
"archive/tar"
"context"
"context"
"fmt"
"fmt"
"io"
"io"
...
@@ -48,6 +49,16 @@ var (
...
@@ -48,6 +49,16 @@ var (
apiGetCount
=
metrics
.
NewRegisteredCounter
(
"api.get.count"
,
nil
)
apiGetCount
=
metrics
.
NewRegisteredCounter
(
"api.get.count"
,
nil
)
apiGetNotFound
=
metrics
.
NewRegisteredCounter
(
"api.get.notfound"
,
nil
)
apiGetNotFound
=
metrics
.
NewRegisteredCounter
(
"api.get.notfound"
,
nil
)
apiGetHTTP300
=
metrics
.
NewRegisteredCounter
(
"api.get.http.300"
,
nil
)
apiGetHTTP300
=
metrics
.
NewRegisteredCounter
(
"api.get.http.300"
,
nil
)
apiManifestUpdateCount
=
metrics
.
NewRegisteredCounter
(
"api.manifestupdate.count"
,
nil
)
apiManifestUpdateFail
=
metrics
.
NewRegisteredCounter
(
"api.manifestupdate.fail"
,
nil
)
apiManifestListCount
=
metrics
.
NewRegisteredCounter
(
"api.manifestlist.count"
,
nil
)
apiManifestListFail
=
metrics
.
NewRegisteredCounter
(
"api.manifestlist.fail"
,
nil
)
apiDeleteCount
=
metrics
.
NewRegisteredCounter
(
"api.delete.count"
,
nil
)
apiDeleteFail
=
metrics
.
NewRegisteredCounter
(
"api.delete.fail"
,
nil
)
apiGetTarCount
=
metrics
.
NewRegisteredCounter
(
"api.gettar.count"
,
nil
)
apiGetTarFail
=
metrics
.
NewRegisteredCounter
(
"api.gettar.fail"
,
nil
)
apiUploadTarCount
=
metrics
.
NewRegisteredCounter
(
"api.uploadtar.count"
,
nil
)
apiUploadTarFail
=
metrics
.
NewRegisteredCounter
(
"api.uploadtar.fail"
,
nil
)
apiModifyCount
=
metrics
.
NewRegisteredCounter
(
"api.modify.count"
,
nil
)
apiModifyCount
=
metrics
.
NewRegisteredCounter
(
"api.modify.count"
,
nil
)
apiModifyFail
=
metrics
.
NewRegisteredCounter
(
"api.modify.fail"
,
nil
)
apiModifyFail
=
metrics
.
NewRegisteredCounter
(
"api.modify.fail"
,
nil
)
apiAddFileCount
=
metrics
.
NewRegisteredCounter
(
"api.addfile.count"
,
nil
)
apiAddFileCount
=
metrics
.
NewRegisteredCounter
(
"api.addfile.count"
,
nil
)
...
@@ -424,6 +435,185 @@ func (a *API) Get(ctx context.Context, manifestAddr storage.Address, path string
...
@@ -424,6 +435,185 @@ func (a *API) Get(ctx context.Context, manifestAddr storage.Address, path string
return
return
}
}
func
(
a
*
API
)
Delete
(
ctx
context
.
Context
,
addr
string
,
path
string
)
(
storage
.
Address
,
error
)
{
apiDeleteCount
.
Inc
(
1
)
uri
,
err
:=
Parse
(
"bzz:/"
+
addr
)
if
err
!=
nil
{
apiDeleteFail
.
Inc
(
1
)
return
nil
,
err
}
key
,
err
:=
a
.
Resolve
(
ctx
,
uri
)
if
err
!=
nil
{
return
nil
,
err
}
newKey
,
err
:=
a
.
UpdateManifest
(
ctx
,
key
,
func
(
mw
*
ManifestWriter
)
error
{
log
.
Debug
(
fmt
.
Sprintf
(
"removing %s from manifest %s"
,
path
,
key
.
Log
()))
return
mw
.
RemoveEntry
(
path
)
})
if
err
!=
nil
{
apiDeleteFail
.
Inc
(
1
)
return
nil
,
err
}
return
newKey
,
nil
}
// GetDirectoryTar fetches a requested directory as a tarstream
// it returns an io.Reader and an error. Do not forget to Close() the returned ReadCloser
func
(
a
*
API
)
GetDirectoryTar
(
ctx
context
.
Context
,
uri
*
URI
)
(
io
.
ReadCloser
,
error
)
{
apiGetTarCount
.
Inc
(
1
)
addr
,
err
:=
a
.
Resolve
(
ctx
,
uri
)
if
err
!=
nil
{
return
nil
,
err
}
walker
,
err
:=
a
.
NewManifestWalker
(
ctx
,
addr
,
nil
)
if
err
!=
nil
{
apiGetTarFail
.
Inc
(
1
)
return
nil
,
err
}
piper
,
pipew
:=
io
.
Pipe
()
tw
:=
tar
.
NewWriter
(
pipew
)
go
func
()
{
err
:=
walker
.
Walk
(
func
(
entry
*
ManifestEntry
)
error
{
// ignore manifests (walk will recurse into them)
if
entry
.
ContentType
==
ManifestType
{
return
nil
}
// retrieve the entry's key and size
reader
,
_
:=
a
.
Retrieve
(
ctx
,
storage
.
Address
(
common
.
Hex2Bytes
(
entry
.
Hash
)))
size
,
err
:=
reader
.
Size
(
nil
)
if
err
!=
nil
{
return
err
}
// write a tar header for the entry
hdr
:=
&
tar
.
Header
{
Name
:
entry
.
Path
,
Mode
:
entry
.
Mode
,
Size
:
size
,
ModTime
:
entry
.
ModTime
,
Xattrs
:
map
[
string
]
string
{
"user.swarm.content-type"
:
entry
.
ContentType
,
},
}
if
err
:=
tw
.
WriteHeader
(
hdr
);
err
!=
nil
{
return
err
}
// copy the file into the tar stream
n
,
err
:=
io
.
Copy
(
tw
,
io
.
LimitReader
(
reader
,
hdr
.
Size
))
if
err
!=
nil
{
return
err
}
else
if
n
!=
size
{
return
fmt
.
Errorf
(
"error writing %s: expected %d bytes but sent %d"
,
entry
.
Path
,
size
,
n
)
}
return
nil
})
if
err
!=
nil
{
apiGetTarFail
.
Inc
(
1
)
pipew
.
CloseWithError
(
err
)
}
else
{
pipew
.
Close
()
}
}()
return
piper
,
nil
}
// GetManifestList lists the manifest entries for the specified address and prefix
// and returns it as a ManifestList
func
(
a
*
API
)
GetManifestList
(
ctx
context
.
Context
,
addr
storage
.
Address
,
prefix
string
)
(
list
ManifestList
,
err
error
)
{
apiManifestListCount
.
Inc
(
1
)
walker
,
err
:=
a
.
NewManifestWalker
(
ctx
,
addr
,
nil
)
if
err
!=
nil
{
apiManifestListFail
.
Inc
(
1
)
return
ManifestList
{},
err
}
err
=
walker
.
Walk
(
func
(
entry
*
ManifestEntry
)
error
{
// handle non-manifest files
if
entry
.
ContentType
!=
ManifestType
{
// ignore the file if it doesn't have the specified prefix
if
!
strings
.
HasPrefix
(
entry
.
Path
,
prefix
)
{
return
nil
}
// if the path after the prefix contains a slash, add a
// common prefix to the list, otherwise add the entry
suffix
:=
strings
.
TrimPrefix
(
entry
.
Path
,
prefix
)
if
index
:=
strings
.
Index
(
suffix
,
"/"
);
index
>
-
1
{
list
.
CommonPrefixes
=
append
(
list
.
CommonPrefixes
,
prefix
+
suffix
[
:
index
+
1
])
return
nil
}
if
entry
.
Path
==
""
{
entry
.
Path
=
"/"
}
list
.
Entries
=
append
(
list
.
Entries
,
entry
)
return
nil
}
// if the manifest's path is a prefix of the specified prefix
// then just recurse into the manifest by returning nil and
// continuing the walk
if
strings
.
HasPrefix
(
prefix
,
entry
.
Path
)
{
return
nil
}
// if the manifest's path has the specified prefix, then if the
// path after the prefix contains a slash, add a common prefix
// to the list and skip the manifest, otherwise recurse into
// the manifest by returning nil and continuing the walk
if
strings
.
HasPrefix
(
entry
.
Path
,
prefix
)
{
suffix
:=
strings
.
TrimPrefix
(
entry
.
Path
,
prefix
)
if
index
:=
strings
.
Index
(
suffix
,
"/"
);
index
>
-
1
{
list
.
CommonPrefixes
=
append
(
list
.
CommonPrefixes
,
prefix
+
suffix
[
:
index
+
1
])
return
ErrSkipManifest
}
return
nil
}
// the manifest neither has the prefix or needs recursing in to
// so just skip it
return
ErrSkipManifest
})
if
err
!=
nil
{
apiManifestListFail
.
Inc
(
1
)
return
ManifestList
{},
err
}
return
list
,
nil
}
func
(
a
*
API
)
UpdateManifest
(
ctx
context
.
Context
,
addr
storage
.
Address
,
update
func
(
mw
*
ManifestWriter
)
error
)
(
storage
.
Address
,
error
)
{
apiManifestUpdateCount
.
Inc
(
1
)
mw
,
err
:=
a
.
NewManifestWriter
(
ctx
,
addr
,
nil
)
if
err
!=
nil
{
apiManifestUpdateFail
.
Inc
(
1
)
return
nil
,
err
}
if
err
:=
update
(
mw
);
err
!=
nil
{
apiManifestUpdateFail
.
Inc
(
1
)
return
nil
,
err
}
addr
,
err
=
mw
.
Store
()
if
err
!=
nil
{
apiManifestUpdateFail
.
Inc
(
1
)
return
nil
,
err
}
log
.
Debug
(
fmt
.
Sprintf
(
"generated manifest %s"
,
addr
))
return
addr
,
nil
}
// Modify loads manifest and checks the content hash before recalculating and storing the manifest.
// Modify loads manifest and checks the content hash before recalculating and storing the manifest.
func
(
a
*
API
)
Modify
(
ctx
context
.
Context
,
addr
storage
.
Address
,
path
,
contentHash
,
contentType
string
)
(
storage
.
Address
,
error
)
{
func
(
a
*
API
)
Modify
(
ctx
context
.
Context
,
addr
storage
.
Address
,
path
,
contentHash
,
contentType
string
)
(
storage
.
Address
,
error
)
{
apiModifyCount
.
Inc
(
1
)
apiModifyCount
.
Inc
(
1
)
...
@@ -501,6 +691,43 @@ func (a *API) AddFile(ctx context.Context, mhash, path, fname string, content []
...
@@ -501,6 +691,43 @@ func (a *API) AddFile(ctx context.Context, mhash, path, fname string, content []
return
fkey
,
newMkey
.
String
(),
nil
return
fkey
,
newMkey
.
String
(),
nil
}
}
func
(
a
*
API
)
UploadTar
(
ctx
context
.
Context
,
bodyReader
io
.
ReadCloser
,
manifestPath
string
,
mw
*
ManifestWriter
)
(
storage
.
Address
,
error
)
{
apiUploadTarCount
.
Inc
(
1
)
var
contentKey
storage
.
Address
tr
:=
tar
.
NewReader
(
bodyReader
)
defer
bodyReader
.
Close
()
for
{
hdr
,
err
:=
tr
.
Next
()
if
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
apiUploadTarFail
.
Inc
(
1
)
return
nil
,
fmt
.
Errorf
(
"error reading tar stream: %s"
,
err
)
}
// only store regular files
if
!
hdr
.
FileInfo
()
.
Mode
()
.
IsRegular
()
{
continue
}
// add the entry under the path from the request
manifestPath
:=
path
.
Join
(
manifestPath
,
hdr
.
Name
)
entry
:=
&
ManifestEntry
{
Path
:
manifestPath
,
ContentType
:
hdr
.
Xattrs
[
"user.swarm.content-type"
],
Mode
:
hdr
.
Mode
,
Size
:
hdr
.
Size
,
ModTime
:
hdr
.
ModTime
,
}
contentKey
,
err
=
mw
.
AddEntry
(
ctx
,
tr
,
entry
)
if
err
!=
nil
{
apiUploadTarFail
.
Inc
(
1
)
return
nil
,
fmt
.
Errorf
(
"error adding manifest entry from tar stream: %s"
,
err
)
}
}
return
contentKey
,
nil
}
// RemoveFile removes a file entry in a manifest.
// RemoveFile removes a file entry in a manifest.
func
(
a
*
API
)
RemoveFile
(
ctx
context
.
Context
,
mhash
string
,
path
string
,
fname
string
,
nameresolver
bool
)
(
string
,
error
)
{
func
(
a
*
API
)
RemoveFile
(
ctx
context
.
Context
,
mhash
string
,
path
string
,
fname
string
,
nameresolver
bool
)
(
string
,
error
)
{
apiRmFileCount
.
Inc
(
1
)
apiRmFileCount
.
Inc
(
1
)
...
...
swarm/api/client/client_test.go
View file @
f7d3678c
...
@@ -31,7 +31,7 @@ import (
...
@@ -31,7 +31,7 @@ import (
)
)
func
serverFunc
(
api
*
api
.
API
)
testutil
.
TestServer
{
func
serverFunc
(
api
*
api
.
API
)
testutil
.
TestServer
{
return
swarmhttp
.
NewServer
(
api
)
return
swarmhttp
.
NewServer
(
api
,
""
)
}
}
// TestClientUploadDownloadRaw test uploading and downloading raw data to swarm
// TestClientUploadDownloadRaw test uploading and downloading raw data to swarm
...
...
swarm/api/http/error_test.go
View file @
f7d3678c
...
@@ -29,7 +29,6 @@ import (
...
@@ -29,7 +29,6 @@ import (
)
)
func
TestError
(
t
*
testing
.
T
)
{
func
TestError
(
t
*
testing
.
T
)
{
srv
:=
testutil
.
NewTestSwarmServer
(
t
,
serverFunc
)
srv
:=
testutil
.
NewTestSwarmServer
(
t
,
serverFunc
)
defer
srv
.
Close
()
defer
srv
.
Close
()
...
...
swarm/api/http/server.go
View file @
f7d3678c
This diff is collapsed.
Click to expand it.
swarm/api/http/server_test.go
View file @
f7d3678c
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
http
package
http
import
(
import
(
"archive/tar"
"bytes"
"bytes"
"context"
"context"
"crypto/rand"
"crypto/rand"
...
@@ -24,11 +25,13 @@ import (
...
@@ -24,11 +25,13 @@ import (
"errors"
"errors"
"flag"
"flag"
"fmt"
"fmt"
"io"
"io/ioutil"
"io/ioutil"
"net/http"
"net/http"
"os"
"os"
"strings"
"strings"
"testing"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
...
@@ -88,7 +91,7 @@ func TestResourcePostMode(t *testing.T) {
...
@@ -88,7 +91,7 @@ func TestResourcePostMode(t *testing.T) {
}
}
func
serverFunc
(
api
*
api
.
API
)
testutil
.
TestServer
{
func
serverFunc
(
api
*
api
.
API
)
testutil
.
TestServer
{
return
NewServer
(
api
)
return
NewServer
(
api
,
""
)
}
}
// test the transparent resolving of multihash resource types with bzz:// scheme
// test the transparent resolving of multihash resource types with bzz:// scheme
...
@@ -356,6 +359,11 @@ func TestBzzGetPath(t *testing.T) {
...
@@ -356,6 +359,11 @@ func TestBzzGetPath(t *testing.T) {
testBzzGetPath
(
true
,
t
)
testBzzGetPath
(
true
,
t
)
}
}
func
TestBzzTar
(
t
*
testing
.
T
)
{
testBzzTar
(
false
,
t
)
testBzzTar
(
true
,
t
)
}
func
testBzzGetPath
(
encrypted
bool
,
t
*
testing
.
T
)
{
func
testBzzGetPath
(
encrypted
bool
,
t
*
testing
.
T
)
{
var
err
error
var
err
error
...
@@ -592,6 +600,122 @@ func testBzzGetPath(encrypted bool, t *testing.T) {
...
@@ -592,6 +600,122 @@ func testBzzGetPath(encrypted bool, t *testing.T) {
}
}
}
}
func
testBzzTar
(
encrypted
bool
,
t
*
testing
.
T
)
{
srv
:=
testutil
.
NewTestSwarmServer
(
t
,
serverFunc
)
defer
srv
.
Close
()
fileNames
:=
[]
string
{
"tmp1.txt"
,
"tmp2.lock"
,
"tmp3.rtf"
}
fileContents
:=
[]
string
{
"tmp1textfilevalue"
,
"tmp2lockfilelocked"
,
"tmp3isjustaplaintextfile"
}
buf
:=
&
bytes
.
Buffer
{}
tw
:=
tar
.
NewWriter
(
buf
)
defer
tw
.
Close
()
for
i
,
v
:=
range
fileNames
{
size
:=
int64
(
len
(
fileContents
[
i
]))
hdr
:=
&
tar
.
Header
{
Name
:
v
,
Mode
:
0644
,
Size
:
size
,
ModTime
:
time
.
Now
(),
Xattrs
:
map
[
string
]
string
{
"user.swarm.content-type"
:
"text/plain"
,
},
}
if
err
:=
tw
.
WriteHeader
(
hdr
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
// copy the file into the tar stream
n
,
err
:=
io
.
Copy
(
tw
,
bytes
.
NewBufferString
(
fileContents
[
i
]))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
else
if
n
!=
size
{
t
.
Fatal
(
"size mismatch"
)
}
}
//post tar stream
url
:=
srv
.
URL
+
"/bzz:/"
if
encrypted
{
url
=
url
+
"encrypt"
}
req
,
err
:=
http
.
NewRequest
(
"POST"
,
url
,
buf
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
req
.
Header
.
Add
(
"Content-Type"
,
"application/x-tar"
)
client
:=
&
http
.
Client
{}
resp2
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
resp2
.
StatusCode
!=
http
.
StatusOK
{
t
.
Fatalf
(
"err %s"
,
resp2
.
Status
)
}
swarmHash
,
err
:=
ioutil
.
ReadAll
(
resp2
.
Body
)
resp2
.
Body
.
Close
()
t
.
Logf
(
"uploaded tarball successfully and got manifest address at %s"
,
string
(
swarmHash
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// now do a GET to get a tarball back
req
,
err
=
http
.
NewRequest
(
"GET"
,
fmt
.
Sprintf
(
srv
.
URL
+
"/bzz:/%s"
,
string
(
swarmHash
)),
nil
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
req
.
Header
.
Add
(
"Accept"
,
"application/x-tar"
)
resp2
,
err
=
client
.
Do
(
req
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
resp2
.
Body
.
Close
()
file
,
err
:=
ioutil
.
TempFile
(
""
,
"swarm-downloaded-tarball"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
Remove
(
file
.
Name
())
_
,
err
=
io
.
Copy
(
file
,
resp2
.
Body
)
if
err
!=
nil
{
t
.
Fatalf
(
"error getting tarball: %v"
,
err
)
}
file
.
Sync
()
file
.
Close
()
tarFileHandle
,
err
:=
os
.
Open
(
file
.
Name
())
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
tr
:=
tar
.
NewReader
(
tarFileHandle
)
for
{
hdr
,
err
:=
tr
.
Next
()
if
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
t
.
Fatalf
(
"error reading tar stream: %s"
,
err
)
}
bb
:=
make
([]
byte
,
hdr
.
Size
)
_
,
err
=
tr
.
Read
(
bb
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
t
.
Fatal
(
err
)
}
passed
:=
false
for
i
,
v
:=
range
fileNames
{
if
v
==
hdr
.
Name
{
if
string
(
bb
)
==
fileContents
[
i
]
{
passed
=
true
break
}
}
}
if
!
passed
{
t
.
Fatalf
(
"file %s did not pass content assertion"
,
hdr
.
Name
)
}
}
}
// TestBzzRootRedirect tests that getting the root path of a manifest without
// TestBzzRootRedirect tests that getting the root path of a manifest without
// a trailing slash gets redirected to include the trailing slash so that
// a trailing slash gets redirected to include the trailing slash so that
// relative URLs work as expected.
// relative URLs work as expected.
...
...
swarm/swarm.go
View file @
f7d3678c
...
@@ -388,10 +388,9 @@ func (self *Swarm) Start(srv *p2p.Server) error {
...
@@ -388,10 +388,9 @@ func (self *Swarm) Start(srv *p2p.Server) error {
// start swarm http proxy server
// start swarm http proxy server
if
self
.
config
.
Port
!=
""
{
if
self
.
config
.
Port
!=
""
{
addr
:=
net
.
JoinHostPort
(
self
.
config
.
ListenAddr
,
self
.
config
.
Port
)
addr
:=
net
.
JoinHostPort
(
self
.
config
.
ListenAddr
,
self
.
config
.
Port
)
go
httpapi
.
StartHTTPServer
(
self
.
api
,
&
httpapi
.
ServerConfig
{
server
:=
httpapi
.
NewServer
(
self
.
api
,
self
.
config
.
Cors
)
Addr
:
addr
,
CorsString
:
self
.
config
.
Cors
,
go
server
.
ListenAndServe
(
addr
)
})
}
}
log
.
Debug
(
fmt
.
Sprintf
(
"Swarm http proxy started on port: %v"
,
self
.
config
.
Port
))
log
.
Debug
(
fmt
.
Sprintf
(
"Swarm http proxy started on port: %v"
,
self
.
config
.
Port
))
...
...
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