Commit cf2d2cc4 authored by acud's avatar acud Committed by GitHub

add debug api to expose localstore Has (#114)

* add debug api to expose localstore Has
parent 218d07d3
// 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 debugapi
import (
"net/http"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/gorilla/mux"
)
func (s *server) hasChunkHandler(w http.ResponseWriter, r *http.Request) {
addr, err := swarm.ParseHexAddress(mux.Vars(r)["address"])
if err != nil {
s.Logger.Debugf("debug api: parse chunk address: %v", err)
jsonhttp.BadRequest(w, "bad address")
return
}
has, err := s.Storer.Has(r.Context(), addr)
if err != nil {
s.Logger.Debugf("debug api: localstore has: %v", err)
jsonhttp.BadRequest(w, err)
return
}
if !has {
jsonhttp.NotFound(w, nil)
return
}
jsonhttp.OK(w, nil)
}
// 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 debugapi_test
import (
"context"
"net/http"
"testing"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/storage/mock"
"github.com/ethersphere/bee/pkg/swarm"
)
func TestHasChunkHandler(t *testing.T) {
mockStorer := mock.NewStorer()
testServer := newTestServer(t, testServerOptions{
Storer: mockStorer,
})
defer testServer.Cleanup()
key := swarm.MustParseHexAddress("aabbcc")
value := []byte("data data data")
_, err := mockStorer.Put(context.Background(), storage.ModePutUpload, swarm.NewChunk(key, value))
if err != nil {
t.Fatal(err)
}
t.Run("ok", func(t *testing.T) {
jsonhttptest.ResponseDirect(t, testServer.Client, http.MethodGet, "/chunks/"+key.String(), nil, http.StatusOK, jsonhttp.StatusResponse{
Message: http.StatusText(http.StatusOK),
Code: http.StatusOK,
})
})
t.Run("not found", func(t *testing.T) {
jsonhttptest.ResponseDirect(t, testServer.Client, http.MethodGet, "/chunks/abbbbb", nil, http.StatusNotFound, jsonhttp.StatusResponse{
Message: http.StatusText(http.StatusNotFound),
Code: http.StatusNotFound,
})
})
t.Run("bad address", func(t *testing.T) {
jsonhttptest.ResponseDirect(t, testServer.Client, http.MethodGet, "/chunks/abcd1100zz", nil, http.StatusBadRequest, jsonhttp.StatusResponse{
Message: "bad address",
Code: http.StatusBadRequest,
})
})
}
......@@ -10,6 +10,7 @@ import (
"github.com/ethersphere/bee/pkg/addressbook"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/topology"
"github.com/prometheus/client_golang/prometheus"
......@@ -32,6 +33,7 @@ type Options struct {
P2P p2p.Service
Addressbook addressbook.GetPutter
TopologyDriver topology.PeerAdder
Storer storage.Storer
Logger logging.Logger
}
......
......@@ -16,6 +16,7 @@ import (
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
mockstore "github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/topology/mock"
"github.com/multiformats/go-multiaddr"
......@@ -25,6 +26,7 @@ import (
type testServerOptions struct {
Overlay swarm.Address
P2P p2p.Service
Storer storage.Storer
}
type testServer struct {
......@@ -45,6 +47,7 @@ func newTestServer(t *testing.T, o testServerOptions) *testServer {
Logger: logging.New(ioutil.Discard, 0),
Addressbook: addressbook,
TopologyDriver: topologyDriver,
Storer: o.Storer,
})
ts := httptest.NewServer(s)
cleanup := ts.Close
......
......@@ -52,6 +52,9 @@ func (s *server) setupRouting() {
router.Handle("/peers/{address}", jsonhttp.MethodHandler{
"DELETE": http.HandlerFunc(s.peerDisconnectHandler),
})
router.Handle("/chunks/{address}", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.hasChunkHandler),
})
baseRouter.Handle("/", web.ChainHandlers(
logging.NewHTTPAccessLogHandler(s.Logger, logrus.InfoLevel, "debug api access"),
......
......@@ -179,17 +179,18 @@ func NewBee(o Options) (*Bee, error) {
logger.Infof("p2p address: %s", addr)
}
var storer storage.Storer
if o.DataDir == "" {
storer, err = localstore.New("", address.Bytes(), nil, logger)
if err != nil {
return nil, fmt.Errorf("localstore: %w", err)
}
} else {
storer, err = localstore.New(filepath.Join(o.DataDir, "localstore"), address.Bytes(), nil, logger)
if err != nil {
return nil, fmt.Errorf("localstore: %w", err)
}
var (
storer storage.Storer
path = ""
)
if o.DataDir != "" {
path = filepath.Join(o.DataDir, "localstore")
}
storer, err = localstore.New(path, address.Bytes(), nil, logger)
if err != nil {
return nil, fmt.Errorf("localstore: %w", err)
}
b.localstoreCloser = storer
......@@ -241,6 +242,7 @@ func NewBee(o Options) (*Bee, error) {
Logger: logger,
Addressbook: addressbook,
TopologyDriver: topologyDriver,
Storer: storer,
})
// register metrics from components
debugAPIService.MustRegisterMetrics(p2ps.Metrics()...)
......
......@@ -53,7 +53,8 @@ func (m *mockStorer) GetMulti(ctx context.Context, mode storage.ModeGet, addrs .
}
func (m *mockStorer) Has(ctx context.Context, addr swarm.Address) (yes bool, err error) {
panic("not implemented") // TODO: Implement
_, has := m.store[addr.String()]
return has, nil
}
func (m *mockStorer) HasMulti(ctx context.Context, addrs ...swarm.Address) (yes []bool, err error) {
......
......@@ -39,13 +39,19 @@ func TestMockStorer(t *testing.T) {
}
if chunk, err := s.Get(ctx, storage.ModeGetRequest, keyFound); err != nil {
t.Fatalf("expected not error but got: %v", err)
t.Fatalf("expected no error but got: %v", err)
} else {
if !bytes.Equal(chunk.Data(), valueFound) {
t.Fatalf("expected value %s but got %s", valueFound, chunk.Data())
}
}
has, err := s.Has(ctx, keyFound)
if err != nil {
t.Fatal(err)
}
if !has {
t.Fatal("expected mock store to have key")
}
}
func TestMockValidatingStorer(t *testing.T) {
......
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