cmd/swarm/global-store: add http server

This commit is contained in:
Janos Guljas 2019-01-31 13:18:12 +01:00
parent 82f1b042c3
commit 4ab38f28bb
3 changed files with 132 additions and 18 deletions

View file

@ -29,18 +29,54 @@ import (
cli "gopkg.in/urfave/cli.v1"
)
func startHTTP(ctx *cli.Context) (err error) {
server, cleanup, err := newServer(ctx)
if err != nil {
return err
}
defer cleanup()
listener, err := net.Listen("tcp", ctx.String("addr"))
if err != nil {
return err
}
log.Info("http", "address", listener.Addr().String())
return http.Serve(listener, server)
}
func startWS(ctx *cli.Context) (err error) {
server, cleanup, err := newServer(ctx)
if err != nil {
return err
}
defer cleanup()
listener, err := net.Listen("tcp", ctx.String("addr"))
if err != nil {
return err
}
origins := ctx.StringSlice("origins")
log.Info("websocket", "address", listener.Addr().String(), "origins", origins)
return http.Serve(listener, server.WebsocketHandler(origins))
}
func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error) {
log.PrintOrigins(true)
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
cleanup = func() {}
var globalStore mock.GlobalStorer
dir := ctx.String("dir")
if dir != "" {
dbStore, err := db.NewGlobalStore(dir)
if err != nil {
return err
return nil, nil, err
}
cleanup = func() {
dbStore.Close()
}
defer dbStore.Close()
globalStore = dbStore
log.Info("database global store", "dir", dir)
} else {
@ -48,19 +84,10 @@ func startWS(ctx *cli.Context) (err error) {
log.Info("in-memory global store")
}
server := rpc.NewServer()
server = rpc.NewServer()
if err := server.RegisterName("mockStore", globalStore); err != nil {
return err
return nil, nil, err
}
endpoint := ctx.String("endpoint")
listener, err := net.Listen("tcp", endpoint)
if err != nil {
return err
}
wsAddress := listener.Addr().String()
origins := ctx.StringSlice("origins")
log.Info("websocket", "address", wsAddress, "origins", origins)
return http.Serve(listener, server.WebsocketHandler(origins))
return server, cleanup, nil
}

View file

@ -20,6 +20,7 @@ import (
"context"
"io/ioutil"
"net"
"net/http"
"os"
"testing"
"time"
@ -29,6 +30,70 @@ import (
mockRPC "github.com/ethereum/go-ethereum/swarm/storage/mock/rpc"
)
func TestHTTP_InMemory(t *testing.T) {
testHTTP(t, true)
}
func TestHTTP_Database(t *testing.T) {
dir, err := ioutil.TempDir("", "swarm-global-store-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
testHTTP(t, true, "--dir", dir)
testHTTP(t, false, "--dir", dir)
}
func testHTTP(t *testing.T, put bool, args ...string) {
addr := findFreeTCPAddress(t)
testCmd := runGlobalStore(t, append([]string{"http", "--addr", addr}, args...)...)
defer testCmd.Interrupt()
client, err := rpc.DialHTTP("http://" + addr)
if err != nil {
t.Fatal(err)
}
// wait until global store process is started as
// rpc.DialHTTP is actually not connecting
for i := 0; i < 1000; i++ {
_, err := http.DefaultClient.Get("http://" + addr)
if err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
if err != nil {
t.Fatal(err)
}
store := mockRPC.NewGlobalStore(client)
defer store.Close()
node := store.NewNodeStore(common.HexToAddress("123abc"))
wantKey := "key"
wantValue := "value"
if put {
err = node.Put([]byte(wantKey), []byte(wantValue))
if err != nil {
t.Fatal(err)
}
}
gotValue, err := node.Get([]byte(wantKey))
if err != nil {
t.Fatal(err)
}
if string(gotValue) != wantValue {
t.Errorf("got value %s for key %s, want %s", string(gotValue), wantKey, wantValue)
}
}
func TestWebsocket_InMemory(t *testing.T) {
testWebsocket(t, true)
}
@ -47,11 +112,12 @@ func TestWebsocket_Database(t *testing.T) {
func testWebsocket(t *testing.T, put bool, args ...string) {
addr := findFreeTCPAddress(t)
testCmd := runGlobalStore(t, append([]string{"ws", "--endpoint", addr}, args...)...)
testCmd := runGlobalStore(t, append([]string{"ws", "--addr", addr}, args...)...)
defer testCmd.Interrupt()
var client *rpc.Client
var err error
// wait until global store process is started
for i := 0; i < 1000; i++ {
client, err = rpc.DialWebsocket(context.Background(), "ws://"+addr, "")
if err == nil {

View file

@ -51,10 +51,31 @@ func newApp() (app *cli.App) {
}
app.Commands = []cli.Command{
{
Name: "http",
Aliases: []string{"h"},
Usage: "start swarm global store with http server",
Action: startHTTP,
// Flags only for "start" command.
// Allow app flags to be specified after the
// command argument.
Flags: append(app.Flags,
cli.StringFlag{
Name: "dir",
Value: "",
Usage: "data directory",
},
cli.StringFlag{
Name: "addr",
Value: "0.0.0.0:3033",
Usage: "address to listen for http connection",
},
),
},
{
Name: "websocket",
Aliases: []string{"ws"},
Usage: "start swarm global store with websocket endpoint",
Usage: "start swarm global store with websocket server",
Action: startWS,
// Flags only for "start" command.
// Allow app flags to be specified after the
@ -66,9 +87,9 @@ func newApp() (app *cli.App) {
Usage: "data directory",
},
cli.StringFlag{
Name: "endpoint",
Name: "addr",
Value: "0.0.0.0:3033",
Usage: "websocket endpoint",
Usage: "address to listen for websocket connection",
},
cli.StringSliceFlag{
Name: "origins",