[#19] Add a version with no cdn-sdk deps
Signed-off-by: Pavel Korotkov <pavel@nspcc.ru>
This commit is contained in:
parent
cdab794d62
commit
4c96885a42
20 changed files with 930 additions and 266 deletions
10
.test.env
10
.test.env
|
@ -1,5 +1,5 @@
|
|||
HTTP_GW_VERBOSE=--true
|
||||
HTTP_GW_KEY=generated
|
||||
HTTP_GW_KEY=/home/pk/devbox/work/neo/user.key
|
||||
|
||||
HTTP_GW_LISTEN_ADDRESS=0.0.0.0:8087
|
||||
HTTP_GW_LOGGER_LEVEL=debug
|
||||
|
@ -10,10 +10,4 @@ HTTP_GW_KEEPALIVE_TIME=120s
|
|||
HTTP_GW_KEEPALIVE_PERMIT_WITHOUT_STREAM=True
|
||||
HTTP_GW_CONN_TTL=1h
|
||||
HTTP_GW_PEERS_0_WEIGHT=1.0
|
||||
HTTP_GW_PEERS_1_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_2_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_3_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_4_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_5_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_6_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_7_WEIGHT=0.125
|
||||
HTTP_GW_PEERS_0_ADDRESS=s01.neofs.devenv:8080
|
58
README.md
58
README.md
|
@ -34,7 +34,8 @@ NeoFS HTTP Gate is example of tool that provides basic interactions with NeoFS.
|
|||
## Configuration
|
||||
|
||||
```
|
||||
# Flags
|
||||
# Flags:
|
||||
|
||||
--pprof enable pprof
|
||||
--metrics enable prometheus
|
||||
-h, --help show help
|
||||
|
@ -43,35 +44,36 @@ NeoFS HTTP Gate is example of tool that provides basic interactions with NeoFS.
|
|||
--verbose debug gRPC connections
|
||||
--request_timeout duration gRPC request timeout (default 5s)
|
||||
--connect_timeout duration gRPC connect timeout (default 30s)
|
||||
--listen_address string HTTP Gate listen address (default "0.0.0.0:8082")
|
||||
--listen_address string HTTP gate's listen address (default "0.0.0.0:8082")
|
||||
-p, --peers stringArray NeoFS nodes
|
||||
|
||||
# Environments:
|
||||
|
||||
HTTP_GW_KEY=string - "generated" to generate key, path to private key file, hex string or wif (default "generated")
|
||||
HTTP_GW_CONNECT_TIMEOUT=Duration - timeout for connection
|
||||
HTTP_GW_REQUEST_TIMEOUT=Duration - timeout for request
|
||||
HTTP_GW_REBALANCE_TIMER=Duration - time between connections checks
|
||||
HTTP_GW_LISTEN_ADDRESS=host:port - address to listen connections
|
||||
HTTP_GW_PEERS_<X>_ADDRESS=host:port - address of NeoFS Node
|
||||
HTTP_GW_PEERS_<X>_WEIGHT=float - weight of NeoFS Node
|
||||
HTTP_GW_PPROF=bool - enable/disable pprof (/debug/pprof)
|
||||
HTTP_GW_METRICS=bool - enable/disable prometheus metrics endpoint (/metrics)
|
||||
HTTP_GW_LOGGER_FORMAT=string - logger format
|
||||
HTTP_GW_LOGGER_LEVEL=string - logger level
|
||||
HTTP_GW_LOGGER_NO_CALLER=bool - logger don't show caller
|
||||
HTTP_GW_LOGGER_NO_DISCLAIMER=bool - logger don't show application name/version
|
||||
HTTP_GW_LOGGER_SAMPLING_INITIAL=int - logger sampling initial
|
||||
HTTP_GW_LOGGER_SAMPLING_THEREAFTER=int - logger sampling thereafter
|
||||
HTTP_GW_LOGGER_TRACE_LEVEL=string - logger show trace on level
|
||||
HTTP_GW_KEEPALIVE_TIME=Duration - аfter a duration of this time if the client doesn't see any activity
|
||||
it pings the server to see if the transport is still alive.
|
||||
HTTP_GW_KEEPALIVE_TIMEOUT=Duration - after having pinged for keepalive check, the client waits for a duration
|
||||
of Timeout and if no activity is seen even after that the connection is closed
|
||||
HTTP_GW_KEEPALIVE_PERMIT_WITHOUT_STREAM=Bool - if true, client sends keepalive pings even with no active RPCs.
|
||||
If false, when there are no active RPCs, Time and Timeout will be ignored and no keepalive pings will be sent.
|
||||
|
||||
HTTP_GW_UPLOAD_HEADER_USE_DEFAULT_TIMESTAMP=bool - enable/disable adding current timestamp attribute when object uploads
|
||||
HTTP_GW_KEY=string - Path to private key file, hex string or wif string
|
||||
HTTP_GW_CONNECT_TIMEOUT=duration - Timeout for connection
|
||||
HTTP_GW_REQUEST_TIMEOUT=duration - Timeout for request
|
||||
HTTP_GW_REBALANCE_TIMER=duration - Time between connections checks
|
||||
HTTP_GW_LISTEN_ADDRESS=host:port - Address to listen connections
|
||||
HTTP_GW_PEERS_<X>_ADDRESS=host:port - Address of NeoFS Node
|
||||
HTTP_GW_PEERS_<X>_WEIGHT=float - Weight of NeoFS Node
|
||||
HTTP_GW_PPROF=bool - Enable/disable pprof (/debug/pprof)
|
||||
HTTP_GW_METRICS=bool - Enable/disable prometheus metrics endpoint (/metrics)
|
||||
HTTP_GW_LOGGER_FORMAT=string - Logger format
|
||||
HTTP_GW_LOGGER_LEVEL=string - Logger level
|
||||
HTTP_GW_LOGGER_NO_CALLER=bool - Logger don't show caller
|
||||
HTTP_GW_LOGGER_NO_DISCLAIMER=bool - Logger don't show application name/version
|
||||
HTTP_GW_LOGGER_SAMPLING_INITIAL=int - Logger sampling initial
|
||||
HTTP_GW_LOGGER_SAMPLING_THEREAFTER=int - Logger sampling thereafter
|
||||
HTTP_GW_LOGGER_TRACE_LEVEL=string - Logger show trace on level
|
||||
HTTP_GW_KEEPALIVE_TIME=duration - After a duration of this time if the client sees no activity
|
||||
it pings the server to see if the transport is still alive
|
||||
HTTP_GW_KEEPALIVE_TIMEOUT=duration - After having pinged for keepalive check, the client waits for a duration
|
||||
of Timeout and if no activity is seen even after that the connection
|
||||
is closed
|
||||
HTTP_GW_KEEPALIVE_PERMIT_WITHOUT_STREAM=bool - If true, client sends keepalive pings even with no active RPCs.
|
||||
If false, when there are no active RPCs, Time and Timeout will be
|
||||
ignored and no keepalive pings will be sent
|
||||
HTTP_GW_UPLOAD_HEADER_USE_DEFAULT_TIMESTAMP=bool - Enable/disable adding current timestamp attribute when object uploads
|
||||
|
||||
HTTP_GW_WEB_READ_BUFFER_SIZE=4096 - per-connection buffer size for requests' reading
|
||||
HTTP_GW_WEB_READ_TIMEOUT=15s - an amount of time allowed to read the full request including body
|
||||
|
@ -84,6 +86,6 @@ HTTP_GW_WEB_MAX_REQUEST_BODY_SIZE=4194304 - maximum request body size, server r
|
|||
|
||||
Peers preset:
|
||||
|
||||
HTTP_GW_PEERS_[N]_ADDRESS = string
|
||||
HTTP_GW_PEERS_[N]_WEIGHT = 0..1 (float)
|
||||
HTTP_GW_PEERS_<N>_ADDRESS = string
|
||||
HTTP_GW_PEERS_<N>_WEIGHT = 0..1 (float)
|
||||
```
|
138
app.go
138
app.go
|
@ -2,36 +2,33 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/fasthttp/router"
|
||||
sdk "github.com/nspcc-dev/cdn-sdk"
|
||||
"github.com/nspcc-dev/cdn-sdk/creds/neofs"
|
||||
"github.com/nspcc-dev/cdn-sdk/logger"
|
||||
"github.com/nspcc-dev/cdn-sdk/pool"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/client"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-http-gate/logger"
|
||||
"github.com/nspcc-dev/neofs-http-gate/neofs"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
||||
type (
|
||||
app struct {
|
||||
cli sdk.Client
|
||||
pool pool.Client
|
||||
log *zap.Logger
|
||||
cfg *viper.Viper
|
||||
key *ecdsa.PrivateKey
|
||||
|
||||
wlog logger.Logger
|
||||
web *fasthttp.Server
|
||||
|
||||
jobDone chan struct{}
|
||||
webDone chan struct{}
|
||||
|
||||
plant neofs.ClientPlant
|
||||
getOperations struct {
|
||||
client client.Client
|
||||
sessionToken *token.SessionToken
|
||||
}
|
||||
log *zap.Logger
|
||||
cfg *viper.Viper
|
||||
wlog logger.Logger
|
||||
web *fasthttp.Server
|
||||
jobDone chan struct{}
|
||||
webDone chan struct{}
|
||||
enableDefaultTimestamp bool
|
||||
}
|
||||
|
||||
|
@ -84,11 +81,11 @@ func newApp(ctx context.Context, opt ...Option) App {
|
|||
grpclog.SetLoggerV2(a.wlog)
|
||||
}
|
||||
|
||||
conTimeout := a.cfg.GetDuration(cfgConTimeout)
|
||||
reqTimeout := a.cfg.GetDuration(cfgReqTimeout)
|
||||
tckTimeout := a.cfg.GetDuration(cfgRebalance)
|
||||
// conTimeout := a.cfg.GetDuration(cfgConTimeout)
|
||||
// reqTimeout := a.cfg.GetDuration(cfgReqTimeout)
|
||||
// tckTimeout := a.cfg.GetDuration(cfgRebalance)
|
||||
|
||||
// -- setup FastHTTP server: --
|
||||
// -- setup FastHTTP server --
|
||||
a.web.Name = "neofs-http-gate"
|
||||
a.web.ReadBufferSize = a.cfg.GetInt(cfgWebReadBufferSize)
|
||||
a.web.WriteBufferSize = a.cfg.GetInt(cfgWebWriteBufferSize)
|
||||
|
@ -99,68 +96,42 @@ func newApp(ctx context.Context, opt ...Option) App {
|
|||
a.web.NoDefaultContentType = true
|
||||
a.web.MaxRequestBodySize = a.cfg.GetInt(cfgWebMaxRequestBodySize)
|
||||
|
||||
// FIXME don't work with StreamRequestBody,
|
||||
// some bugs with readMultipartForm
|
||||
// -- -- -- -- -- -- FIXME -- -- -- -- -- --
|
||||
// Does not work with StreamRequestBody,
|
||||
// some bugs with readMultipartForm
|
||||
// https://github.com/valyala/fasthttp/issues/968
|
||||
a.web.DisablePreParseMultipartForm = true
|
||||
|
||||
a.web.StreamRequestBody = a.cfg.GetBool(cfgWebStreamRequestBody)
|
||||
// -- -- -- -- -- -- -- -- -- --
|
||||
// -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
||||
|
||||
connections := make(map[string]float64)
|
||||
var cl connectionList
|
||||
for i := 0; ; i++ {
|
||||
address := a.cfg.GetString(cfgPeers + "." + strconv.Itoa(i) + ".address")
|
||||
weight := a.cfg.GetFloat64(cfgPeers + "." + strconv.Itoa(i) + ".weight")
|
||||
if address == "" {
|
||||
break
|
||||
}
|
||||
|
||||
connections[address] = weight
|
||||
a.log.Info("add connection peer",
|
||||
zap.String("address", address),
|
||||
zap.Float64("weight", weight))
|
||||
cl = append(cl, connection{address: address, weight: weight})
|
||||
a.log.Info("add connection peer", zap.String("address", address), zap.Float64("weight", weight))
|
||||
}
|
||||
|
||||
cred, err := neofs.New(a.cfg.GetString(cmdNeoFSKey))
|
||||
sort.Sort(sort.Reverse(cl))
|
||||
cred, err := neofs.NewCredentials(a.cfg.GetString(cmdNeoFSKey))
|
||||
if err != nil {
|
||||
a.log.Fatal("could not prepare credentials", zap.Error(err))
|
||||
a.log.Fatal("could not get credentials", zap.Error(err))
|
||||
}
|
||||
|
||||
a.pool, err = pool.New(ctx,
|
||||
pool.WithLogger(a.log),
|
||||
pool.WithCredentials(cred),
|
||||
pool.WithWeightPool(connections),
|
||||
pool.WithTickerTimeout(tckTimeout),
|
||||
pool.WithConnectTimeout(conTimeout),
|
||||
pool.WithRequestTimeout(reqTimeout),
|
||||
pool.WithAPIPreparer(sdk.APIPreparer),
|
||||
pool.WithGRPCOptions(
|
||||
grpc.WithBlock(),
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: a.cfg.GetDuration(cfgKeepaliveTime),
|
||||
Timeout: a.cfg.GetDuration(cfgKeepaliveTimeout),
|
||||
PermitWithoutStream: a.cfg.GetBool(cfgKeepalivePermitWithoutStream),
|
||||
})))
|
||||
|
||||
a.plant, err = neofs.NewClientPlant(ctx, cl[0].address, cred)
|
||||
if err != nil {
|
||||
a.log.Fatal("could not prepare connection pool", zap.Error(err))
|
||||
a.log.Fatal("failed to create neofs client")
|
||||
}
|
||||
|
||||
a.cli, err = sdk.New(ctx,
|
||||
sdk.WithLogger(a.log),
|
||||
sdk.WithCredentials(cred),
|
||||
sdk.WithConnectionPool(a.pool),
|
||||
sdk.WithAPIPreparer(sdk.APIPreparer))
|
||||
a.getOperations.client, a.getOperations.sessionToken, err = a.plant.GetReusableArtifacts(ctx)
|
||||
if err != nil {
|
||||
a.log.Fatal("could not prepare sdk client", zap.Error(err))
|
||||
a.log.Fatal("failed to get neofs client's reusable artifacts")
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *app) Wait() {
|
||||
a.log.Info("application started")
|
||||
a.log.Info("starting application")
|
||||
|
||||
select {
|
||||
case <-a.jobDone: // wait for job is stopped
|
||||
|
@ -171,50 +142,51 @@ func (a *app) Wait() {
|
|||
}
|
||||
|
||||
func (a *app) Worker(ctx context.Context) {
|
||||
a.pool.Worker(ctx)
|
||||
close(a.jobDone)
|
||||
}
|
||||
|
||||
func (a *app) Serve(ctx context.Context) {
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
a.log.Info("stop web-server", zap.Error(a.web.Shutdown()))
|
||||
a.log.Info("shutting down web server", zap.Error(a.web.Shutdown()))
|
||||
close(a.webDone)
|
||||
}()
|
||||
|
||||
// Configure router.
|
||||
r := router.New()
|
||||
r.RedirectTrailingSlash = true
|
||||
|
||||
a.log.Info("enabled /upload/{cid}")
|
||||
r.POST("/upload/{cid}", a.upload)
|
||||
|
||||
a.log.Info("enabled /get/{cid}/{oid}")
|
||||
a.log.Info("added path /upload/{cid}")
|
||||
r.GET("/get/{cid}/{oid}", a.byAddress)
|
||||
|
||||
a.log.Info("enabled /get_by_attribute/{cid}/{attr_key}/{attr_val:*}")
|
||||
a.log.Info("added path /get/{cid}/{oid}")
|
||||
r.GET("/get_by_attribute/{cid}/{attr_key}/{attr_val:*}", a.byAttribute)
|
||||
|
||||
a.log.Info("added path /get_by_attribute/{cid}/{attr_key}/{attr_val:*}")
|
||||
// attaching /-/(ready,healthy)
|
||||
attachHealthy(r, a.pool.Status)
|
||||
|
||||
// attachHealthy(r, a.pool.Status)
|
||||
// enable metrics
|
||||
if a.cfg.GetBool(cmdMetrics) {
|
||||
a.log.Info("enabled /metrics/")
|
||||
a.log.Info("added path /metrics/")
|
||||
attachMetrics(r, a.wlog)
|
||||
}
|
||||
|
||||
// enable pprof
|
||||
if a.cfg.GetBool(cmdPprof) {
|
||||
a.log.Info("enabled /debug/pprof/")
|
||||
a.log.Info("added path /debug/pprof/")
|
||||
attachProfiler(r)
|
||||
}
|
||||
|
||||
bind := a.cfg.GetString(cfgListenAddress)
|
||||
a.log.Info("run gateway server",
|
||||
zap.String("address", bind))
|
||||
|
||||
a.log.Info("running web server", zap.String("address", bind))
|
||||
a.web.Handler = r.Handler
|
||||
if err := a.web.ListenAndServe(bind); err != nil {
|
||||
a.log.Fatal("could not start server", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
type connection struct {
|
||||
address string
|
||||
weight float64
|
||||
}
|
||||
|
||||
type connectionList []connection
|
||||
|
||||
func (p connectionList) Len() int { return len(p) }
|
||||
func (p connectionList) Less(i, j int) bool { return p[i].weight < p[j].weight }
|
||||
func (p connectionList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
|
16
bearer.go
16
bearer.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
|
@ -18,7 +19,7 @@ const (
|
|||
|
||||
// BearerToken usage:
|
||||
//
|
||||
// if err = checkAndPropagateBearerToken(ctx); err != nil {
|
||||
// if err = storeBearerToken(ctx); err != nil {
|
||||
// log.Error("could not fetch bearer token", zap.Error(err))
|
||||
// c.Error("could not fetch bearer token", fasthttp.StatusBadRequest)
|
||||
// return
|
||||
|
@ -46,15 +47,13 @@ func fromCookie(h *fasthttp.RequestHeader) []byte {
|
|||
return auth
|
||||
}
|
||||
|
||||
func checkAndPropagateBearerToken(ctx *fasthttp.RequestCtx) error {
|
||||
func storeBearerToken(ctx *fasthttp.RequestCtx) error {
|
||||
tkn, err := fetchBearerToken(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This is an analog of context.WithValue.
|
||||
ctx.SetUserValue(bearerTokenKey, tkn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -63,14 +62,12 @@ func fetchBearerToken(ctx *fasthttp.RequestCtx) (*token.BearerToken, error) {
|
|||
if ctx == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
lastErr error
|
||||
|
||||
buf []byte
|
||||
tkn = new(token.BearerToken)
|
||||
)
|
||||
|
||||
for _, parse := range []fromHandler{fromHeader, fromCookie} {
|
||||
if buf = parse(&ctx.Request.Header); buf == nil {
|
||||
continue
|
||||
|
@ -89,3 +86,10 @@ func fetchBearerToken(ctx *fasthttp.RequestCtx) (*token.BearerToken, error) {
|
|||
|
||||
return nil, lastErr
|
||||
}
|
||||
|
||||
func loadBearerToken(ctx context.Context) (*token.BearerToken, error) {
|
||||
if tkn, ok := ctx.Value(bearerTokenKey).(*token.BearerToken); ok && tkn != nil {
|
||||
return tkn, nil
|
||||
}
|
||||
return nil, errors.New("found empty bearer token")
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/nspcc-dev/cdn-sdk"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -152,10 +151,10 @@ func Test_checkAndPropagateBearerToken(t *testing.T) {
|
|||
ctx := makeTestRequest(t64, "")
|
||||
|
||||
// Expect to see the token within the context.
|
||||
require.NoError(t, checkAndPropagateBearerToken(ctx))
|
||||
require.NoError(t, storeBearerToken(ctx))
|
||||
|
||||
// Expect to see the same token without errors.
|
||||
actual, err := sdk.BearerToken(ctx)
|
||||
actual, err := loadBearerToken(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tkn, actual)
|
||||
}
|
||||
|
|
|
@ -8,13 +8,16 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
globalContext context.Context
|
||||
globalContexOnce sync.Once
|
||||
globalContext context.Context
|
||||
globalContextOnce sync.Once
|
||||
globalContextBarrier = make(chan struct{})
|
||||
)
|
||||
|
||||
func Context() context.Context {
|
||||
globalContexOnce.Do(func() {
|
||||
globalContextOnce.Do(func() {
|
||||
globalContext, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||
close(globalContextBarrier)
|
||||
})
|
||||
<-globalContextBarrier
|
||||
return globalContext
|
||||
}
|
||||
|
|
13
go.mod
13
go.mod
|
@ -1,18 +1,21 @@
|
|||
module github.com/nspcc-dev/neofs-http-gate
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/fasthttp/router v1.3.5
|
||||
github.com/nspcc-dev/cdn-sdk v0.3.4
|
||||
github.com/nspcc-dev/neofs-api-go v1.23.0
|
||||
github.com/nspcc-dev/neofs-api-go v1.25.0
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0
|
||||
github.com/nspcc-dev/neofs-node v0.17.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.9.0
|
||||
github.com/prometheus/common v0.15.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/valyala/fasthttp v1.20.0
|
||||
github.com/valyala/fasthttp v1.22.0
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/zap v1.16.0
|
||||
google.golang.org/grpc v1.35.0
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
|
||||
google.golang.org/grpc v1.36.1
|
||||
)
|
||||
|
|
88
go.sum
88
go.sum
|
@ -10,6 +10,7 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
|
|||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
|
@ -21,6 +22,9 @@ github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1
|
|||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I=
|
||||
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
|
||||
github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
|
@ -29,6 +33,8 @@ github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzg
|
|||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/participle v0.6.0/go.mod h1:HfdmEuwvr12HXQN44HPWXR0lHmVolVYe4dyL6lQ3duY=
|
||||
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
@ -38,6 +44,8 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGn
|
|||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
|
@ -92,6 +100,7 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
|||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -140,6 +149,7 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
|
|||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -190,6 +200,7 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
|||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
|
@ -214,6 +225,8 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
|
|||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
|
@ -232,6 +245,7 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT
|
|||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
|
@ -239,10 +253,14 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg=
|
||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.8 h1:difgzQsp5mdAz9v8lm3P/I+EpDKMU/6uTMw1y1FObuo=
|
||||
github.com/klauspost/compress v1.11.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
|
@ -270,6 +288,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
|
@ -285,6 +305,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
|
||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
|
||||
github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y=
|
||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
||||
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
|
@ -294,27 +322,37 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
|||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nspcc-dev/cdn-sdk v0.3.4 h1:RtYWuF9xDWrkVwu6sFRWlyZ+ToYM7Y9h8B93Fg4CPEA=
|
||||
github.com/nspcc-dev/cdn-sdk v0.3.4/go.mod h1:JC4dT16H5HilyZcb8sTxL/TMC1FSEKMuFAqRsmAPoAk=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20200711144034-c526ccc6f570/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20210302103605-cc75991b7cfb/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y=
|
||||
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
||||
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
|
||||
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
|
||||
github.com/nspcc-dev/neo-go v0.91.0 h1:KKOPMKs0fm8JIau1SuwxiLdrZ+1kDPBiVRlWwzfebWE=
|
||||
github.com/nspcc-dev/neo-go v0.91.0/go.mod h1:G6HdOWvzQ6tlvFdvFSN/PgCzLPN/X/X4d5hTjFRUDcc=
|
||||
github.com/nspcc-dev/neo-go v0.94.0 h1:2eafoyEnueqEMGDZF06HZJQN0MHgYxFzlcre5YUOP1M=
|
||||
github.com/nspcc-dev/neo-go v0.94.0/go.mod h1:IrBT/UG3/Slhqgjge8r6zni5tNRsWmwwG9OnVdASheI=
|
||||
github.com/nspcc-dev/neofs-api-go v1.23.0 h1:t4FB5uVY99UkYR0Hiyi1SHjZuqzf4qicw7tf7BBnkHk=
|
||||
github.com/nspcc-dev/neofs-api-go v1.23.0/go.mod h1:G7dqincfdjBrAbL5nxVp82emF05fSVEqe59ICsoRDI8=
|
||||
github.com/nspcc-dev/neofs-api-go v1.24.0/go.mod h1:G7dqincfdjBrAbL5nxVp82emF05fSVEqe59ICsoRDI8=
|
||||
github.com/nspcc-dev/neofs-api-go v1.25.0 h1:hw1TTi3/3wCBB3KN6cycuM8Sn/MFnapSQptBx8KgDIY=
|
||||
github.com/nspcc-dev/neofs-api-go v1.25.0/go.mod h1:G7dqincfdjBrAbL5nxVp82emF05fSVEqe59ICsoRDI8=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM=
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
|
||||
github.com/nspcc-dev/neofs-http-gate/sdk v0.3.4 h1:RtYWuF9xDWrkVwu6sFRWlyZ+ToYM7Y9h8B93Fg4CPEA=
|
||||
github.com/nspcc-dev/neofs-http-gate/sdk v0.3.4/go.mod h1:JC4dT16H5HilyZcb8sTxL/TMC1FSEKMuFAqRsmAPoAk=
|
||||
github.com/nspcc-dev/neofs-node v0.17.0 h1:Xh01n8AKC1XmSRBN7yBKSO7Vz2rchqZfAnofcq1lis0=
|
||||
github.com/nspcc-dev/neofs-node v0.17.0/go.mod h1:nC4+0Zqxv7KZMOv59g5TvcCg0kV6m+1ySiDEuzlAuLc=
|
||||
github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
github.com/nspcc-dev/tzhash v1.4.0 h1:RVIR+mxOBHl58CE99+DXtE31ylD5PEkZSoWqoj4fVjg=
|
||||
github.com/nspcc-dev/tzhash v1.4.0/go.mod h1:Z8gp/VZbyWgPhaMp/KTmeoW5UTynp/N60g0jTtSzBws=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
|
@ -335,7 +373,10 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
|
|||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/panjf2000/ants/v2 v2.3.0/go.mod h1:LtwNaBX6OeF5qRtQlaeGndalVwJlS2ueur7uwoAHbPA=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/paulmach/orb v0.2.1/go.mod h1:91bG5A8qKNOiZtlKc0BqKMB3O5kWfRQorTwo8BZ2B/0=
|
||||
github.com/paulmach/protoscan v0.2.0/go.mod h1:2c55sl1Hu6/tgRfc8Y8zADsxuSCYC2IrPh0JCqP/yrw=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
@ -357,6 +398,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
|
|||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
|
||||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
|
||||
|
@ -372,6 +414,7 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
|
||||
|
@ -382,6 +425,7 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
|
|||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
|
@ -415,6 +459,7 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
|||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
|
@ -422,6 +467,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
|
@ -442,6 +489,7 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
|||
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
|
@ -451,6 +499,8 @@ github.com/valyala/fasthttp v1.19.0 h1:PfTS4PeH3xDr3WomrDS2ID8lU2GskK1xS3YG6gIpi
|
|||
github.com/valyala/fasthttp v1.19.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8ermTRJNroD7A=
|
||||
github.com/valyala/fasthttp v1.20.0 h1:olTmcnLQeZrkBc4TVgE/BatTo1NE/IvW050AuD8SW+U=
|
||||
github.com/valyala/fasthttp v1.20.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8ermTRJNroD7A=
|
||||
github.com/valyala/fasthttp v1.22.0 h1:OpwH5KDOJ9cS2bq8fD+KfT4IrksK0llvkHf4MZx42jQ=
|
||||
github.com/valyala/fasthttp v1.22.0/go.mod h1:0mw2RjXGOzxf4NL2jni3gUQ7LfjjUSiG5sskOUUSEpU=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
|
@ -459,6 +509,7 @@ github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBU
|
|||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
|
@ -468,12 +519,14 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
||||
|
@ -489,11 +542,17 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -509,6 +568,7 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl
|
|||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
|
@ -528,15 +588,21 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226101413-39120d07d75e h1:jIQURUJ9mlLvYwTBtRHm9h58rYhSonLvRvgAnP8Nr7I=
|
||||
golang.org/x/net v0.0.0-20210226101413-39120d07d75e/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -571,23 +637,34 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -596,6 +673,7 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
@ -614,6 +692,7 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200123022218-593de606220b h1:ztSlcncMErSAUzXwnVO1iTPxHwtvOHBB26SGiyYXIEE=
|
||||
golang.org/x/tools v0.0.0-20200123022218-593de606220b/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
|
@ -660,6 +739,10 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1 h1:cmUfbeGKnz9+2DD/UYsMQXeqbHZqZDs4eQwW0sFOpBY=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -692,6 +775,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module github.com/nspcc-dev/neofs-http-gate
|
||||
|
||||
go 1.13
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/fasthttp/router v0.6.1
|
||||
|
|
|
@ -17,7 +17,6 @@ func attachHealthy(r *router.Router, e stater) {
|
|||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||
ctx.SetBodyString(healthyState + "ready")
|
||||
})
|
||||
|
||||
r.GET("/-/healthy/", func(c *fasthttp.RequestCtx) {
|
||||
code := fasthttp.StatusOK
|
||||
msg := "healthy"
|
||||
|
@ -26,7 +25,6 @@ func attachHealthy(r *router.Router, e stater) {
|
|||
msg = "unhealthy: " + err.Error()
|
||||
code = fasthttp.StatusBadRequest
|
||||
}
|
||||
|
||||
c.Response.Reset()
|
||||
c.SetStatusCode(code)
|
||||
c.SetContentType(defaultContentType)
|
||||
|
|
60
logger/grpc.go
Normal file
60
logger/grpc.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
type (
|
||||
zapLogger struct {
|
||||
zapcore.Core
|
||||
log *zap.SugaredLogger
|
||||
}
|
||||
|
||||
Logger interface {
|
||||
grpclog.LoggerV2
|
||||
Println(v ...interface{})
|
||||
}
|
||||
)
|
||||
|
||||
func GRPC(l *zap.Logger) Logger {
|
||||
log := l.WithOptions(
|
||||
// skip gRPCLog + zapLogger in caller
|
||||
zap.AddCallerSkip(2))
|
||||
|
||||
return &zapLogger{
|
||||
Core: log.Core(),
|
||||
log: log.Sugar(),
|
||||
}
|
||||
}
|
||||
|
||||
func (z *zapLogger) Info(args ...interface{}) { z.log.Info(args...) }
|
||||
|
||||
func (z *zapLogger) Infoln(args ...interface{}) { z.log.Info(args...) }
|
||||
|
||||
func (z *zapLogger) Infof(format string, args ...interface{}) { z.log.Infof(format, args...) }
|
||||
|
||||
func (z *zapLogger) Println(args ...interface{}) { z.log.Info(args...) }
|
||||
|
||||
func (z *zapLogger) Printf(format string, args ...interface{}) { z.log.Infof(format, args...) }
|
||||
|
||||
func (z *zapLogger) Warning(args ...interface{}) { z.log.Warn(args...) }
|
||||
|
||||
func (z *zapLogger) Warningln(args ...interface{}) { z.log.Warn(args...) }
|
||||
|
||||
func (z *zapLogger) Warningf(format string, args ...interface{}) { z.log.Warnf(format, args...) }
|
||||
|
||||
func (z *zapLogger) Error(args ...interface{}) { z.log.Error(args...) }
|
||||
|
||||
func (z *zapLogger) Errorln(args ...interface{}) { z.log.Error(args...) }
|
||||
|
||||
func (z *zapLogger) Errorf(format string, args ...interface{}) { z.log.Errorf(format, args...) }
|
||||
|
||||
func (z *zapLogger) Fatal(args ...interface{}) { z.log.Fatal(args...) }
|
||||
|
||||
func (z *zapLogger) Fatalln(args ...interface{}) { z.log.Fatal(args...) }
|
||||
|
||||
func (z *zapLogger) Fatalf(format string, args ...interface{}) { z.Fatalf(format, args...) }
|
||||
|
||||
func (z *zapLogger) V(int) bool { return z.Enabled(zapcore.DebugLevel) }
|
23
logger/option.go
Normal file
23
logger/option.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package logger
|
||||
|
||||
import "go.uber.org/zap"
|
||||
|
||||
func WithSamplingInitial(v int) Option { return func(o *options) { o.SamplingInitial = v } }
|
||||
|
||||
func WithSamplingThereafter(v int) Option { return func(o *options) { o.SamplingThereafter = v } }
|
||||
|
||||
func WithFormat(v string) Option { return func(o *options) { o.Format = v } }
|
||||
|
||||
func WithLevel(v string) Option { return func(o *options) { o.Level = v } }
|
||||
|
||||
func WithTraceLevel(v string) Option { return func(o *options) { o.TraceLevel = v } }
|
||||
|
||||
func WithoutDisclaimer() Option { return func(o *options) { o.NoDisclaimer = true } }
|
||||
|
||||
func WithoutCaller() Option { return func(o *options) { o.NoCaller = true } }
|
||||
|
||||
func WithAppName(v string) Option { return func(o *options) { o.AppName = v } }
|
||||
|
||||
func WithAppVersion(v string) Option { return func(o *options) { o.AppVersion = v } }
|
||||
|
||||
func WithZapOptions(opts ...zap.Option) Option { return func(o *options) { o.Options = opts } }
|
131
logger/zap.go
Normal file
131
logger/zap.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type (
|
||||
Option func(o *options)
|
||||
|
||||
options struct {
|
||||
Options []zap.Option
|
||||
|
||||
SamplingInitial int
|
||||
SamplingThereafter int
|
||||
|
||||
Format string
|
||||
Level string
|
||||
TraceLevel string
|
||||
|
||||
NoCaller bool
|
||||
NoDisclaimer bool
|
||||
|
||||
AppName string
|
||||
AppVersion string
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
formatJSON = "json"
|
||||
formatConsole = "console"
|
||||
|
||||
defaultSamplingInitial = 100
|
||||
defaultSamplingThereafter = 100
|
||||
|
||||
lvlInfo = "info"
|
||||
lvlWarn = "warn"
|
||||
lvlDebug = "debug"
|
||||
lvlError = "error"
|
||||
lvlFatal = "fatal"
|
||||
lvlPanic = "panic"
|
||||
)
|
||||
|
||||
func safeLevel(lvl string) zap.AtomicLevel {
|
||||
switch strings.ToLower(lvl) {
|
||||
case lvlDebug:
|
||||
return zap.NewAtomicLevelAt(zap.DebugLevel)
|
||||
case lvlWarn:
|
||||
return zap.NewAtomicLevelAt(zap.WarnLevel)
|
||||
case lvlError:
|
||||
return zap.NewAtomicLevelAt(zap.ErrorLevel)
|
||||
case lvlFatal:
|
||||
return zap.NewAtomicLevelAt(zap.FatalLevel)
|
||||
case lvlPanic:
|
||||
return zap.NewAtomicLevelAt(zap.PanicLevel)
|
||||
default:
|
||||
return zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func defaults() *options {
|
||||
return &options{
|
||||
SamplingInitial: defaultSamplingInitial,
|
||||
SamplingThereafter: defaultSamplingThereafter,
|
||||
|
||||
Format: formatConsole,
|
||||
Level: lvlDebug,
|
||||
TraceLevel: lvlInfo,
|
||||
|
||||
NoCaller: false,
|
||||
NoDisclaimer: false,
|
||||
|
||||
AppName: "",
|
||||
AppVersion: "",
|
||||
}
|
||||
}
|
||||
|
||||
func New(opts ...Option) (*zap.Logger, error) {
|
||||
o := defaults()
|
||||
c := zap.NewProductionConfig()
|
||||
|
||||
c.OutputPaths = []string{"stdout"}
|
||||
c.ErrorOutputPaths = []string{"stdout"}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
// set sampling
|
||||
c.Sampling = &zap.SamplingConfig{
|
||||
Initial: o.SamplingInitial,
|
||||
Thereafter: o.SamplingThereafter,
|
||||
}
|
||||
|
||||
// logger level
|
||||
c.Level = safeLevel(o.Level)
|
||||
traceLvl := safeLevel(o.TraceLevel)
|
||||
|
||||
// logger format
|
||||
switch f := o.Format; strings.ToLower(f) {
|
||||
case formatConsole:
|
||||
c.Encoding = formatConsole
|
||||
default:
|
||||
c.Encoding = formatJSON
|
||||
}
|
||||
|
||||
// logger time
|
||||
c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
|
||||
if o.NoCaller {
|
||||
c.EncoderConfig.EncodeCaller = nil
|
||||
}
|
||||
|
||||
// enable trace only for current log-level
|
||||
o.Options = append(o.Options, zap.AddStacktrace(traceLvl))
|
||||
|
||||
l, err := c.Build(o.Options...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if o.NoDisclaimer {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
return l.With(
|
||||
zap.String("app_name", o.AppName),
|
||||
zap.String("app_version", o.AppVersion)), nil
|
||||
}
|
65
main.go
65
main.go
|
@ -1,50 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/cdn-sdk/logger"
|
||||
"github.com/nspcc-dev/neofs-http-gate/global"
|
||||
"github.com/nspcc-dev/neofs-http-gate/logger"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func newLogger(v *viper.Viper) *zap.Logger {
|
||||
options := []logger.Option{
|
||||
logger.WithLevel(v.GetString(cfgLoggerLevel)),
|
||||
logger.WithTraceLevel(v.GetString(cfgLoggerTraceLevel)),
|
||||
|
||||
logger.WithFormat(v.GetString(cfgLoggerFormat)),
|
||||
|
||||
logger.WithSamplingInitial(v.GetInt(cfgLoggerSamplingInitial)),
|
||||
logger.WithSamplingThereafter(v.GetInt(cfgLoggerSamplingThereafter)),
|
||||
|
||||
logger.WithAppName(v.GetString(cfgApplicationName)),
|
||||
logger.WithAppVersion(v.GetString(cfgApplicationVersion)),
|
||||
}
|
||||
|
||||
if v.GetBool(cfgLoggerNoCaller) {
|
||||
options = append(options, logger.WithoutCaller())
|
||||
}
|
||||
|
||||
if v.GetBool(cfgLoggerNoDisclaimer) {
|
||||
options = append(options, logger.WithoutDisclaimer())
|
||||
}
|
||||
|
||||
l, err := logger.New(options...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
v = settings()
|
||||
l = newLogger(v)
|
||||
g = global.Context()
|
||||
a = newApp(g, WithLogger(l), WithConfig(v))
|
||||
)
|
||||
go a.Serve(g)
|
||||
go a.Worker(g)
|
||||
a.Wait()
|
||||
globalContext := global.Context()
|
||||
app := newApp(globalContext, WithLogger(l), WithConfig(v))
|
||||
go app.Serve(globalContext)
|
||||
go app.Worker(globalContext)
|
||||
app.Wait()
|
||||
}
|
||||
|
||||
func newLogger(v *viper.Viper) *zap.Logger {
|
||||
options := []logger.Option{
|
||||
logger.WithLevel(v.GetString(cfgLoggerLevel)),
|
||||
logger.WithTraceLevel(v.GetString(cfgLoggerTraceLevel)),
|
||||
logger.WithFormat(v.GetString(cfgLoggerFormat)),
|
||||
logger.WithSamplingInitial(v.GetInt(cfgLoggerSamplingInitial)),
|
||||
logger.WithSamplingThereafter(v.GetInt(cfgLoggerSamplingThereafter)),
|
||||
logger.WithAppName(v.GetString(cfgApplicationName)),
|
||||
logger.WithAppVersion(v.GetString(cfgApplicationVersion)),
|
||||
}
|
||||
if v.GetBool(cfgLoggerNoCaller) {
|
||||
options = append(options, logger.WithoutCaller())
|
||||
}
|
||||
if v.GetBool(cfgLoggerNoDisclaimer) {
|
||||
options = append(options, logger.WithoutDisclaimer())
|
||||
}
|
||||
l, err := logger.New(options...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
|
286
neofs/client-plant.go
Normal file
286
neofs/client-plant.go
Normal file
|
@ -0,0 +1,286 @@
|
|||
package neofs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/client"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
objectCore "github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/transformer"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
nodeConnectionTimeout = 10 * time.Second
|
||||
maxObjectSize = uint64(1 << (20 + 6)) // 64MB
|
||||
)
|
||||
|
||||
type PutOptions struct {
|
||||
Client client.Client
|
||||
SessionToken *token.SessionToken
|
||||
BearerToken *token.BearerToken
|
||||
// ...
|
||||
ContainerID *container.ID
|
||||
OwnerID *owner.ID
|
||||
PrepareObjectOnsite bool
|
||||
Reader io.Reader
|
||||
}
|
||||
|
||||
type GetOptions struct {
|
||||
Client client.Client
|
||||
SessionToken *token.SessionToken
|
||||
BearerToken *token.BearerToken
|
||||
// ...
|
||||
ObjectAddress *object.Address
|
||||
Writer io.Writer
|
||||
}
|
||||
|
||||
type SearchOptions struct {
|
||||
Client client.Client
|
||||
SessionToken *token.SessionToken
|
||||
BearerToken *token.BearerToken
|
||||
// ...
|
||||
ContainerID *container.ID
|
||||
Attribute struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
}
|
||||
|
||||
type DeleteOptions struct {
|
||||
Client client.Client
|
||||
SessionToken *token.SessionToken
|
||||
BearerToken *token.BearerToken
|
||||
// ...
|
||||
ObjectAddress *object.Address
|
||||
}
|
||||
|
||||
type ObjectClient interface {
|
||||
Put(context.Context, *PutOptions) (*object.Address, error)
|
||||
Get(context.Context, *GetOptions) (*object.Object, error)
|
||||
Search(context.Context, *SearchOptions) ([]*object.ID, error)
|
||||
Delete(context.Context, *DeleteOptions) error
|
||||
}
|
||||
|
||||
type ClientPlant interface {
|
||||
GetReusableArtifacts(ctx context.Context) (client.Client, *token.SessionToken, error)
|
||||
Object() ObjectClient
|
||||
OwnerID() *owner.ID
|
||||
}
|
||||
|
||||
type objectClient struct {
|
||||
key *ecdsa.PrivateKey
|
||||
conn *grpc.ClientConn
|
||||
}
|
||||
|
||||
type neofsClient struct {
|
||||
key *ecdsa.PrivateKey
|
||||
ownerID *owner.ID
|
||||
conn *grpc.ClientConn
|
||||
}
|
||||
|
||||
func (cc *neofsClient) GetReusableArtifacts(ctx context.Context) (client.Client, *token.SessionToken, error) {
|
||||
c, err := client.New(client.WithDefaultPrivateKey(cc.key), client.WithGRPCConnection(cc.conn))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to create reusable neofs client")
|
||||
}
|
||||
st, err := c.CreateSession(ctx, math.MaxUint64)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to create reusable neofs session token")
|
||||
}
|
||||
return c, st, nil
|
||||
}
|
||||
|
||||
func (cc *neofsClient) Object() ObjectClient {
|
||||
return &objectClient{key: cc.key, conn: cc.conn}
|
||||
}
|
||||
|
||||
func (cc *neofsClient) OwnerID() *owner.ID {
|
||||
return cc.ownerID
|
||||
}
|
||||
|
||||
func NewClientPlant(ctx context.Context, address string, creds Credentials) (ClientPlant, error) {
|
||||
toctx, c := context.WithTimeout(ctx, nodeConnectionTimeout)
|
||||
defer c()
|
||||
conn, err := grpc.DialContext(toctx, address, grpc.WithInsecure(), grpc.WithBlock())
|
||||
if err != nil {
|
||||
if err == context.DeadlineExceeded {
|
||||
err = errors.New("failed to connect to neofs node")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &neofsClient{
|
||||
key: creds.PrivateKey(),
|
||||
ownerID: creds.Owner(),
|
||||
conn: conn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (oc *objectClient) Put(ctx context.Context, options *PutOptions) (*object.Address, error) {
|
||||
var (
|
||||
err error
|
||||
objectID *object.ID
|
||||
)
|
||||
address := object.NewAddress()
|
||||
if options.PrepareObjectOnsite {
|
||||
rawObject := objectCore.NewRaw()
|
||||
rawObject.SetContainerID(options.ContainerID)
|
||||
rawObject.SetOwnerID(options.OwnerID)
|
||||
ns := newNetworkState(ctx, options.Client)
|
||||
objectTarget := transformer.NewPayloadSizeLimiter(maxObjectSize, func() transformer.ObjectTarget {
|
||||
return transformer.NewFormatTarget(&transformer.FormatterParams{
|
||||
Key: oc.key,
|
||||
NextTarget: &remoteClientTarget{
|
||||
ctx: ctx,
|
||||
client: options.Client,
|
||||
},
|
||||
NetworkState: ns,
|
||||
})
|
||||
})
|
||||
if err = ns.LastError(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = objectTarget.WriteHeader(rawObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = io.Copy(objectTarget, options.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ids *transformer.AccessIdentifiers
|
||||
ids, err = objectTarget.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
address.SetObjectID(ids.SelfID())
|
||||
} else {
|
||||
rawObject := object.NewRaw()
|
||||
rawObject.SetContainerID(options.ContainerID)
|
||||
rawObject.SetOwnerID(options.OwnerID)
|
||||
ops := new(client.PutObjectParams).
|
||||
WithObject(rawObject.Object()).
|
||||
WithPayloadReader(options.Reader)
|
||||
objectID, err = options.Client.PutObject(
|
||||
ctx,
|
||||
ops,
|
||||
client.WithSession(options.SessionToken),
|
||||
client.WithBearer(options.BearerToken),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
address.SetObjectID(objectID)
|
||||
}
|
||||
address.SetContainerID(options.ContainerID)
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func (oc *objectClient) Get(ctx context.Context, options *GetOptions) (*object.Object, error) {
|
||||
var (
|
||||
err error
|
||||
obj *object.Object
|
||||
)
|
||||
ops := new(client.GetObjectParams).
|
||||
WithAddress(options.ObjectAddress).
|
||||
WithPayloadWriter(options.Writer)
|
||||
obj, err = options.Client.GetObject(
|
||||
ctx,
|
||||
ops,
|
||||
client.WithSession(options.SessionToken),
|
||||
client.WithBearer(options.BearerToken),
|
||||
)
|
||||
return obj, err
|
||||
}
|
||||
|
||||
func (oc *objectClient) Search(ctx context.Context, options *SearchOptions) ([]*object.ID, error) {
|
||||
sfs := object.NewSearchFilters()
|
||||
sfs.AddRootFilter()
|
||||
sfs.AddFilter(options.Attribute.Key, options.Attribute.Value, object.MatchStringEqual)
|
||||
sops := new(client.SearchObjectParams)
|
||||
sops.WithContainerID(options.ContainerID)
|
||||
sops.WithSearchFilters(sfs)
|
||||
return options.Client.SearchObject(
|
||||
ctx,
|
||||
sops,
|
||||
client.WithSession(options.SessionToken),
|
||||
client.WithBearer(options.BearerToken),
|
||||
)
|
||||
}
|
||||
|
||||
func (oc *objectClient) Delete(ctx context.Context, options *DeleteOptions) error {
|
||||
ops := new(client.DeleteObjectParams).WithAddress(options.ObjectAddress)
|
||||
err := options.Client.DeleteObject(
|
||||
ctx,
|
||||
ops,
|
||||
client.WithSession(options.SessionToken),
|
||||
client.WithBearer(options.BearerToken),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
type remoteClientTarget struct {
|
||||
ctx context.Context
|
||||
client client.Client
|
||||
object *object.Object
|
||||
payload []byte
|
||||
}
|
||||
|
||||
func (rct *remoteClientTarget) WriteHeader(raw *objectCore.RawObject) error {
|
||||
rct.object = raw.Object().SDK()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rct *remoteClientTarget) Write(p []byte) (n int, err error) {
|
||||
rct.payload = append(rct.payload, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (rct *remoteClientTarget) Close() (*transformer.AccessIdentifiers, error) {
|
||||
id, err := rct.client.PutObject(
|
||||
rct.ctx, new(client.PutObjectParams).
|
||||
WithObject(rct.object).
|
||||
WithPayloadReader(bytes.NewReader(rct.payload)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new(transformer.AccessIdentifiers).WithSelfID(id), nil
|
||||
}
|
||||
|
||||
type networkState struct {
|
||||
ctx context.Context
|
||||
client client.Client
|
||||
lastError error
|
||||
onError func(error)
|
||||
}
|
||||
|
||||
func newNetworkState(ctx context.Context, client client.Client) *networkState {
|
||||
ns := &networkState{
|
||||
ctx: ctx,
|
||||
client: client,
|
||||
}
|
||||
ns.onError = func(err error) { ns.lastError = err }
|
||||
return ns
|
||||
}
|
||||
|
||||
func (ns *networkState) LastError() error {
|
||||
return ns.lastError
|
||||
}
|
||||
|
||||
func (ns *networkState) CurrentEpoch() uint64 {
|
||||
ce, err := ns.client.NetworkInfo(ns.ctx)
|
||||
if err != nil {
|
||||
ns.onError(err)
|
||||
}
|
||||
return ce.CurrentEpoch()
|
||||
}
|
67
neofs/credentials.go
Normal file
67
neofs/credentials.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package neofs
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
)
|
||||
|
||||
type (
|
||||
// Credentials contains methods that needed to work with NeoFS.
|
||||
Credentials interface {
|
||||
WIF() string
|
||||
Owner() *owner.ID
|
||||
PublicKey() *ecdsa.PublicKey
|
||||
PrivateKey() *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
cred struct {
|
||||
key *ecdsa.PrivateKey
|
||||
owner *owner.ID
|
||||
wif string
|
||||
}
|
||||
)
|
||||
|
||||
// New creates an instance of Credentials through string representation of secret.
|
||||
// It allows passing WIF, path, hex-encoded and others.
|
||||
func NewCredentials(secret string) (Credentials, error) {
|
||||
key, err := crypto.LoadPrivateKey(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return setFromPrivateKey(key)
|
||||
}
|
||||
|
||||
// PrivateKey returns ecdsa.PrivateKey.
|
||||
func (c *cred) PrivateKey() *ecdsa.PrivateKey {
|
||||
return c.key
|
||||
}
|
||||
|
||||
// PublicKey returns ecdsa.PublicKey.
|
||||
func (c *cred) PublicKey() *ecdsa.PublicKey {
|
||||
return &c.key.PublicKey
|
||||
}
|
||||
|
||||
// Owner returns owner.ID.
|
||||
func (c *cred) Owner() *owner.ID {
|
||||
return c.owner
|
||||
}
|
||||
|
||||
// WIF returns string representation of WIF.
|
||||
func (c *cred) WIF() string {
|
||||
return c.wif
|
||||
}
|
||||
|
||||
func setFromPrivateKey(key *ecdsa.PrivateKey) (*cred, error) {
|
||||
wallet, err := owner.NEO3WalletFromPublicKey(&key.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ownerID := owner.NewIDFromNeo3Wallet(wallet)
|
||||
wif, err := crypto.WIFEncode(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cred{key: key, owner: ownerID, wif: wif}, nil
|
||||
}
|
39
pool/pool.go
Normal file
39
pool/pool.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package pool
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
// receive status of connection pool
|
||||
Status() error
|
||||
// worker should be run in goroutine to re-balancing
|
||||
Worker(context.Context)
|
||||
Connection(context.Context) (*grpc.ClientConn, error)
|
||||
Session(context.Context, *grpc.ClientConn) (*token.SessionToken, error)
|
||||
}
|
||||
|
||||
type pool struct{}
|
||||
|
||||
func (p *pool) Status() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pool) Worker(ctx context.Context) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (p *pool) Connection(ctx context.Context) (*grpc.ClientConn, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (p *pool) Session(ctx context.Context, conn *grpc.ClientConn) (*token.SessionToken, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func New() Client {
|
||||
return &pool{}
|
||||
}
|
101
receive.go
101
receive.go
|
@ -9,9 +9,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
sdk "github.com/nspcc-dev/cdn-sdk"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-http-gate/neofs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
|
@ -31,7 +31,7 @@ type (
|
|||
*fasthttp.RequestCtx
|
||||
|
||||
log *zap.Logger
|
||||
obj sdk.ObjectClient
|
||||
obj neofs.ObjectClient
|
||||
}
|
||||
|
||||
objectIDs []*object.ID
|
||||
|
@ -49,40 +49,38 @@ func (d *detector) Write(data []byte) (int, error) {
|
|||
return d.Writer.Write(data)
|
||||
}
|
||||
|
||||
func (r *request) receiveFile(address *object.Address) {
|
||||
func (r *request) receiveFile(options *neofs.GetOptions) {
|
||||
var (
|
||||
err error
|
||||
dis = "inline"
|
||||
start = time.Now()
|
||||
filename string
|
||||
)
|
||||
|
||||
if err = checkAndPropagateBearerToken(r.RequestCtx); err != nil {
|
||||
r.log.Error("could not fetch bearer token", zap.Error(err))
|
||||
r.Error("could not fetch bearer token", fasthttp.StatusBadRequest)
|
||||
if err = storeBearerToken(r.RequestCtx); err != nil {
|
||||
r.log.Error("could not fetch and store bearer token", zap.Error(err))
|
||||
r.Error("could not fetch and store bearer token", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
writer := newDetector(r.Response.BodyWriter())
|
||||
obj, err := r.obj.Get(r, address, sdk.WithGetWriter(writer))
|
||||
// obj, err := r.obj.Get(r, address, sdk.WithGetWriter(writer))
|
||||
options.Writer = writer
|
||||
obj, err := r.obj.Get(r.RequestCtx, options)
|
||||
if err != nil {
|
||||
r.log.Error("could not receive object",
|
||||
r.log.Error(
|
||||
"could not receive object",
|
||||
zap.Stringer("elapsed", time.Since(start)),
|
||||
zap.Error(err))
|
||||
|
||||
zap.Error(err),
|
||||
)
|
||||
var (
|
||||
msg = errors.Wrap(err, "could not receive object").Error()
|
||||
code = fasthttp.StatusBadRequest
|
||||
)
|
||||
|
||||
if st, ok := status.FromError(errors.Cause(err)); ok && st != nil {
|
||||
if st.Code() == codes.NotFound {
|
||||
code = fasthttp.StatusNotFound
|
||||
}
|
||||
|
||||
msg = st.Message()
|
||||
}
|
||||
|
||||
r.Error(msg, code)
|
||||
return
|
||||
}
|
||||
|
@ -139,68 +137,79 @@ func (a *app) request(ctx *fasthttp.RequestCtx, log *zap.Logger) *request {
|
|||
RequestCtx: ctx,
|
||||
|
||||
log: log,
|
||||
obj: a.cli.Object(),
|
||||
obj: a.plant.Object(),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *app) byAddress(c *fasthttp.RequestCtx) {
|
||||
var (
|
||||
err error
|
||||
adr = object.NewAddress()
|
||||
cid, _ = c.UserValue("cid").(string)
|
||||
oid, _ = c.UserValue("oid").(string)
|
||||
val = strings.Join([]string{cid, oid}, "/")
|
||||
log = a.log.With(
|
||||
zap.String("cid", cid),
|
||||
zap.String("oid", oid))
|
||||
err error
|
||||
address = object.NewAddress()
|
||||
cid, _ = c.UserValue("cid").(string)
|
||||
oid, _ = c.UserValue("oid").(string)
|
||||
val = strings.Join([]string{cid, oid}, "/")
|
||||
log = a.log.With(zap.String("cid", cid), zap.String("oid", oid))
|
||||
)
|
||||
|
||||
if err = adr.Parse(val); err != nil {
|
||||
if err = address.Parse(val); err != nil {
|
||||
log.Error("wrong object address", zap.Error(err))
|
||||
c.Error("wrong object address", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
a.request(c, log).receiveFile(adr)
|
||||
// TODO: Take this from a sync-pool.
|
||||
getOpts := new(neofs.GetOptions)
|
||||
getOpts.Client = a.getOperations.client
|
||||
getOpts.SessionToken = a.getOperations.sessionToken
|
||||
getOpts.ObjectAddress = address
|
||||
getOpts.Writer = nil
|
||||
a.request(c, log).receiveFile(getOpts)
|
||||
}
|
||||
|
||||
func (a *app) byAttribute(c *fasthttp.RequestCtx) {
|
||||
var (
|
||||
err error
|
||||
ids []*object.ID
|
||||
cid = container.NewID()
|
||||
adr = object.NewAddress()
|
||||
sCID, _ = c.UserValue("cid").(string)
|
||||
scid, _ = c.UserValue("cid").(string)
|
||||
key, _ = c.UserValue("attr_key").(string)
|
||||
val, _ = c.UserValue("attr_val").(string)
|
||||
|
||||
log = a.log.With(
|
||||
zap.String("cid", sCID),
|
||||
zap.String("attr_key", key),
|
||||
zap.String("attr_val", val))
|
||||
log = a.log.With(zap.String("cid", scid), zap.String("attr_key", key), zap.String("attr_val", val))
|
||||
)
|
||||
|
||||
if err = cid.Parse(sCID); err != nil {
|
||||
cid := container.NewID()
|
||||
if err = cid.Parse(scid); err != nil {
|
||||
log.Error("wrong container id", zap.Error(err))
|
||||
c.Error("wrong container id", fasthttp.StatusBadRequest)
|
||||
return
|
||||
} else if ids, err = a.cli.Object().Search(c, cid, sdk.SearchRootObjects(), sdk.SearchByAttribute(key, val)); err != nil {
|
||||
// } else if ids, err = a.cli.Object().Search(c, cid, sdk.SearchRootObjects(), sdk.SearchByAttribute(key, val)); err != nil {
|
||||
}
|
||||
// TODO: Take this from a sync-pool.
|
||||
searchOpts := new(neofs.SearchOptions)
|
||||
searchOpts.Client = a.getOperations.client
|
||||
searchOpts.SessionToken = a.getOperations.sessionToken
|
||||
searchOpts.BearerToken = nil
|
||||
searchOpts.ContainerID = cid
|
||||
searchOpts.Attribute.Key = key
|
||||
searchOpts.Attribute.Value = val
|
||||
var ids []*object.ID
|
||||
if ids, err = a.plant.Object().Search(c, searchOpts); err != nil {
|
||||
log.Error("something went wrong", zap.Error(err))
|
||||
c.Error("something went wrong", fasthttp.StatusBadRequest)
|
||||
return
|
||||
} else if len(ids) == 0 {
|
||||
log.Debug("object not found")
|
||||
c.Error("not found", fasthttp.StatusNotFound)
|
||||
c.Error("object not found", fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if len(ids) > 1 {
|
||||
log.Debug("found multiple objects",
|
||||
zap.Strings("object_ids", objectIDs(ids).Slice()),
|
||||
zap.Stringer("show_object_id", ids[0]))
|
||||
}
|
||||
|
||||
adr.SetContainerID(cid)
|
||||
adr.SetObjectID(ids[0])
|
||||
a.request(c, log).receiveFile(adr)
|
||||
address := object.NewAddress()
|
||||
address.SetContainerID(cid)
|
||||
address.SetObjectID(ids[0])
|
||||
// TODO: Take this from a sync-pool.
|
||||
getOpts := new(neofs.GetOptions)
|
||||
getOpts.Client = a.getOperations.client
|
||||
getOpts.SessionToken = a.getOperations.sessionToken
|
||||
getOpts.ObjectAddress = address
|
||||
getOpts.Writer = nil
|
||||
a.request(c, log).receiveFile(getOpts)
|
||||
}
|
||||
|
|
12
settings.go
12
settings.go
|
@ -79,11 +79,9 @@ var ignore = map[string]struct{}{
|
|||
cfgApplicationName: {},
|
||||
cfgApplicationVersion: {},
|
||||
cfgApplicationBuildTime: {},
|
||||
|
||||
cfgPeers: {},
|
||||
|
||||
cmdHelp: {},
|
||||
cmdVersion: {},
|
||||
cfgPeers: {},
|
||||
cmdHelp: {},
|
||||
cmdVersion: {},
|
||||
}
|
||||
|
||||
func (empty) Read([]byte) (int, error) { return 0, io.EOF }
|
||||
|
@ -106,14 +104,14 @@ func settings() *viper.Viper {
|
|||
help := flags.BoolP(cmdHelp, "h", false, "show help")
|
||||
version := flags.BoolP(cmdVersion, "v", false, "show version")
|
||||
|
||||
flags.String(cmdNeoFSKey, "", `"Path to private key file, hex string or wif`)
|
||||
flags.String(cmdNeoFSKey, "", `path to private key file, hex string or wif`)
|
||||
|
||||
flags.Bool(cmdVerbose, false, "debug gRPC connections")
|
||||
flags.Duration(cfgConTimeout, defaultConnectTimeout, "gRPC connect timeout")
|
||||
flags.Duration(cfgReqTimeout, defaultRequestTimeout, "gRPC request timeout")
|
||||
flags.Duration(cfgRebalance, defaultRebalanceTimer, "gRPC connection rebalance timer")
|
||||
|
||||
flags.String(cfgListenAddress, "0.0.0.0:8082", "HTTP Gateway listen address")
|
||||
flags.String(cfgListenAddress, "0.0.0.0:8082", "address to listen")
|
||||
peers := flags.StringArrayP(cfgPeers, "p", nil, "NeoFS nodes")
|
||||
|
||||
// set prefers:
|
||||
|
|
69
upload.go
69
upload.go
|
@ -7,10 +7,11 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
sdk "github.com/nspcc-dev/cdn-sdk"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||||
"github.com/nspcc-dev/neofs-http-gate/neofs"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -29,18 +30,17 @@ func newPutResponse(addr *object.Address) *putResponse {
|
|||
}
|
||||
}
|
||||
|
||||
func (pr *putResponse) Encode(w io.Writer) error {
|
||||
func (pr *putResponse) encode(w io.Writer) error {
|
||||
enc := json.NewEncoder(w)
|
||||
enc.SetIndent("", "\t")
|
||||
return enc.Encode(pr)
|
||||
}
|
||||
|
||||
func (a *app) fetchOwner(ctx context.Context) *owner.ID {
|
||||
if tkn, err := sdk.BearerToken(ctx); err == nil && tkn != nil {
|
||||
return tkn.Issuer()
|
||||
func (a *app) fetchOwnerAndBearerToken(ctx context.Context) (*owner.ID, *token.BearerToken) {
|
||||
if token, err := loadBearerToken(ctx); err == nil && token != nil {
|
||||
return token.Issuer(), token
|
||||
}
|
||||
|
||||
return a.cli.Owner()
|
||||
return a.plant.OwnerID(), nil
|
||||
}
|
||||
|
||||
func (a *app) upload(c *fasthttp.RequestCtx) {
|
||||
|
@ -50,94 +50,93 @@ func (a *app) upload(c *fasthttp.RequestCtx) {
|
|||
addr *object.Address
|
||||
cid = container.NewID()
|
||||
sCID, _ = c.UserValue("cid").(string)
|
||||
|
||||
log = a.log.With(zap.String("cid", sCID))
|
||||
log = a.log.With(zap.String("cid", sCID))
|
||||
)
|
||||
|
||||
if err = checkAndPropagateBearerToken(c); err != nil {
|
||||
if err = storeBearerToken(c); err != nil {
|
||||
log.Error("could not fetch bearer token", zap.Error(err))
|
||||
c.Error("could not fetch bearer token", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err = cid.Parse(sCID); err != nil {
|
||||
log.Error("wrong container id", zap.Error(err))
|
||||
c.Error("wrong container id", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// if temporary reader can be closed - close it
|
||||
if file == nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug("close temporary multipart/form file",
|
||||
err := file.Close()
|
||||
log.Debug(
|
||||
"close temporary multipart/form file",
|
||||
zap.Stringer("address", addr),
|
||||
zap.String("filename", file.FileName()),
|
||||
zap.Error(file.Close()))
|
||||
zap.Error(err),
|
||||
)
|
||||
}()
|
||||
|
||||
boundary := string(c.Request.Header.MultipartFormBoundary())
|
||||
if file, err = fetchMultipartFile(a.log, c.RequestBodyStream(), boundary); err != nil {
|
||||
log.Error("could not receive multipart/form", zap.Error(err))
|
||||
c.Error("could not receive multipart/form: "+err.Error(), fasthttp.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
filtered := filterHeaders(a.log, &c.Request.Header)
|
||||
attributes := make([]*object.Attribute, 0, len(filtered))
|
||||
|
||||
// prepares attributes from filtered headers
|
||||
for key, val := range filtered {
|
||||
attribute := object.NewAttribute()
|
||||
attribute.SetKey(key)
|
||||
attribute.SetValue(val)
|
||||
|
||||
attributes = append(attributes, attribute)
|
||||
}
|
||||
|
||||
// sets FileName attribute if it wasn't set from header
|
||||
if _, ok := filtered[object.AttributeFileName]; !ok {
|
||||
filename := object.NewAttribute()
|
||||
filename.SetKey(object.AttributeFileName)
|
||||
filename.SetValue(file.FileName())
|
||||
|
||||
attributes = append(attributes, filename)
|
||||
}
|
||||
|
||||
// sets Timestamp attribute if it wasn't set from header and enabled by settings
|
||||
if _, ok := filtered[object.AttributeTimestamp]; !ok && a.enableDefaultTimestamp {
|
||||
timestamp := object.NewAttribute()
|
||||
timestamp.SetKey(object.AttributeTimestamp)
|
||||
timestamp.SetValue(strconv.FormatInt(time.Now().Unix(), 10))
|
||||
|
||||
attributes = append(attributes, timestamp)
|
||||
}
|
||||
|
||||
oid, bt := a.fetchOwnerAndBearerToken(c)
|
||||
// prepares new object and fill it
|
||||
raw := object.NewRaw()
|
||||
raw.SetContainerID(cid)
|
||||
raw.SetOwnerID(a.fetchOwner(c))
|
||||
raw.SetOwnerID(oid)
|
||||
raw.SetAttributes(attributes...)
|
||||
|
||||
// tries to put file into NeoFS or throw error
|
||||
if addr, err = a.cli.Object().Put(c, raw.Object(), sdk.WithPutReader(file)); err != nil {
|
||||
log.Error("could not store file in NeoFS", zap.Error(err))
|
||||
c.Error("could not store file in NeoFS", fasthttp.StatusBadRequest)
|
||||
|
||||
// if addr, err = a.plant.Object().Put(c, raw.Object(), sdk.WithPutReader(file)); err != nil {
|
||||
// TODO: Take this from a sync pool.
|
||||
putOpts := new(neofs.PutOptions)
|
||||
putOpts.Client, putOpts.SessionToken, err = a.plant.GetReusableArtifacts(c)
|
||||
if err != nil {
|
||||
log.Error("failed to get neofs client's reusable artifacts", zap.Error(err))
|
||||
c.Error("failed to get neofs client's reusable artifacts", fasthttp.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
putOpts.BearerToken = bt
|
||||
putOpts.ContainerID = cid
|
||||
putOpts.OwnerID = oid
|
||||
putOpts.PrepareObjectOnsite = false
|
||||
putOpts.Reader = file
|
||||
if addr, err = a.plant.Object().Put(c, putOpts); err != nil {
|
||||
log.Error("could not store file in NeoFS", zap.Error(err))
|
||||
c.Error("could not store file in NeoFS", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// tries to return response, otherwise, if something went wrong throw error
|
||||
if err = newPutResponse(addr).Encode(c); err != nil {
|
||||
if err = newPutResponse(addr).encode(c); err != nil {
|
||||
log.Error("could not prepare response", zap.Error(err))
|
||||
c.Error("could not prepare response", fasthttp.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// reports status code and content type
|
||||
c.Response.SetStatusCode(fasthttp.StatusOK)
|
||||
c.Response.Header.SetContentType(jsonHeader)
|
||||
|
|
Loading…
Reference in a new issue