mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
cmd/swarm, swarm/api: Swarm command line api to upload encrypted files
This commit is contained in:
parent
f6d48fe564
commit
3d1a1aa459
4 changed files with 57 additions and 14 deletions
|
|
@ -218,12 +218,21 @@ The output of this command is supposed to be machine-readable.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: upload,
|
Action: nonEncryptedUpload,
|
||||||
Name: "up",
|
Name: "up",
|
||||||
Usage: "upload a file or directory to swarm using the HTTP API",
|
Usage: "upload a file or directory to swarm using the HTTP API",
|
||||||
ArgsUsage: " <file>",
|
ArgsUsage: " <file>",
|
||||||
Description: `
|
Description: `
|
||||||
"upload a file or directory to swarm using the HTTP API and prints the root hash",
|
"upload a file or directory to swarm using the HTTP API and prints the root hash",
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: encryptedUpload,
|
||||||
|
Name: "encrypted-up",
|
||||||
|
Usage: "Upload a file or directory with encryption to swarm using the HTTP API. NOTE: Currently the reference for the uploaded content is non-deterministic, so you will receive different references if you upload it twice.",
|
||||||
|
ArgsUsage: " <file>",
|
||||||
|
Description: `
|
||||||
|
"upload a file or directory to swarm using the HTTP API and prints the root hash",
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,15 @@ import (
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func upload(ctx *cli.Context) {
|
func encryptedUpload(ctx *cli.Context) {
|
||||||
|
upload(ctx, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nonEncryptedUpload(ctx *cli.Context) {
|
||||||
|
upload(ctx, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func upload(ctx *cli.Context, toEncrypt bool) {
|
||||||
|
|
||||||
args := ctx.Args()
|
args := ctx.Args()
|
||||||
var (
|
var (
|
||||||
|
|
@ -97,7 +105,7 @@ func upload(ctx *cli.Context) {
|
||||||
if !recursive {
|
if !recursive {
|
||||||
return "", errors.New("Argument is a directory and recursive upload is disabled")
|
return "", errors.New("Argument is a directory and recursive upload is disabled")
|
||||||
}
|
}
|
||||||
return client.UploadDirectory(file, defaultPath, "")
|
return client.UploadDirectory(file, defaultPath, "", toEncrypt)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
doUpload = func() (string, error) {
|
doUpload = func() (string, error) {
|
||||||
|
|
@ -110,7 +118,7 @@ func upload(ctx *cli.Context) {
|
||||||
mimeType = detectMimeType(file)
|
mimeType = detectMimeType(file)
|
||||||
}
|
}
|
||||||
f.ContentType = mimeType
|
f.ContentType = mimeType
|
||||||
return client.Upload(f, "")
|
return client.Upload(f, "", toEncrypt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash, err := doUpload()
|
hash, err := doUpload()
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -29,6 +30,16 @@ import (
|
||||||
// TestCLISwarmUp tests that running 'swarm up' makes the resulting file
|
// TestCLISwarmUp tests that running 'swarm up' makes the resulting file
|
||||||
// available from all nodes via the HTTP API
|
// available from all nodes via the HTTP API
|
||||||
func TestCLISwarmUp(t *testing.T) {
|
func TestCLISwarmUp(t *testing.T) {
|
||||||
|
testCLISwarmUp(false, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCLISwarmUpEncrypted tests that running 'swarm encrypted-up' makes the resulting file
|
||||||
|
// available from all nodes via the HTTP API
|
||||||
|
func TestCLISwarmUpEncrypted(t *testing.T) {
|
||||||
|
testCLISwarmUp(true, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCLISwarmUp(toEncrypt bool, t *testing.T) {
|
||||||
log.Info("starting 3 node cluster")
|
log.Info("starting 3 node cluster")
|
||||||
cluster := newTestCluster(t, 3)
|
cluster := newTestCluster(t, 3)
|
||||||
defer cluster.Shutdown()
|
defer cluster.Shutdown()
|
||||||
|
|
@ -48,10 +59,16 @@ func TestCLISwarmUp(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// upload the file with 'swarm up' and expect a hash
|
cmd := "up"
|
||||||
log.Info("uploading file with 'swarm up'")
|
hashRegexp := `[a-f\d]{64}`
|
||||||
up := runSwarm(t, "--bzzapi", cluster.Nodes[0].URL, "up", tmp.Name())
|
if toEncrypt {
|
||||||
_, matches := up.ExpectRegexp(`[a-f\d]{64}`)
|
cmd = "encrypted-up"
|
||||||
|
hashRegexp = `[a-f\d]{128}`
|
||||||
|
}
|
||||||
|
// upload the file with 'swarm up' or 'swarm encrypted-up' and expect a hash
|
||||||
|
log.Info(fmt.Sprintf("uploading file with '%s'", cmd))
|
||||||
|
up := runSwarm(t, "--bzzapi", cluster.Nodes[0].URL, cmd, tmp.Name())
|
||||||
|
_, matches := up.ExpectRegexp(hashRegexp)
|
||||||
up.ExpectExit()
|
up.ExpectExit()
|
||||||
hash := matches[0]
|
hash := matches[0]
|
||||||
log.Info("file uploaded", "hash", hash)
|
log.Info("file uploaded", "hash", hash)
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,11 @@ func Open(path string) (*File, error) {
|
||||||
// (if the manifest argument is non-empty) or creates a new manifest containing
|
// (if the manifest argument is non-empty) or creates a new manifest containing
|
||||||
// the file, returning the resulting manifest hash (the file will then be
|
// the file, returning the resulting manifest hash (the file will then be
|
||||||
// available at bzz:/<hash>/<path>)
|
// available at bzz:/<hash>/<path>)
|
||||||
func (c *Client) Upload(file *File, manifest string) (string, error) {
|
func (c *Client) Upload(file *File, manifest string, toEncrypt bool) (string, error) {
|
||||||
if file.Size <= 0 {
|
if file.Size <= 0 {
|
||||||
return "", errors.New("file size must be greater than zero")
|
return "", errors.New("file size must be greater than zero")
|
||||||
}
|
}
|
||||||
return c.TarUpload(manifest, &FileUploader{file})
|
return c.TarUpload(manifest, &FileUploader{file}, toEncrypt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download downloads a file with the given path from the swarm manifest with
|
// Download downloads a file with the given path from the swarm manifest with
|
||||||
|
|
@ -159,14 +159,14 @@ func (c *Client) Download(hash, path string) (*File, error) {
|
||||||
// directory will then be available at bzz:/<hash>/path/to/file), with
|
// directory will then be available at bzz:/<hash>/path/to/file), with
|
||||||
// the file specified in defaultPath being uploaded to the root of the manifest
|
// the file specified in defaultPath being uploaded to the root of the manifest
|
||||||
// (i.e. bzz:/<hash>/)
|
// (i.e. bzz:/<hash>/)
|
||||||
func (c *Client) UploadDirectory(dir, defaultPath, manifest string) (string, error) {
|
func (c *Client) UploadDirectory(dir, defaultPath, manifest string, toEncrypt bool) (string, error) {
|
||||||
stat, err := os.Stat(dir)
|
stat, err := os.Stat(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
} else if !stat.IsDir() {
|
} else if !stat.IsDir() {
|
||||||
return "", fmt.Errorf("not a directory: %s", dir)
|
return "", fmt.Errorf("not a directory: %s", dir)
|
||||||
}
|
}
|
||||||
return c.TarUpload(manifest, &DirectoryUploader{dir, defaultPath})
|
return c.TarUpload(manifest, &DirectoryUploader{dir, defaultPath}, toEncrypt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadDirectory downloads the files contained in a swarm manifest under
|
// DownloadDirectory downloads the files contained in a swarm manifest under
|
||||||
|
|
@ -350,10 +350,19 @@ type UploadFn func(file *File) error
|
||||||
|
|
||||||
// TarUpload uses the given Uploader to upload files to swarm as a tar stream,
|
// TarUpload uses the given Uploader to upload files to swarm as a tar stream,
|
||||||
// returning the resulting manifest hash
|
// returning the resulting manifest hash
|
||||||
func (c *Client) TarUpload(hash string, uploader Uploader) (string, error) {
|
func (c *Client) TarUpload(hash string, uploader Uploader, toEncrypt bool) (string, error) {
|
||||||
reqR, reqW := io.Pipe()
|
reqR, reqW := io.Pipe()
|
||||||
defer reqR.Close()
|
defer reqR.Close()
|
||||||
req, err := http.NewRequest("POST", c.Gateway+"/bzz:/"+hash, reqR)
|
addr := hash
|
||||||
|
|
||||||
|
// If there is a hash already (a manifest), then that manifest will determine if the upload has
|
||||||
|
// to be encrypted or not. If there is no manifest then the toEncrypt parameter decides if
|
||||||
|
// there is encryption or not.
|
||||||
|
if hash == "" && toEncrypt {
|
||||||
|
// This is the built-in address for the encrypted upload endpoint
|
||||||
|
addr = "encrypt"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("POST", c.Gateway+"/bzz:/"+addr, reqR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue