From 0ad0d9bf789f107473851df14dbc06b5dabe9961 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 30 Jul 2024 14:00:29 +0200 Subject: [PATCH 1/2] feat(reva): bump reva Signed-off-by: jkoberg --- changelog/unreleased/bump-reva.md | 3 +- go.mod | 3 +- go.sum | 8 +- .../http/services/owncloud/ocdav/copy.go | 30 +- .../http/services/owncloud/ocdav/tus.go | 2 +- .../v2/pkg/ocm/storage/received/upload.go | 4 +- .../cs3org/reva/v2/pkg/rgrpc/keepalive.go | 24 + .../cs3org/reva/v2/pkg/rgrpc/rgrpc.go | 4 + .../v2/pkg/rhttp/datatx/manager/tus/tus.go | 36 +- .../reva/v2/pkg/storage/fs/cephfs/upload.go | 4 +- .../reva/v2/pkg/storage/fs/hello/hello.go | 241 +++ .../v2/pkg/storage/fs/hello/unimplemented.go | 198 +++ .../reva/v2/pkg/storage/fs/loader/loader.go | 1 + .../v2/pkg/storage/fs/owncloudsql/upload.go | 4 +- .../reva/v2/pkg/storage/fs/posix/posix.go | 2 +- .../cs3org/reva/v2/pkg/storage/storage.go | 142 +- .../cs3org/reva/v2/pkg/storage/uploads.go | 2 +- .../utils/decomposedfs/decomposedfs.go | 2 +- .../pkg/storage/utils/decomposedfs/upload.go | 2 +- .../utils/decomposedfs/upload/session.go | 2 +- .../utils/decomposedfs/upload/store.go | 2 +- .../utils/decomposedfs/upload/upload.go | 4 +- .../v2/pkg/storage/utils/localfs/upload.go | 4 +- .../storage/utils/middleware/middleware.go | 2 +- vendor/github.com/tus/tusd/v2/LICENSE.txt | 19 + .../tus/tusd/v2/pkg/handler/body_reader.go | 132 ++ .../tus/tusd/v2/pkg/handler/composer.go | 87 + .../tus/tusd/v2/pkg/handler/composer.mgo | 74 + .../tus/tusd/v2/pkg/handler/config.go | 195 ++ .../tus/tusd/v2/pkg/handler/context.go | 102 ++ .../tus/tusd/v2/pkg/handler/datastore.go | 190 ++ .../github.com/tus/tusd/v2/pkg/handler/doc.go | 69 + .../tus/tusd/v2/pkg/handler/error.go | 37 + .../tus/tusd/v2/pkg/handler/handler.go | 77 + .../tus/tusd/v2/pkg/handler/hooks.go | 48 + .../tus/tusd/v2/pkg/handler/http.go | 79 + .../tus/tusd/v2/pkg/handler/metrics.go | 132 ++ .../tusd/v2/pkg/handler/unrouted_handler.go | 1569 +++++++++++++++++ vendor/golang.org/x/exp/slog/attr.go | 102 ++ vendor/golang.org/x/exp/slog/doc.go | 316 ++++ vendor/golang.org/x/exp/slog/handler.go | 577 ++++++ .../x/exp/slog/internal/buffer/buffer.go | 84 + .../x/exp/slog/internal/ignorepc.go | 9 + vendor/golang.org/x/exp/slog/json_handler.go | 336 ++++ vendor/golang.org/x/exp/slog/level.go | 201 +++ vendor/golang.org/x/exp/slog/logger.go | 343 ++++ vendor/golang.org/x/exp/slog/noplog.bench | 36 + vendor/golang.org/x/exp/slog/record.go | 207 +++ vendor/golang.org/x/exp/slog/text_handler.go | 161 ++ vendor/golang.org/x/exp/slog/value.go | 456 +++++ vendor/golang.org/x/exp/slog/value_119.go | 53 + vendor/golang.org/x/exp/slog/value_120.go | 39 + vendor/modules.txt | 9 +- 53 files changed, 6396 insertions(+), 69 deletions(-) create mode 100644 vendor/github.com/cs3org/reva/v2/pkg/rgrpc/keepalive.go create mode 100644 vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go create mode 100644 vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go create mode 100644 vendor/github.com/tus/tusd/v2/LICENSE.txt create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/composer.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/composer.mgo create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/config.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/context.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/datastore.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/doc.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/error.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/handler.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/hooks.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/http.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/metrics.go create mode 100644 vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go create mode 100644 vendor/golang.org/x/exp/slog/attr.go create mode 100644 vendor/golang.org/x/exp/slog/doc.go create mode 100644 vendor/golang.org/x/exp/slog/handler.go create mode 100644 vendor/golang.org/x/exp/slog/internal/buffer/buffer.go create mode 100644 vendor/golang.org/x/exp/slog/internal/ignorepc.go create mode 100644 vendor/golang.org/x/exp/slog/json_handler.go create mode 100644 vendor/golang.org/x/exp/slog/level.go create mode 100644 vendor/golang.org/x/exp/slog/logger.go create mode 100644 vendor/golang.org/x/exp/slog/noplog.bench create mode 100644 vendor/golang.org/x/exp/slog/record.go create mode 100644 vendor/golang.org/x/exp/slog/text_handler.go create mode 100644 vendor/golang.org/x/exp/slog/value.go create mode 100644 vendor/golang.org/x/exp/slog/value_119.go create mode 100644 vendor/golang.org/x/exp/slog/value_120.go diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index e2d1ab5186..ffb06ca615 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -1,3 +1,4 @@ Enhancement: Bump reva -https://github.com/owncloud/ocis/pull/9715 \ No newline at end of file +https://github.com/owncloud/ocis/pull/9714 +https://github.com/owncloud/ocis/pull/9715 diff --git a/go.mod b/go.mod index ffeab5eb9f..dbc22712f9 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.11.0 github.com/cs3org/go-cs3apis v0.0.0-20240724121416-062c4e3046cb - github.com/cs3org/reva/v2 v2.22.1-0.20240730105121-548644c31544 + github.com/cs3org/reva/v2 v2.22.1-0.20240806075425-8bcdd93dfa20 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 @@ -323,6 +323,7 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect github.com/trustelem/zxcvbn v1.0.1 // indirect + github.com/tus/tusd/v2 v2.4.0 // indirect github.com/wk8/go-ordered-map v1.0.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect diff --git a/go.sum b/go.sum index 28d3f67d18..3f1fe00df2 100644 --- a/go.sum +++ b/go.sum @@ -766,6 +766,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/Acconut/go-httptest-recorder v1.0.0 h1:TAv2dfnqp/l+SUvIaMAUK4GeN4+wqb6KZsFFFTGhoJg= +github.com/Acconut/go-httptest-recorder v1.0.0/go.mod h1:CwQyhTH1kq/gLyWiRieo7c0uokpu3PXeyF/nZjUNtmM= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= @@ -1024,8 +1026,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20240724121416-062c4e3046cb h1:KmYZDReplv/yfwc1LNYpDcVhVujC3Pasv6WjXx1haSU= github.com/cs3org/go-cs3apis v0.0.0-20240724121416-062c4e3046cb/go.mod h1:yyP8PRo0EZou3nSH7H4qjlzQwaydPeIRNgX50npQHpE= -github.com/cs3org/reva/v2 v2.22.1-0.20240730105121-548644c31544 h1:cBqx8oou5aXM9SqiG96bYGBD4akYwecPoopsFva51yI= -github.com/cs3org/reva/v2 v2.22.1-0.20240730105121-548644c31544/go.mod h1:R6OO/ZPMr8MivSiESfk7pUfsdXdr709L8kJErLgqvDI= +github.com/cs3org/reva/v2 v2.22.1-0.20240806075425-8bcdd93dfa20 h1:GVxOUoabZQ5kgeS3oBOHZZn+sY0Sb5VOyhjsEFttJ4g= +github.com/cs3org/reva/v2 v2.22.1-0.20240806075425-8bcdd93dfa20/go.mod h1:l/llk1KaiB/XiJYfk+gznzkXZqVv+TbxJKgDbpti444= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -2056,6 +2058,8 @@ github.com/trustelem/zxcvbn v1.0.1 h1:mp4JFtzdDYGj9WYSD3KQSkwwUumWNFzXaAjckaTYps github.com/trustelem/zxcvbn v1.0.1/go.mod h1:zonUyKeh7sw6psPf/e3DtRqkRyZvAbOfjNz/aO7YQ5s= github.com/tus/tusd v1.13.0 h1:W7rtb1XPSpde/GPZAgdfUS3vus2Jt2KmckS6OUd3CU8= github.com/tus/tusd v1.13.0/go.mod h1:1tX4CDGlx8koHGFJdSaJ5ybUIm2NeVloJgZEPSKRcQA= +github.com/tus/tusd/v2 v2.4.0 h1:SpXmzQPCtiedkhNPl5Gn4ApQXLChPLdYrWbZQI42uJE= +github.com/tus/tusd/v2 v2.4.0/go.mod h1:X+fc/MU+T+NDD5gNJHHE58jo6cQj1vlMstlT16+xlrg= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go index c009e59789..cccc3c2f08 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go @@ -127,7 +127,7 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string) return } - cp := s.prepareCopy(ctx, w, r, spacelookup.MakeRelativeReference(srcSpace, src, false), spacelookup.MakeRelativeReference(dstSpace, dst, false), &sublog) + cp := s.prepareCopy(ctx, w, r, spacelookup.MakeRelativeReference(srcSpace, src, false), spacelookup.MakeRelativeReference(dstSpace, dst, false), &sublog, dstSpace.GetRoot().GetStorageId() == utils.ShareStorageProviderID) if cp == nil { return } @@ -362,7 +362,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s return } - cp := s.prepareCopy(ctx, w, r, &srcRef, &dstRef, &sublog) + cp := s.prepareCopy(ctx, w, r, &srcRef, &dstRef, &sublog, dstRef.GetResourceId().GetStorageId() == utils.ShareStorageProviderID) if cp == nil { return } @@ -552,7 +552,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele return nil } -func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, log *zerolog.Logger) *copy { +func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, log *zerolog.Logger, destInShareJail bool) *copy { isChild, err := s.referenceIsChildOf(ctx, s.gatewaySelector, dstRef, srcRef) if err != nil { switch err.(type) { @@ -675,11 +675,6 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re if dstStatRes.Status.Code == rpc.Code_CODE_OK { successCode = http.StatusNoContent // 204 if target already existed, see https://tools.ietf.org/html/rfc4918#section-9.8.5 - if utils.IsSpaceRoot(dstStatRes.GetInfo()) { - log.Error().Msg("overwriting is not allowed") - w.WriteHeader(http.StatusBadRequest) - return nil - } if !overwrite { log.Warn().Bool("overwrite", overwrite).Msg("dst already exists") w.WriteHeader(http.StatusPreconditionFailed) @@ -688,10 +683,29 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re errors.HandleWebdavError(log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5 return nil } + + if utils.IsSpaceRoot(dstStatRes.GetInfo()) { + log.Error().Msg("overwriting is not allowed") + w.WriteHeader(http.StatusBadRequest) + return nil + } + // delete existing tree when overwriting a directory or replacing a file with a directory if dstStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER || (dstStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_FILE && srcStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER) { + + // we must not allow to override mountpoints - so we check if we have access to the parent. If not this is a mountpoint + if destInShareJail { + dir, file := filepath.Split(dstRef.GetPath()) + if dir == "/" || dir == "" || file == "" { + log.Error().Msg("must not overwrite mount points") + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte("must not overwrite mount points")) + return nil + } + } + delReq := &provider.DeleteRequest{Ref: dstRef} delRes, err := client.Delete(ctx, delReq) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go index 2b85a1d231..0851a7ecb5 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go @@ -42,7 +42,7 @@ import ( "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/rs/zerolog" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" "go.opentelemetry.io/otel/propagation" ) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/upload.go index b2e39e5a79..951bec8992 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/upload.go @@ -35,7 +35,7 @@ import ( "strings" "github.com/google/uuid" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -266,7 +266,7 @@ func (u *upload) GetInfo(ctx context.Context) (tusd.FileInfo, error) { return u.Info, nil } -func (u *upload) GetReader(ctx context.Context) (io.Reader, error) { +func (u *upload) GetReader(ctx context.Context) (io.ReadCloser, error) { return os.Open(u.BinPath()) } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/keepalive.go b/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/keepalive.go new file mode 100644 index 0000000000..1baab9efb2 --- /dev/null +++ b/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/keepalive.go @@ -0,0 +1,24 @@ +package rgrpc + +import ( + "math" + "os" + "time" +) + +const ( + _serverMaxConnectionAgeEnv = "GRPC_MAX_CONNECTION_AGE" + + // same default as grpc + infinity = time.Duration(math.MaxInt64) + _defaultMaxConnectionAge = infinity +) + +// GetMaxConnectionAge returns the maximum grpc connection age. +func GetMaxConnectionAge() time.Duration { + d, err := time.ParseDuration(os.Getenv(_serverMaxConnectionAgeEnv)) + if err != nil { + return _defaultMaxConnectionAge + } + return d +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/rgrpc.go b/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/rgrpc.go index 1085a5e034..c04bedc3da 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/rgrpc.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rgrpc/rgrpc.go @@ -42,6 +42,7 @@ import ( "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/keepalive" "google.golang.org/grpc/reflection" ) @@ -245,6 +246,9 @@ func (s *Server) registerServices() error { if s.conf.TLSSettings.tlsConfig != nil { opts = append(opts, grpc.Creds(credentials.NewTLS(s.conf.TLSSettings.tlsConfig))) } + opts = append(opts, grpc.KeepaliveParams(keepalive.ServerParameters{ + MaxConnectionAge: GetMaxConnectionAge(), // this forces clients to reconnect after 30 seconds, triggering a new DNS lookup to pick up new IPs + })) grpcServer := grpc.NewServer(opts...) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go index f3ddd77c70..829440ecaf 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go @@ -20,13 +20,13 @@ package tus import ( "context" - "log" "net/http" "path" "regexp" "github.com/pkg/errors" - tusd "github.com/tus/tusd/pkg/handler" + "github.com/rs/zerolog" + tusd "github.com/tus/tusd/v2/pkg/handler" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net" @@ -39,6 +39,7 @@ import ( "github.com/cs3org/reva/v2/pkg/storage" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/mitchellh/mapstructure" + "golang.org/x/exp/slog" ) func init() { @@ -99,7 +100,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { config := tusd.Config{ StoreComposer: composer, NotifyCompleteUploads: true, - Logger: log.New(appctx.GetLogger(context.Background()), "", 0), + Logger: slog.New(tusdLogger{log: appctx.GetLogger(context.Background())}), // Note: this is a noop logger } if m.conf.CorsEnabled { @@ -222,3 +223,32 @@ func setHeaders(fs storage.FS, w http.ResponseWriter, r *http.Request) { } w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(resourceid)) } + +// tusdLogger is a logger implementation (slog) for tusd that uses zerolog. +type tusdLogger struct { + log *zerolog.Logger +} + +// Handle handles the record +func (l tusdLogger) Handle(_ context.Context, r slog.Record) error { + switch r.Level { + case slog.LevelDebug: + l.log.Debug().Msg(r.Message) + case slog.LevelInfo: + l.log.Info().Msg(r.Message) + case slog.LevelWarn: + l.log.Warn().Msg(r.Message) + case slog.LevelError: + l.log.Error().Msg(r.Message) + } + return nil +} + +// Enabled returns true +func (l tusdLogger) Enabled(_ context.Context, _ slog.Level) bool { return true } + +// WithAttrs is not implemented +func (l tusdLogger) WithAttrs(_ []slog.Attr) slog.Handler { return l } + +// WithGroup is not implemented +func (l tusdLogger) WithGroup(_ string) slog.Handler { return l } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/upload.go index 031508cbea..4243957153 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/upload.go @@ -39,7 +39,7 @@ import ( "github.com/cs3org/reva/v2/pkg/utils" "github.com/google/uuid" "github.com/pkg/errors" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" ) func (fs *cephfs) Upload(ctx context.Context, req storage.UploadRequest, uff storage.UploadFinishedFunc) (*provider.ResourceInfo, error) { @@ -299,7 +299,7 @@ func (upload *fileUpload) GetInfo(ctx context.Context) (tusd.FileInfo, error) { } // GetReader returns an io.Reader for the upload -func (upload *fileUpload) GetReader(ctx context.Context) (file io.Reader, err error) { +func (upload *fileUpload) GetReader(ctx context.Context) (file io.ReadCloser, err error) { user := upload.fs.makeUser(upload.ctx) user.op(func(cv *cacheVal) { file, err = cv.mount.Open(upload.binPath, os.O_RDONLY, 0) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go new file mode 100644 index 0000000000..0a9d72e2d0 --- /dev/null +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go @@ -0,0 +1,241 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package hello + +import ( + "bytes" + "context" + "crypto/md5" + "encoding/binary" + "fmt" + "io" + "strings" + "time" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/errtypes" + "github.com/cs3org/reva/v2/pkg/events" + "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/fs/registry" + "github.com/cs3org/reva/v2/pkg/utils" +) + +func init() { + registry.Register("hello", New) +} + +type hellofs struct { + bootTime time.Time +} + +const ( + storageid = "hello-storage-id" + spaceid = "hello-space-id" + rootid = "hello-root-id" + fileid = "hello-file-id" + filename = "Hello world.txt" + content = "Hello world!" +) + +func (fs *hellofs) space(withRoot bool) *provider.StorageSpace { + s := &provider.StorageSpace{ + Id: &provider.StorageSpaceId{OpaqueId: spaceid}, + Root: &provider.ResourceId{ + StorageId: storageid, + SpaceId: spaceid, + OpaqueId: rootid, + }, + Quota: &provider.Quota{ + QuotaMaxBytes: uint64(len(content)), + QuotaMaxFiles: 1, + }, + Name: "Hello Space", + SpaceType: "project", + RootInfo: fs.rootInfo(), + Mtime: utils.TimeToTS(fs.bootTime), + } + // FIXME move this to the CS3 API + s.Opaque = utils.AppendPlainToOpaque(s.Opaque, "spaceAlias", "project/hello") + + if withRoot { + s.RootInfo = fs.rootInfo() + } + return s +} + +func (fs *hellofs) rootInfo() *provider.ResourceInfo { + return &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_CONTAINER, + Id: &provider.ResourceId{ + StorageId: storageid, + SpaceId: spaceid, + OpaqueId: rootid, + }, + Etag: calcEtag(fs.bootTime, rootid), + MimeType: "httpd/unix-directory", + Mtime: utils.TimeToTS(fs.bootTime), + Path: ".", + PermissionSet: &provider.ResourcePermissions{ + GetPath: true, + GetQuota: true, + InitiateFileDownload: true, + Stat: true, + ListContainer: true, + }, + Size: uint64(len(content)), + } +} + +func (fs *hellofs) fileInfo() *provider.ResourceInfo { + return &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Id: &provider.ResourceId{ + StorageId: storageid, + SpaceId: spaceid, + OpaqueId: fileid, + }, + Etag: calcEtag(fs.bootTime, fileid), + MimeType: "text/plain", + Mtime: utils.TimeToTS(fs.bootTime), + Path: ".", + PermissionSet: &provider.ResourcePermissions{ + GetPath: true, + GetQuota: true, + InitiateFileDownload: true, + Stat: true, + ListContainer: true, + }, + Size: uint64(len(content)), + ParentId: &provider.ResourceId{ + StorageId: storageid, + SpaceId: spaceid, + OpaqueId: rootid, + }, + Name: filename, + Space: fs.space(false), + } +} + +func calcEtag(t time.Time, nodeid string) string { + h := md5.New() + _ = binary.Write(h, binary.BigEndian, t.Unix()) + _ = binary.Write(h, binary.BigEndian, int64(t.Nanosecond())) + _ = binary.Write(h, binary.BigEndian, []byte(nodeid)) + etag := fmt.Sprintf(`"%x"`, h.Sum(nil)) + return fmt.Sprintf("\"%s\"", strings.Trim(etag, "\"")) +} + +// New returns an implementation to of the storage.FS interface that talks to +// a local filesystem with user homes disabled. +func New(_ map[string]interface{}, _ events.Stream) (storage.FS, error) { + return &hellofs{ + bootTime: time.Now(), + }, nil +} + +// Shutdown is called when the process is exiting to give the driver a chance to flush and close all open handles +func (fs *hellofs) Shutdown(ctx context.Context) error { + return nil +} + +// ListStorageSpaces lists the spaces in the storage. +func (fs *hellofs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter, unrestricted bool) ([]*provider.StorageSpace, error) { + return []*provider.StorageSpace{fs.space(true)}, nil +} + +// GetQuota returns the quota on the referenced resource +func (fs *hellofs) GetQuota(ctx context.Context, ref *provider.Reference) (uint64, uint64, uint64, error) { + return uint64(len(content)), uint64(len(content)), 0, nil +} + +func (fs *hellofs) lookup(ctx context.Context, ref *provider.Reference) (*provider.ResourceInfo, error) { + if ref.GetResourceId().GetStorageId() != storageid || ref.GetResourceId().GetSpaceId() != spaceid { + return nil, errtypes.NotFound("") + } + + // switch root or file + switch ref.GetResourceId().GetOpaqueId() { + case rootid: + switch ref.GetPath() { + case "", ".": + return fs.rootInfo(), nil + case filename: + return fs.fileInfo(), nil + default: + return nil, errtypes.NotFound("unknown filename") + } + case fileid: + return fs.fileInfo(), nil + } + + return nil, errtypes.NotFound("unknown id") +} + +// GetPathByID returns the path pointed by the file id +func (fs *hellofs) GetPathByID(ctx context.Context, resID *provider.ResourceId) (string, error) { + info, err := fs.lookup(ctx, &provider.Reference{ResourceId: resID}) + if err != nil { + return "", err + } + + return info.Path, nil +} + +// GetMD returns the resuorce info for the referenced resource +func (fs *hellofs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string, fieldMask []string) (*provider.ResourceInfo, error) { + return fs.lookup(ctx, ref) +} + +// ListFolder returns the resource infos for all children of the referenced resource +func (fs *hellofs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error) { + info, err := fs.lookup(ctx, ref) + if err != nil { + return nil, err + } + + if info.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER { + return nil, errtypes.InternalError("expected a container") + } + if info.GetId().GetOpaqueId() != rootid { + return nil, errtypes.InternalError("unknown folder") + } + + return []*provider.ResourceInfo{ + fs.fileInfo(), + }, nil +} + +// Download returns a ReadCloser for the content of the referenced resource +func (fs *hellofs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) { + info, err := fs.lookup(ctx, ref) + if err != nil { + return nil, err + } + + if info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + return nil, errtypes.InternalError("expected a file") + } + if info.GetId().GetOpaqueId() != fileid { + return nil, errtypes.InternalError("unknown file") + } + + b := &bytes.Buffer{} + b.WriteString(content) + return io.NopCloser(b), nil +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go new file mode 100644 index 0000000000..3490b81083 --- /dev/null +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go @@ -0,0 +1,198 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package hello + +import ( + "context" + "io" + "net/url" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/errtypes" + "github.com/cs3org/reva/v2/pkg/storage" +) + +// hellofs is readonly so these remain unimplemented + +// CreateReference creates a resource of type reference +func (fs *hellofs) CreateReference(ctx context.Context, path string, targetURI *url.URL) error { + return errtypes.NotSupported("unimplemented") +} + +// CreateStorageSpace creates a storage space +func (fs *hellofs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) { + return nil, errtypes.NotSupported("unimplemented: CreateStorageSpace") +} + +// UpdateStorageSpace updates a storage space +func (fs *hellofs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { + return nil, errtypes.NotSupported("update storage space") +} + +// DeleteStorageSpace deletes a storage space +func (fs *hellofs) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) error { + return errtypes.NotSupported("delete storage space") +} + +// CreateDir creates a resource of type container +func (fs *hellofs) CreateDir(ctx context.Context, ref *provider.Reference) error { + return errtypes.NotSupported("unimplemented") +} + +// TouchFile sets the mtime of a resource, creating an empty file if it does not exist +// FIXME the markprocessing flag is an implementation detail of decomposedfs, remove it from the function +// FIXME the mtime should either be a time.Time or a CS3 Timestamp, not a string +func (fs *hellofs) TouchFile(ctx context.Context, ref *provider.Reference, _ bool, _ string) error { + return errtypes.NotSupported("unimplemented") +} + +// Delete deletes a resource. +// If the storage driver supports a recycle bin it should moves it to the recycle bin +func (fs *hellofs) Delete(ctx context.Context, ref *provider.Reference) error { + return errtypes.NotSupported("unimplemented") +} + +// Move changes the path of a resource +func (fs *hellofs) Move(ctx context.Context, oldRef, newRef *provider.Reference) error { + return errtypes.NotSupported("unimplemented") +} + +// Upload creates or updates a resource of type file with a new revision +func (fs *hellofs) Upload(ctx context.Context, req storage.UploadRequest, uff storage.UploadFinishedFunc) (*provider.ResourceInfo, error) { + return nil, errtypes.NotSupported("hellofs: upload not supported") +} + +// InitiateUpload returns a list of protocols with urls that can be used to append bytes to a new upload session +func (fs *hellofs) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) { + return nil, errtypes.NotSupported("hellofs: initiate upload not supported") +} + +// grants + +// DenyGrant marks a resource as denied for a recipient +// The resource and its children must be completely hidden for the recipient +func (fs *hellofs) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error { + return errtypes.NotSupported("hellofs: deny grant not supported") +} + +// AddGrant adds a grant to a resource +func (fs *hellofs) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + return errtypes.NotSupported("unimplemented") +} + +// ListGrants lists all grants on a resource +func (fs *hellofs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) { + return nil, errtypes.NotSupported("unimplemented") +} + +// RemoveGrant removes a grant from a resource +func (fs *hellofs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + return errtypes.NotSupported("unimplemented") +} + +// UpdateGrant updates a grant on a resource +func (fs *hellofs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error { + return errtypes.NotSupported("unimplemented") +} + +// arbitrary metadata + +// SetArbitraryMetadata sets arbitraty metadata on a resource +func (fs *hellofs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error { + return errtypes.NotSupported("unimplemented") +} + +// UnsetArbitraryMetadata removes arbitraty metadata from a resource +func (fs *hellofs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error { + return errtypes.NotSupported("unimplemented") +} + +// locks + +// GetLock returns an existing lock on the given reference +func (fs *hellofs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) { + return nil, errtypes.NotSupported("unimplemented") +} + +// SetLock puts a lock on the given reference +func (fs *hellofs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + return errtypes.NotSupported("unimplemented") +} + +// RefreshLock refreshes an existing lock on the given reference +func (fs *hellofs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { + return errtypes.NotSupported("unimplemented") +} + +// Unlock removes an existing lock from the given reference +func (fs *hellofs) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { + return errtypes.NotSupported("unimplemented") +} + +// revisions + +// ListRevisions lists all revisions for the referenced resource +func (fs *hellofs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) { + return nil, errtypes.NotSupported("unimplemented") +} + +// DownloadRevision downloads a revision +func (fs *hellofs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) { + return nil, errtypes.NotSupported("unimplemented") +} + +// RestoreRevision restores a revision +func (fs *hellofs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error { + return errtypes.NotSupported("unimplemented") +} + +// trash + +// PurgeRecycleItem removes a resource from the recycle bin +func (fs *hellofs) PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error { + return errtypes.NotSupported("unimplemented") +} + +// EmptyRecycle removes all resource from the recycle bin +func (fs *hellofs) EmptyRecycle(ctx context.Context, ref *provider.Reference) error { + return errtypes.NotSupported("unimplemented") +} + +// ListRecycle lists the content of the recycle bin +func (fs *hellofs) ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error) { + return nil, errtypes.NotSupported("unimplemented") +} + +// RestoreRecycleItem restores an item from the recyle bin +// if restoreRef is nil the resource should be restored at the original path +func (fs *hellofs) RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error { + return errtypes.NotSupported("unimplemented") +} + +// CreateHome creates a users home +// Deprecated: use CreateStorageSpace with type personal +func (fs *hellofs) CreateHome(ctx context.Context) error { + return errtypes.NotSupported("unimplemented") +} + +// GetHome returns the path to the users home +// Deprecated: use ListStorageSpaces with type personal +func (fs *hellofs) GetHome(ctx context.Context) (string, error) { + return "", errtypes.NotSupported("unimplemented") +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/loader/loader.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/loader/loader.go index 68575752c9..bb662eb238 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/loader/loader.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/loader/loader.go @@ -26,6 +26,7 @@ import ( _ "github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpc" _ "github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpchome" _ "github.com/cs3org/reva/v2/pkg/storage/fs/eoshome" + _ "github.com/cs3org/reva/v2/pkg/storage/fs/hello" _ "github.com/cs3org/reva/v2/pkg/storage/fs/local" _ "github.com/cs3org/reva/v2/pkg/storage/fs/localhome" _ "github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud" diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/upload.go index 872cf0503b..5e9877d97c 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/upload.go @@ -44,7 +44,7 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" "github.com/rs/zerolog/log" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" ) var defaultFilePerm = os.FileMode(0664) @@ -388,7 +388,7 @@ func (upload *fileUpload) WriteChunk(ctx context.Context, offset int64, src io.R } // GetReader returns an io.Reader for the upload -func (upload *fileUpload) GetReader(ctx context.Context) (io.Reader, error) { +func (upload *fileUpload) GetReader(ctx context.Context) (io.ReadCloser, error) { return os.Open(upload.binPath) } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/posix.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/posix.go index 4308f94867..dfffdf04b9 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/posix.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/posix.go @@ -27,7 +27,7 @@ import ( "os" "syscall" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" microstore "go-micro.dev/v4/store" "github.com/cs3org/reva/v2/pkg/events" diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go index 6fc19a0a23..11cab0c5e7 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go @@ -23,7 +23,7 @@ import ( "io" "net/url" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" @@ -31,46 +31,118 @@ import ( // FS is the interface to implement access to the storage. type FS interface { - GetHome(ctx context.Context) (string, error) - CreateHome(ctx context.Context) error - CreateDir(ctx context.Context, ref *provider.Reference) error - TouchFile(ctx context.Context, ref *provider.Reference, markprocessing bool, mtime string) error - Delete(ctx context.Context, ref *provider.Reference) error - Move(ctx context.Context, oldRef, newRef *provider.Reference) error - GetMD(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) (*provider.ResourceInfo, error) - ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error) - InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) - Upload(ctx context.Context, req UploadRequest, uploadFunc UploadFinishedFunc) (*provider.ResourceInfo, error) - Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) - ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) - DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) - RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error - ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error) - RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error - PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error - EmptyRecycle(ctx context.Context, ref *provider.Reference) error - GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) - AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error - DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error - RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error - UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error - ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) - GetQuota(ctx context.Context, ref *provider.Reference) ( /*TotalBytes*/ uint64 /*UsedBytes*/, uint64 /*RemainingBytes*/, uint64, error) - CreateReference(ctx context.Context, path string, targetURI *url.URL) error + // Minimal set for a readonly storage driver + + // Shutdown is called when the process is exiting to give the driver a chance to flush and close all open handles Shutdown(ctx context.Context) error - SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error - UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error - SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error - GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) - RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error - Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error + // ListStorageSpaces lists the spaces in the storage. - // The unrestricted parameter can be used to list other user's spaces when - // the user has the necessary permissions. + // FIXME The unrestricted parameter is an implementation detail of decomposedfs, remove it from the function? ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter, unrestricted bool) ([]*provider.StorageSpace, error) + + // GetQuota returns the quota on the referenced resource + GetQuota(ctx context.Context, ref *provider.Reference) ( /*TotalBytes*/ uint64 /*UsedBytes*/, uint64 /*RemainingBytes*/, uint64, error) + + // GetMD returns the resuorce info for the referenced resource + GetMD(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) (*provider.ResourceInfo, error) + // ListFolder returns the resource infos for all children of the referenced resource + ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error) + // Download returns a ReadCloser for the content of the referenced resource + Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) + + // GetPathByID returns the path for the given resource id relative to the space root + // It should only reveal the path visible to the current user to not leak the names uf unshared parent resources + // FIXME should be deprecated in favor of calls to GetMD and the fieldmask 'path' + GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) + + // Functions for a writeable storage space + + // CreateReference creates a resource of type reference + CreateReference(ctx context.Context, path string, targetURI *url.URL) error + // CreateDir creates a resource of type container + CreateDir(ctx context.Context, ref *provider.Reference) error + // TouchFile sets the mtime of a resource, creating an empty file if it does not exist + // FIXME the markprocessing flag is an implementation detail of decomposedfs, remove it from the function + // FIXME the mtime should either be a time.Time or a CS3 Timestamp, not a string + TouchFile(ctx context.Context, ref *provider.Reference, markprocessing bool, mtime string) error + // Delete deletes a resource. + // If the storage driver supports a recycle bin it should moves it to the recycle bin + Delete(ctx context.Context, ref *provider.Reference) error + // Move changes the path of a resource + Move(ctx context.Context, oldRef, newRef *provider.Reference) error + // InitiateUpload returns a list of protocols with urls that can be used to append bytes to a new upload session + InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) + // Upload creates or updates a resource of type file with a new revision + Upload(ctx context.Context, req UploadRequest, uploadFunc UploadFinishedFunc) (*provider.ResourceInfo, error) + + // Revisions + + // ListRevisions lists all revisions for the referenced resource + ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) + // DownloadRevision downloads a revision + DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) + // RestoreRevision restores a revision + RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error + + // Recyce bin + + // ListRecycle lists the content of the recycle bin + ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error) + // RestoreRecycleItem restores an item from the recyle bin + // if restoreRef is nil the resource should be restored at the original path + RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error + // PurgeRecycleItem removes a resource from the recycle bin + PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error + // EmptyRecycle removes all resource from the recycle bin + EmptyRecycle(ctx context.Context, ref *provider.Reference) error + + // Grants + + // AddGrant adds a grant to a resource + AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error + // DenyGrant marks a resource as denied for a recipient + // The resource and its children must be completely hidden for the recipient + DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error + // RemoveGrant removes a grant from a resource + RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error + // UpdateGrant updates a grant on a resource + UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error + // ListGrants lists all grants on a resource + ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) + + // Arbitrary Metadata + + // SetArbitraryMetadata sets arbitraty metadata on a resource + SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error + // UnsetArbitraryMetadata removes arbitraty metadata from a resource + UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error + + // Locks + + // GetLock returns an existing lock on the given reference + GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) + // SetLock puts a lock on the given reference + SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error + // RefreshLock refreshes an existing lock on the given reference + RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error + // Unlock removes an existing lock from the given reference + Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error + + // Spaces + + // CreateStorageSpace creates a storage space CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) + // UpdateStorageSpace updates a storage space UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) + // DeleteStorageSpace deletes a storage space DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) error + + // CreateHome creates a users home + // Deprecated: use CreateStorageSpace with type personal + CreateHome(ctx context.Context) error + // GetHome returns the path to the users home + // Deprecated: use ListStorageSpaces with type personal + GetHome(ctx context.Context) (string, error) } // UnscopeFunc is a function that unscopes a user diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go index 50a8fe0eb4..d928f3d694 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go @@ -25,7 +25,7 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" ) // UploadFinishedFunc is a callback function used in storage drivers to indicate that an upload has finished diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go index 529f32d0eb..2bb6b1076c 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -59,7 +59,7 @@ import ( "github.com/cs3org/reva/v2/pkg/utils" "github.com/jellydator/ttlcache/v2" "github.com/pkg/errors" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" microstore "go-micro.dev/v4/store" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go index dc2a075515..d0b84f6a79 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go @@ -27,7 +27,7 @@ import ( "time" "github.com/google/uuid" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/appctx" diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go index c008c274dd..1c1386d9b4 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go @@ -26,7 +26,7 @@ import ( "strconv" "time" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go index cd5e3a6091..9abc856fc8 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go @@ -44,7 +44,7 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" "github.com/rogpeppe/go-internal/lockedfile" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" ) var _idRegexp = regexp.MustCompile(".*/([^/]+).info") diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go index 92c9438f7e..4a3bfc61c2 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go @@ -40,7 +40,7 @@ import ( "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node" "github.com/golang-jwt/jwt" "github.com/pkg/errors" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) @@ -94,7 +94,7 @@ func (session *OcisSession) GetInfo(_ context.Context) (tusd.FileInfo, error) { } // GetReader returns an io.Reader for the upload -func (session *OcisSession) GetReader(ctx context.Context) (io.Reader, error) { +func (session *OcisSession) GetReader(ctx context.Context) (io.ReadCloser, error) { _, span := tracer.Start(session.Context(ctx), "GetReader") defer span.End() return os.Open(session.binPath()) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/upload.go index 45c61dc8a1..1c9219bb83 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/upload.go @@ -35,7 +35,7 @@ import ( "github.com/cs3org/reva/v2/pkg/utils" "github.com/google/uuid" "github.com/pkg/errors" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" ) var defaultFilePerm = os.FileMode(0664) @@ -296,7 +296,7 @@ func (upload *fileUpload) GetInfo(ctx context.Context) (tusd.FileInfo, error) { } // GetReader returns an io.Reader for the upload -func (upload *fileUpload) GetReader(ctx context.Context) (io.Reader, error) { +func (upload *fileUpload) GetReader(ctx context.Context) (io.ReadCloser, error) { return os.Open(upload.binPath) } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go index 4566007171..b90cb2a088 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go @@ -23,7 +23,7 @@ import ( "io" "net/url" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/storage" diff --git a/vendor/github.com/tus/tusd/v2/LICENSE.txt b/vendor/github.com/tus/tusd/v2/LICENSE.txt new file mode 100644 index 0000000000..bdf13822ce --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2013-2017 Transloadit Ltd and Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go b/vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go new file mode 100644 index 0000000000..ab9c8d3cd9 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go @@ -0,0 +1,132 @@ +package handler + +import ( + "errors" + "io" + "net" + "net/http" + "os" + "strings" + "sync/atomic" + "time" +) + +// bodyReader is an io.Reader, which is intended to wrap the request +// body reader. If an error occurr during reading the request body, it +// will not return this error to the reading entity, but instead store +// the error and close the io.Reader, so that the error can be checked +// afterwards. This is helpful, so that the stores do not have to handle +// the error but this can instead be done in the handler. +// In addition, the bodyReader keeps track of how many bytes were read. +type bodyReader struct { + // bytesCounter is the first field to ensure that it's properly aligned, + // otherwise we run into alignment issues on some 32-bit builds. + // See https://github.com/tus/tusd/issues/1047 + // See https://pkg.go.dev/sync/atomic#pkg-note-BUG + // TODO: In the future we should move all of these values to the safe + // atomic.Uint64 type, which takes care of alignment automatically. + bytesCounter int64 + ctx *httpContext + reader io.ReadCloser + err error + onReadDone func() +} + +func newBodyReader(c *httpContext, maxSize int64) *bodyReader { + return &bodyReader{ + ctx: c, + reader: http.MaxBytesReader(c.res, c.req.Body, maxSize), + onReadDone: func() {}, + } +} + +func (r *bodyReader) Read(b []byte) (int, error) { + if r.err != nil { + return 0, io.EOF + } + + n, err := r.reader.Read(b) + atomic.AddInt64(&r.bytesCounter, int64(n)) + if !errors.Is(err, os.ErrDeadlineExceeded) { + // If the timeout wasn't exceeded (due to SetReadDeadline), invoke + // the callback so the deadline can be extended + r.onReadDone() + + } + if err != nil { + // Note: if an error occurs while reading the body, we must set `r.err` (either in here + // or somewhere else, such as in closeWithError). Otherwise, the PATCH handler might not know + // that an error occurred and assumes that a request was transferred succesfully even though + // it was interrupted. This leads to problems with the RUFH draft. + + // io.EOF means that the request body was fully read and does not represent an error. + if err == io.EOF { + return n, io.EOF + } + + // http.ErrBodyReadAfterClose means that the bodyReader closed the request body because the upload is + // is stopped or the server shuts down. In this case, the closeWithError method already + // set `r.err` and thus we don't overerwrite it here but just return. + if err == http.ErrBodyReadAfterClose { + return n, io.EOF + } + + // All of the following errors can be understood as the input stream ending too soon: + // - io.ErrClosedPipe is returned in the package's unit test with io.Pipe() + // - io.UnexpectedEOF means that the client aborted the request. + if err == io.ErrClosedPipe || err == io.ErrUnexpectedEOF { + err = ErrUnexpectedEOF + } + + // Connection resets are not dropped silently, but responded to the client. + // We change the error because otherwise the message would contain the local address, + // which is unnecessary to be included in the response. + if strings.HasSuffix(err.Error(), "read: connection reset by peer") { + err = ErrConnectionReset + } + + // For timeouts, we also send a nicer response to the clients. + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + err = ErrReadTimeout + } + + // MaxBytesError is returned from http.MaxBytesReader, which we use to limit + // the request body size. + maxBytesErr := &http.MaxBytesError{} + if errors.As(err, &maxBytesErr) { + err = ErrSizeExceeded + } + + // Other errors are stored for retrival with hasError, but is not returned + // to the consumer. We do not overwrite an error if it has been set already. + if r.err == nil { + r.err = err + } + } + + return n, nil +} + +func (r bodyReader) hasError() error { + if r.err == io.EOF { + return nil + } + + return r.err +} + +func (r *bodyReader) bytesRead() int64 { + return atomic.LoadInt64(&r.bytesCounter) +} + +func (r *bodyReader) closeWithError(err error) { + r.err = err + + // SetReadDeadline with the current time causes concurrent reads to the body to time out, + // so the body will be closed sooner with less delay. + if err := r.ctx.resC.SetReadDeadline(time.Now()); err != nil { + r.ctx.log.Warn("NetworkTimeoutError", "error", err) + } + + r.reader.Close() +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/composer.go b/vendor/github.com/tus/tusd/v2/pkg/handler/composer.go new file mode 100644 index 0000000000..abea0a6900 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/composer.go @@ -0,0 +1,87 @@ +package handler + +// StoreComposer represents a composable data store. It consists of the core +// data store and optional extensions. Please consult the package's overview +// for a more detailed introduction in how to use this structure. +type StoreComposer struct { + Core DataStore + + UsesTerminater bool + Terminater TerminaterDataStore + UsesLocker bool + Locker Locker + UsesConcater bool + Concater ConcaterDataStore + UsesLengthDeferrer bool + LengthDeferrer LengthDeferrerDataStore +} + +// NewStoreComposer creates a new and empty store composer. +func NewStoreComposer() *StoreComposer { + return &StoreComposer{} +} + +// Capabilities returns a string representing the provided extensions in a +// human-readable format meant for debugging. +func (store *StoreComposer) Capabilities() string { + str := "Core: " + + if store.Core != nil { + str += "✓" + } else { + str += "✗" + } + + str += ` Terminater: ` + if store.UsesTerminater { + str += "✓" + } else { + str += "✗" + } + str += ` Locker: ` + if store.UsesLocker { + str += "✓" + } else { + str += "✗" + } + str += ` Concater: ` + if store.UsesConcater { + str += "✓" + } else { + str += "✗" + } + str += ` LengthDeferrer: ` + if store.UsesLengthDeferrer { + str += "✓" + } else { + str += "✗" + } + + return str +} + +// UseCore will set the used core data store. If the argument is nil, the +// property will be unset. +func (store *StoreComposer) UseCore(core DataStore) { + store.Core = core +} + +func (store *StoreComposer) UseTerminater(ext TerminaterDataStore) { + store.UsesTerminater = ext != nil + store.Terminater = ext +} + +func (store *StoreComposer) UseLocker(ext Locker) { + store.UsesLocker = ext != nil + store.Locker = ext +} + +func (store *StoreComposer) UseConcater(ext ConcaterDataStore) { + store.UsesConcater = ext != nil + store.Concater = ext +} + +func (store *StoreComposer) UseLengthDeferrer(ext LengthDeferrerDataStore) { + store.UsesLengthDeferrer = ext != nil + store.LengthDeferrer = ext +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/composer.mgo b/vendor/github.com/tus/tusd/v2/pkg/handler/composer.mgo new file mode 100644 index 0000000000..f4fc3ef87b --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/composer.mgo @@ -0,0 +1,74 @@ +package handler + +#define USE_FUNC(TYPE) \ +func (store *StoreComposer) Use ## TYPE(ext TYPE ## DataStore) { \ + store.Uses ## TYPE = ext != nil; \ + store.TYPE = ext; \ +} + +#define USE_FIELD(TYPE) Uses ## TYPE bool; \ + TYPE TYPE ## DataStore + +#define USE_FROM(TYPE) if mod, ok := store.(TYPE ## DataStore); ok { \ + composer.Use ## TYPE (mod) \ +} + +#define USE_CAP(TYPE) str += ` TYPE: `; \ +if store.Uses ## TYPE { \ + str += "✓" \ +} else { \ + str += "✗" \ +} + +// StoreComposer represents a composable data store. It consists of the core +// data store and optional extensions. Please consult the package's overview +// for a more detailed introduction in how to use this structure. +type StoreComposer struct { + Core DataStore + + USE_FIELD(Terminater) + USE_FIELD(Finisher) + USE_FIELD(Locker) + USE_FIELD(GetReader) + USE_FIELD(Concater) + USE_FIELD(LengthDeferrer) +} + +// NewStoreComposer creates a new and empty store composer. +func NewStoreComposer() *StoreComposer { + return &StoreComposer{} +} + +// Capabilities returns a string representing the provided extensions in a +// human-readable format meant for debugging. +func (store *StoreComposer) Capabilities() string { + str := "Core: " + + if store.Core != nil { + str += "✓" + } else { + str += "✗" + } + + USE_CAP(Terminater) + USE_CAP(Finisher) + USE_CAP(Locker) + USE_CAP(GetReader) + USE_CAP(Concater) + USE_CAP(LengthDeferrer) + + return str +} + +// UseCore will set the used core data store. If the argument is nil, the +// property will be unset. +func (store *StoreComposer) UseCore(core DataStore) { + store.Core = core +} + +USE_FUNC(Terminater) +USE_FUNC(Finisher) +USE_FUNC(Locker) +USE_FUNC(GetReader) +USE_FUNC(Concater) +USE_FUNC(LengthDeferrer) diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/config.go b/vendor/github.com/tus/tusd/v2/pkg/handler/config.go new file mode 100644 index 0000000000..e5c6702632 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/config.go @@ -0,0 +1,195 @@ +package handler + +import ( + "errors" + "net/url" + "regexp" + "time" + + "golang.org/x/exp/slog" +) + +// Config provides a way to configure the Handler depending on your needs. +type Config struct { + // StoreComposer points to the store composer from which the core data store + // and optional dependencies should be taken. May only be nil if DataStore is + // set. + StoreComposer *StoreComposer + // MaxSize defines how many bytes may be stored in one single upload. If its + // value is is 0 or smaller no limit will be enforced. + MaxSize int64 + // BasePath defines the URL path used for handling uploads, e.g. "/files/". + // If no trailing slash is presented it will be added. You may specify an + // absolute URL containing a scheme, e.g. "http://tus.io" + BasePath string + isAbs bool + // EnableExperimentalProtocol controls whether the new resumable upload protocol draft + // from the IETF's HTTP working group is accepted next to the current tus v1 protocol. + // See https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/ + EnableExperimentalProtocol bool + // DisableDownload indicates whether the server will refuse downloads of the + // uploaded file, by not mounting the GET handler. + DisableDownload bool + // DisableTermination indicates whether the server will refuse termination + // requests of the uploaded file, by not mounting the DELETE handler. + DisableTermination bool + // Cors can be used to customize the handling of Cross-Origin Resource Sharing (CORS). + // See the CorsConfig struct for more details. + // Defaults to DefaultCorsConfig. + Cors *CorsConfig + // NotifyCompleteUploads indicates whether sending notifications about + // completed uploads using the CompleteUploads channel should be enabled. + NotifyCompleteUploads bool + // NotifyTerminatedUploads indicates whether sending notifications about + // terminated uploads using the TerminatedUploads channel should be enabled. + NotifyTerminatedUploads bool + // NotifyUploadProgress indicates whether sending notifications about + // the upload progress using the UploadProgress channel should be enabled. + NotifyUploadProgress bool + // NotifyCreatedUploads indicates whether sending notifications about + // the upload having been created using the CreatedUploads channel should be enabled. + NotifyCreatedUploads bool + // UploadProgressInterval specifies the interval at which the upload progress + // notifications are sent to the UploadProgress channel, if enabled. + // Defaults to 1s. + UploadProgressInterval time.Duration + // Logger is the logger to use internally, mostly for printing requests. + Logger *slog.Logger + // Respect the X-Forwarded-Host, X-Forwarded-Proto and Forwarded headers + // potentially set by proxies when generating an absolute URL in the + // response to POST requests. + RespectForwardedHeaders bool + // PreUploadCreateCallback will be invoked before a new upload is created, if the + // property is supplied. If the callback returns no error, the upload will be created + // and optional values from HTTPResponse will be contained in the HTTP response. + // If the error is non-nil, the upload will not be created. This can be used to implement + // validation of upload metadata etc. Furthermore, HTTPResponse will be ignored and + // the error value can contain values for the HTTP response. + // If the error is nil, FileInfoChanges can be filled out to specify individual properties + // that should be overwriten before the upload is create. See its type definition for + // more details on its behavior. If you do not want to make any changes, return an empty struct. + PreUploadCreateCallback func(hook HookEvent) (HTTPResponse, FileInfoChanges, error) + // PreFinishResponseCallback will be invoked after an upload is completed but before + // a response is returned to the client. This can be used to implement post-processing validation. + // If the callback returns no error, optional values from HTTPResponse will be contained in the HTTP response. + // If the error is non-nil, the error will be forwarded to the client. Furthermore, + // HTTPResponse will be ignored and the error value can contain values for the HTTP response. + PreFinishResponseCallback func(hook HookEvent) (HTTPResponse, error) + // GracefulRequestCompletionTimeout is the timeout for operations to complete after an HTTP + // request has ended (successfully or by error). For example, if an HTTP request is interrupted, + // instead of stopping immediately, the handler and data store will be given some additional + // time to wrap up their operations and save any uploaded data. GracefulRequestCompletionTimeout + // controls this time. + // See HookEvent.Context for more details. + // Defaults to 10s. + GracefulRequestCompletionTimeout time.Duration + // AcquireLockTimeout is the duration that a request handler will wait to acquire a lock for + // an upload. If the timeout is reached, it will stop waiting and send an error response to the + // client. + // Defaults to 20s. + AcquireLockTimeout time.Duration + // NetworkTimeout is the timeout for individual read operations on the request body. If the + // read operation succeeds in this time window, the handler will continue consuming the body. + // If a read operation times out, the handler will stop reading and close the request. + // This ensures that an upload is consumed while data is being transmitted, while also closing + // dead connections. + // Under the hood, this is passed to ResponseController.SetReadDeadline + // Defaults to 60s + NetworkTimeout time.Duration +} + +// CorsConfig provides a way to customize the the handling of Cross-Origin Resource Sharing (CORS). +// More details about CORS are available at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS. +type CorsConfig struct { + // Disable instructs the handler to ignore all CORS-related headers and never set a + // CORS-related header in a response. This is useful if CORS is already handled by a proxy. + Disable bool + // AllowOrigin is a regular expression used to check if a request is allowed to participate in the + // CORS protocol. If the request's Origin header matches the regular expression, CORS is allowed. + // If not, a 403 Forbidden response is sent, rejecting the CORS request. + AllowOrigin *regexp.Regexp + // AllowCredentials defines whether the `Access-Control-Allow-Credentials: true` header should be + // included in CORS responses. This allows clients to share credentials using the Cookie and + // Authorization header + AllowCredentials bool + // AllowMethods defines the value for the `Access-Control-Allow-Methods` header in the response to + // preflight requests. You can add custom methods here, but make sure that all tus-specific methods + // from DefaultConfig.AllowMethods are included as well. + AllowMethods string + // AllowHeaders defines the value for the `Access-Control-Allow-Headers` header in the response to + // preflight requests. You can add custom headers here, but make sure that all tus-specific header + // from DefaultConfig.AllowHeaders are included as well. + AllowHeaders string + // MaxAge defines the value for the `Access-Control-Max-Age` header in the response to preflight + // requests. + MaxAge string + // ExposeHeaders defines the value for the `Access-Control-Expose-Headers` header in the response to + // actual requests. You can add custom headers here, but make sure that all tus-specific header + // from DefaultConfig.ExposeHeaders are included as well. + ExposeHeaders string +} + +// DefaultCorsConfig is the configuration that will be used in none is provided. +var DefaultCorsConfig = CorsConfig{ + Disable: false, + AllowOrigin: regexp.MustCompile(".*"), + AllowCredentials: false, + AllowMethods: "POST, HEAD, PATCH, OPTIONS, GET, DELETE", + AllowHeaders: "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version", + MaxAge: "86400", + ExposeHeaders: "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version", +} + +func (config *Config) validate() error { + if config.Logger == nil { + config.Logger = slog.Default() + } + + base := config.BasePath + uri, err := url.Parse(base) + if err != nil { + return err + } + + // Ensure base path ends with slash to remove logic from absFileURL + if base != "" && string(base[len(base)-1]) != "/" { + base += "/" + } + + // Ensure base path begins with slash if not absolute (starts with scheme) + if !uri.IsAbs() && len(base) > 0 && string(base[0]) != "/" { + base = "/" + base + } + config.BasePath = base + config.isAbs = uri.IsAbs() + + if config.StoreComposer == nil { + return errors.New("tusd: StoreComposer must no be nil") + } + + if config.StoreComposer.Core == nil { + return errors.New("tusd: StoreComposer in Config needs to contain a non-nil core") + } + + if config.UploadProgressInterval <= 0 { + config.UploadProgressInterval = 1 * time.Second + } + + if config.GracefulRequestCompletionTimeout <= 0 { + config.GracefulRequestCompletionTimeout = 10 * time.Second + } + + if config.AcquireLockTimeout <= 0 { + config.AcquireLockTimeout = 20 * time.Second + } + + if config.NetworkTimeout <= 0 { + config.NetworkTimeout = 60 * time.Second + } + + if config.Cors == nil { + config.Cors = &DefaultCorsConfig + } + + return nil +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/context.go b/vendor/github.com/tus/tusd/v2/pkg/handler/context.go new file mode 100644 index 0000000000..892009bab5 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/context.go @@ -0,0 +1,102 @@ +package handler + +import ( + "context" + "errors" + "net/http" + "time" + + "golang.org/x/exp/slog" +) + +// httpContext is wrapper around context.Context that also carries the +// corresponding HTTP request and response writer, as well as an +// optional body reader +type httpContext struct { + context.Context + + // res and req are the native request and response instances + res http.ResponseWriter + resC *http.ResponseController + req *http.Request + + // body is nil by default and set by the user if the request body is consumed. + body *bodyReader + + // cancel allows a user to cancel the internal request context, causing + // the request body to be closed. + cancel context.CancelCauseFunc + + // log is the logger for this request. It gets extended with more properties as the + // request progresses and is identified. + log *slog.Logger +} + +// newContext constructs a new httpContext for the given request. This should only be done once +// per request and the context should be stored in the request, so it can be fetched with getContext. +func (h UnroutedHandler) newContext(w http.ResponseWriter, r *http.Request) *httpContext { + // requestCtx is the context from the native request instance. It gets cancelled + // if the connection closes, the request is cancelled (HTTP/2), ServeHTTP returns + // or the server's base context is cancelled. + requestCtx := r.Context() + // On top of requestCtx, we construct a context that we can cancel, for example when + // the post-receive hook stops an upload or if another uploads requests a lock to be released. + cancellableCtx, cancelHandling := context.WithCancelCause(requestCtx) + // On top of cancellableCtx, we construct a new context which gets cancelled with a delay. + // See HookEvent.Context for more details, but the gist is that we want to give data stores + // some more time to finish their buisness. + delayedCtx := newDelayedContext(cancellableCtx, h.config.GracefulRequestCompletionTimeout) + + ctx := &httpContext{ + Context: delayedCtx, + res: w, + resC: http.NewResponseController(w), + req: r, + body: nil, // body can be filled later for PATCH requests + cancel: cancelHandling, + log: h.logger.With("method", r.Method, "path", r.URL.Path, "requestId", getRequestId(r)), + } + + go func() { + <-cancellableCtx.Done() + + // If the cause is one of our own errors, close a potential body and relay the error. + cause := context.Cause(cancellableCtx) + if (errors.Is(cause, ErrServerShutdown) || errors.Is(cause, ErrUploadInterrupted) || errors.Is(cause, ErrUploadStoppedByServer)) && ctx.body != nil { + ctx.body.closeWithError(cause) + } + }() + + return ctx +} + +// getContext tries to retrieve a httpContext from the request or constructs a new one. +func (h UnroutedHandler) getContext(w http.ResponseWriter, r *http.Request) *httpContext { + c, ok := r.Context().(*httpContext) + if !ok { + c = h.newContext(w, r) + } + + return c +} + +func (c httpContext) Value(key any) any { + // We overwrite the Value function to ensure that the values from the request + // context are returned because c.Context does not contain any values. + return c.req.Context().Value(key) +} + +// newDelayedContext returns a context that is cancelled with a delay. If the parent context +// is done, the new context will also be cancelled but only after waiting the specified delay. +// Note: The parent context MUST be cancelled or otherwise this will leak resources. In the +// case of http.Request.Context, the net/http package ensures that the context is always cancelled. +func newDelayedContext(parent context.Context, delay time.Duration) context.Context { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + <-parent.Done() + <-time.After(delay) + cancel() + }() + + return ctx +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/datastore.go b/vendor/github.com/tus/tusd/v2/pkg/handler/datastore.go new file mode 100644 index 0000000000..8888a2faad --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/datastore.go @@ -0,0 +1,190 @@ +package handler + +import ( + "context" + "io" +) + +type MetaData map[string]string + +// FileInfo contains information about a single upload resource. +type FileInfo struct { + // ID is the unique identifier of the upload resource. + ID string + // Total file size in bytes specified in the NewUpload call + Size int64 + // Indicates whether the total file size is deferred until later + SizeIsDeferred bool + // Offset in bytes (zero-based) + Offset int64 + MetaData MetaData + // Indicates that this is a partial upload which will later be used to form + // a final upload by concatenation. Partial uploads should not be processed + // when they are finished since they are only incomplete chunks of files. + IsPartial bool + // Indicates that this is a final upload + IsFinal bool + // If the upload is a final one (see IsFinal) this will be a non-empty + // ordered slice containing the ids of the uploads of which the final upload + // will consist after concatenation. + PartialUploads []string + // Storage contains information about where the data storage saves the upload, + // for example a file path. The available values vary depending on what data + // store is used. This map may also be nil. + Storage map[string]string + + // stopUpload is a callback for communicating that an upload should by stopped + // and interrupt the writes to DataStore#WriteChunk. + stopUpload func(HTTPResponse) +} + +// StopUpload interrupts a running upload from the server-side. This means that +// the current request body is closed, so that the data store does not get any +// more data. Furthermore, a response is sent to notify the client of the +// interrupting and the upload is terminated (if supported by the data store), +// so the upload cannot be resumed anymore. The response to the client can be +// optionally modified by providing values in the HTTPResponse struct. +func (f FileInfo) StopUpload(response HTTPResponse) { + if f.stopUpload != nil { + f.stopUpload(response) + } +} + +// FileInfoChanges collects changes the should be made to a FileInfo struct. This +// can be done using the PreUploadCreateCallback to modify certain properties before +// an upload is created. Properties which should not be modified (e.g. Size or Offset) +// are intentionally left out here. +type FileInfoChanges struct { + // If ID is not empty, it will be passed to the data store, allowing + // hooks to influence the upload ID. Be aware that a data store is not required to + // respect a pre-defined upload ID and might overwrite or modify it. However, + // all data stores in the github.com/tus/tusd package do respect pre-defined IDs. + ID string + + // If MetaData is not nil, it replaces the entire user-defined meta data from + // the upload creation request. You can add custom meta data fields this way + // or ensure that only certain fields from the user-defined meta data are saved. + // If you want to retain only specific entries from the user-defined meta data, you must + // manually copy them into this MetaData field. + // If you do not want to store any meta data, set this field to an empty map (`MetaData{}`). + // If you want to keep the entire user-defined meta data, set this field to nil. + MetaData MetaData + + // If Storage is not nil, it is passed to the data store to allow for minor adjustments + // to the upload storage (e.g. destination file name). The details are specific for each + // data store and should be looked up in their respective documentation. + // Please be aware that this behavior is currently not supported by any data store in + // the github.com/tus/tusd package. + Storage map[string]string +} + +type Upload interface { + // Write the chunk read from src into the file specified by the id at the + // given offset. The handler will take care of validating the offset and + // limiting the size of the src to not overflow the file's size. + // The handler will also lock resources while they are written to ensure only one + // write happens per time. + // The function call must return the number of bytes written. + WriteChunk(ctx context.Context, offset int64, src io.Reader) (int64, error) + // Read the fileinformation used to validate the offset and respond to HEAD + // requests. + GetInfo(ctx context.Context) (FileInfo, error) + // GetReader returns an io.ReadCloser which allows iterating of the content of an + // upload. It should attempt to provide a reader even if the upload has not + // been finished yet but it's not required. + GetReader(ctx context.Context) (io.ReadCloser, error) + // FinisherDataStore is the interface which can be implemented by DataStores + // which need to do additional operations once an entire upload has been + // completed. These tasks may include but are not limited to freeing unused + // resources or notifying other services. For example, S3Store uses this + // interface for removing a temporary object. + FinishUpload(ctx context.Context) error +} + +// DataStore is the base interface for storages to implement. It provides functions +// to create new uploads and fetch existing ones. +// +// Note: the context values passed to all functions is not the request's context, +// but a similar context. See HookEvent.Context for more details. +type DataStore interface { + // Create a new upload using the size as the file's length. The method must + // return an unique id which is used to identify the upload. If no backend + // (e.g. Riak) specifes the id you may want to use the uid package to + // generate one. The properties Size and MetaData will be filled. + NewUpload(ctx context.Context, info FileInfo) (upload Upload, err error) + + // GetUpload fetches the upload with a given ID. If no such upload can be found, + // ErrNotFound must be returned. + GetUpload(ctx context.Context, id string) (upload Upload, err error) +} + +type TerminatableUpload interface { + // Terminate an upload so any further requests to the upload resource will + // return the ErrNotFound error. + Terminate(ctx context.Context) error +} + +// TerminaterDataStore is the interface which must be implemented by DataStores +// if they want to receive DELETE requests using the Handler. If this interface +// is not implemented, no request handler for this method is attached. +type TerminaterDataStore interface { + AsTerminatableUpload(upload Upload) TerminatableUpload +} + +// ConcaterDataStore is the interface required to be implemented if the +// Concatenation extension should be enabled. Only in this case, the handler +// will parse and respect the Upload-Concat header. +type ConcaterDataStore interface { + AsConcatableUpload(upload Upload) ConcatableUpload +} + +type ConcatableUpload interface { + // ConcatUploads concatenates the content from the provided partial uploads + // and writes the result in the destination upload. + // The caller (usually the handler) must and will ensure that this + // destination upload has been created before with enough space to hold all + // partial uploads. The order, in which the partial uploads are supplied, + // must be respected during concatenation. + ConcatUploads(ctx context.Context, partialUploads []Upload) error +} + +// LengthDeferrerDataStore is the interface that must be implemented if the +// creation-defer-length extension should be enabled. The extension enables a +// client to upload files when their total size is not yet known. Instead, the +// client must send the total size as soon as it becomes known. +type LengthDeferrerDataStore interface { + AsLengthDeclarableUpload(upload Upload) LengthDeclarableUpload +} + +type LengthDeclarableUpload interface { + DeclareLength(ctx context.Context, length int64) error +} + +// Locker is the interface required for custom lock persisting mechanisms. +// Common ways to store this information is in memory, on disk or using an +// external service, such as Redis. +// When multiple processes are attempting to access an upload, whether it be +// by reading or writing, a synchronization mechanism is required to prevent +// data corruption, especially to ensure correct offset values and the proper +// order of chunks inside a single upload. +type Locker interface { + // NewLock creates a new unlocked lock object for the given upload ID. + NewLock(id string) (Lock, error) +} + +// Lock is the interface for a lock as returned from a Locker. +type Lock interface { + // Lock attempts to obtain an exclusive lock for the upload specified + // by its id. + // If the lock can be acquired, it will return without error. The requestUnlock + // callback is invoked when another caller attempts to create a lock. In this + // case, the holder of the lock should attempt to release the lock as soon + // as possible + // If the lock is already held, the holder's requestUnlock function will be + // invoked to request the lock to be released. If the context is cancelled before + // the lock can be acquired, ErrLockTimeout will be returned without acquiring + // the lock. + Lock(ctx context.Context, requestUnlock func()) error + // Unlock releases an existing lock for the given upload. + Unlock() error +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/doc.go b/vendor/github.com/tus/tusd/v2/pkg/handler/doc.go new file mode 100644 index 0000000000..262eba9f3a --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/doc.go @@ -0,0 +1,69 @@ +/* +Package handler provides ways to accept tus 1.0 calls using HTTP. + +tus is a protocol based on HTTP for resumable file uploads. Resumable means that +an upload can be interrupted at any moment and can be resumed without +re-uploading the previous data again. An interruption may happen willingly, if +the user wants to pause, or by accident in case of an network issue or server +outage (http://tus.io). + +# The basics of tusd + +tusd was designed in way which allows an flexible and customizable usage. We +wanted to avoid binding this package to a specific storage system – particularly +a proprietary third-party software. Therefore tusd is an abstract layer whose +only job is to accept incoming HTTP requests, validate them according to the +specification and finally passes them to the data store. + +The data store is another important component in tusd's architecture whose +purpose is to do the actual file handling. It has to write the incoming upload +to a persistent storage system and retrieve information about an upload's +current state. Therefore it is the only part of the system which communicates +directly with the underlying storage system, whether it be the local disk, a +remote FTP server or cloud providers such as AWS S3. + +# Using a store composer + +The only hard requirements for a data store can be found in the DataStore +interface. It contains methods for creating uploads (NewUpload), writing to +them (WriteChunk) and retrieving their status (GetInfo). However, there +are many more features which are not mandatory but may still be used. +These are contained in their own interfaces which all share the *DataStore +suffix. For example, GetReaderDataStore which enables downloading uploads or +TerminaterDataStore which allows uploads to be terminated. + +The store composer offers a way to combine the basic data store - the core - +implementation and these additional extensions: + + composer := tusd.NewStoreComposer() + composer.UseCore(dataStore) // Implements DataStore + composer.UseTerminater(terminater) // Implements TerminaterDataStore + composer.UseLocker(locker) // Implements LockerDataStore + +The corresponding methods for adding an extension to the composer are prefixed +with Use* followed by the name of the corresponding interface. However, most +data store provide multiple extensions and adding all of them manually can be +tedious and error-prone. Therefore, all data store distributed with tusd provide +an UseIn() method which does this job automatically. For example, this is the +S3 store in action (see S3Store.UseIn): + + store := s3store.New(…) + locker := memorylocker.New() + composer := tusd.NewStoreComposer() + store.UseIn(composer) + locker.UseIn(composer) + +Finally, once you are done with composing your data store, you can pass it +inside the Config struct in order to create create a new tusd HTTP handler: + + config := tusd.Config{ + StoreComposer: composer, + BasePath: "/files/", + } + handler, err := tusd.NewHandler(config) + +This handler can then be mounted to a specific path, e.g. /files: + + http.Handle("/files/", http.StripPrefix("/files/", handler)) +*/ +package handler diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/error.go b/vendor/github.com/tus/tusd/v2/pkg/handler/error.go new file mode 100644 index 0000000000..6400a77a93 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/error.go @@ -0,0 +1,37 @@ +package handler + +// Error represents an error with the intent to be sent in the HTTP +// response to the client. Therefore, it also contains a HTTPResponse, +// next to an error code and error message. +type Error struct { + ErrorCode string + Message string + HTTPResponse HTTPResponse +} + +func (e Error) Error() string { + return e.ErrorCode + ": " + e.Message +} + +func (e1 Error) Is(target error) bool { + e2, ok := target.(Error) + return ok && e1.ErrorCode == e2.ErrorCode +} + +// NewError constructs a new Error object with the given error code and message. +// The corresponding HTTP response will have the provided status code +// and a body consisting of the error details. +// responses. See the net/http package for standardized status codes. +func NewError(errCode string, message string, statusCode int) Error { + return Error{ + ErrorCode: errCode, + Message: message, + HTTPResponse: HTTPResponse{ + StatusCode: statusCode, + Body: errCode + ": " + message + "\n", + Header: HTTPHeader{ + "Content-Type": "text/plain; charset=utf-8", + }, + }, + } +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/handler.go b/vendor/github.com/tus/tusd/v2/pkg/handler/handler.go new file mode 100644 index 0000000000..7953a97022 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/handler.go @@ -0,0 +1,77 @@ +package handler + +import ( + "net/http" + "strings" +) + +// Handler is a ready to use handler with routing +type Handler struct { + *UnroutedHandler + http.Handler +} + +// NewHandler creates a routed tus protocol handler. This is the simplest +// way to use tusd but may not be as configurable as you require. If you are +// integrating this into an existing app you may like to use tusd.NewUnroutedHandler +// instead. Using tusd.NewUnroutedHandler allows the tus handlers to be combined into +// your existing router (aka mux) directly. It also allows the GET and DELETE +// endpoints to be customized. These are not part of the protocol so can be +// changed depending on your needs. +func NewHandler(config Config) (*Handler, error) { + if err := config.validate(); err != nil { + return nil, err + } + + handler, err := NewUnroutedHandler(config) + if err != nil { + return nil, err + } + + routedHandler := &Handler{ + UnroutedHandler: handler, + } + + mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + method := r.Method + path := strings.Trim(r.URL.Path, "/") + + switch path { + case "": + // Root endpoint for upload creation + switch method { + case "POST": + handler.PostFile(w, r) + default: + w.Header().Add("Allow", "POST") + w.WriteHeader(http.StatusMethodNotAllowed) + w.Write([]byte(`method not allowed`)) + } + default: + // URL points to an upload resource + switch { + case method == "HEAD" && r.URL.Path != "": + // Offset retrieval + handler.HeadFile(w, r) + case method == "PATCH" && r.URL.Path != "": + // Upload apppending + handler.PatchFile(w, r) + case method == "GET" && r.URL.Path != "" && !config.DisableDownload: + // Upload download + handler.GetFile(w, r) + case method == "DELETE" && r.URL.Path != "" && config.StoreComposer.UsesTerminater && !config.DisableTermination: + // Upload termination + handler.DelFile(w, r) + default: + // TODO: Only add GET and DELETE if they are supported + w.Header().Add("Allow", "GET, HEAD, PATCH, DELETE") + w.WriteHeader(http.StatusMethodNotAllowed) + w.Write([]byte(`method not allowed`)) + } + } + }) + + routedHandler.Handler = handler.Middleware(mux) + + return routedHandler, nil +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/hooks.go b/vendor/github.com/tus/tusd/v2/pkg/handler/hooks.go new file mode 100644 index 0000000000..c1c6f11333 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/hooks.go @@ -0,0 +1,48 @@ +package handler + +import ( + "context" +) + +// HookEvent represents an event from tusd which can be handled by the application. +type HookEvent struct { + // Context provides access to the context from the HTTP request. This context is + // not the exact value as the request context from http.Request.Context() but + // a similar context that retains the same values as the request context. In + // addition, Context will be cancelled after a short delay when the request context + // is done. This delay is controlled by Config.GracefulRequestCompletionTimeout. + // + // The reason is that we want stores to be able to continue processing a request after + // its context has been cancelled. For example, assume a PATCH request is incoming. If + // the end-user pauses the upload, the connection is closed causing the request context + // to be cancelled immediately. However, we want the store to be able to save the last + // few bytes that were transmitted before the request was aborted. To allow this, we + // copy the request context but cancel it with a brief delay to give the data store + // time to finish its operations. + Context context.Context `json:"-"` + // Upload contains information about the upload that caused this hook + // to be fired. + Upload FileInfo + // HTTPRequest contains details about the HTTP request that reached + // tusd. + HTTPRequest HTTPRequest +} + +func newHookEvent(c *httpContext, info FileInfo) HookEvent { + // The Host header field is not present in the header map, see https://pkg.go.dev/net/http#Request: + // > For incoming requests, the Host header is promoted to the + // > Request.Host field and removed from the Header map. + // That's why we add it back manually. + c.req.Header.Set("Host", c.req.Host) + + return HookEvent{ + Context: c, + Upload: info, + HTTPRequest: HTTPRequest{ + Method: c.req.Method, + URI: c.req.RequestURI, + RemoteAddr: c.req.RemoteAddr, + Header: c.req.Header, + }, + } +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/http.go b/vendor/github.com/tus/tusd/v2/pkg/handler/http.go new file mode 100644 index 0000000000..d521fd1ac4 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/http.go @@ -0,0 +1,79 @@ +package handler + +import ( + "net/http" + "strconv" +) + +// HTTPRequest contains basic details of an incoming HTTP request. +type HTTPRequest struct { + // Method is the HTTP method, e.g. POST or PATCH. + Method string + // URI is the full HTTP request URI, e.g. /files/fooo. + URI string + // RemoteAddr contains the network address that sent the request. + RemoteAddr string + // Header contains all HTTP headers as present in the HTTP request. + Header http.Header +} + +type HTTPHeader map[string]string + +// HTTPResponse contains basic details of an outgoing HTTP response. +type HTTPResponse struct { + // StatusCode is status code, e.g. 200 or 400. + StatusCode int + // Body is the response body. + Body string + // Header contains additional HTTP headers for the response. + Header HTTPHeader +} + +// writeTo writes the HTTP response into w, as specified by the fields in resp. +func (resp HTTPResponse) writeTo(w http.ResponseWriter) { + headers := w.Header() + for key, value := range resp.Header { + headers.Set(key, value) + } + + if len(resp.Body) > 0 { + headers.Set("Content-Length", strconv.Itoa(len(resp.Body))) + } + + w.WriteHeader(resp.StatusCode) + + if len(resp.Body) > 0 { + w.Write([]byte(resp.Body)) + } +} + +// MergeWith returns a copy of resp1, where non-default values from resp2 overwrite +// values from resp1. +func (resp1 HTTPResponse) MergeWith(resp2 HTTPResponse) HTTPResponse { + // Clone the response 1 and use it as a basis + newResp := resp1 + + // Take the status code and body from response 2 to + // overwrite values from response 1. + if resp2.StatusCode != 0 { + newResp.StatusCode = resp2.StatusCode + } + + if len(resp2.Body) > 0 { + newResp.Body = resp2.Body + } + + // For the headers, me must make a new map to avoid writing + // into the header map from response 1. + newResp.Header = make(HTTPHeader, len(resp1.Header)+len(resp2.Header)) + + for key, value := range resp1.Header { + newResp.Header[key] = value + } + + for key, value := range resp2.Header { + newResp.Header[key] = value + } + + return newResp +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/metrics.go b/vendor/github.com/tus/tusd/v2/pkg/handler/metrics.go new file mode 100644 index 0000000000..1a2c6aad99 --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/metrics.go @@ -0,0 +1,132 @@ +package handler + +import ( + "sync" + "sync/atomic" +) + +// Metrics provides numbers about the usage of the tusd handler. Since these may +// be accessed from multiple goroutines, it is necessary to read and modify them +// atomically using the functions exposed in the sync/atomic package, such as +// atomic.LoadUint64. In addition the maps must not be modified to prevent data +// races. +type Metrics struct { + // RequestTotal counts the number of incoming requests per method + RequestsTotal map[string]*uint64 + // ErrorsTotal counts the number of returned errors by their message + ErrorsTotal *ErrorsTotalMap + BytesReceived *uint64 + UploadsFinished *uint64 + UploadsCreated *uint64 + UploadsTerminated *uint64 +} + +// incRequestsTotal increases the counter for this request method atomically by +// one. The method must be one of GET, HEAD, POST, PATCH, DELETE. +func (m Metrics) incRequestsTotal(method string) { + if ptr, ok := m.RequestsTotal[method]; ok { + atomic.AddUint64(ptr, 1) + } +} + +// incErrorsTotal increases the counter for this error atomically by one. +func (m Metrics) incErrorsTotal(err Error) { + ptr := m.ErrorsTotal.retrievePointerFor(err) + atomic.AddUint64(ptr, 1) +} + +// incBytesReceived increases the number of received bytes atomically be the +// specified number. +func (m Metrics) incBytesReceived(delta uint64) { + atomic.AddUint64(m.BytesReceived, delta) +} + +// incUploadsFinished increases the counter for finished uploads atomically by one. +func (m Metrics) incUploadsFinished() { + atomic.AddUint64(m.UploadsFinished, 1) +} + +// incUploadsCreated increases the counter for completed uploads atomically by one. +func (m Metrics) incUploadsCreated() { + atomic.AddUint64(m.UploadsCreated, 1) +} + +// incUploadsTerminated increases the counter for completed uploads atomically by one. +func (m Metrics) incUploadsTerminated() { + atomic.AddUint64(m.UploadsTerminated, 1) +} + +func newMetrics() Metrics { + return Metrics{ + RequestsTotal: map[string]*uint64{ + "GET": new(uint64), + "HEAD": new(uint64), + "POST": new(uint64), + "PATCH": new(uint64), + "DELETE": new(uint64), + "OPTIONS": new(uint64), + }, + ErrorsTotal: newErrorsTotalMap(), + BytesReceived: new(uint64), + UploadsFinished: new(uint64), + UploadsCreated: new(uint64), + UploadsTerminated: new(uint64), + } +} + +// ErrorsTotalMap stores the counters for the different HTTP errors. +type ErrorsTotalMap struct { + lock sync.RWMutex + counter map[ErrorsTotalMapEntry]*uint64 +} + +type ErrorsTotalMapEntry struct { + ErrorCode string + StatusCode int +} + +func newErrorsTotalMap() *ErrorsTotalMap { + m := make(map[ErrorsTotalMapEntry]*uint64, 20) + return &ErrorsTotalMap{ + counter: m, + } +} + +// retrievePointerFor returns (after creating it if necessary) the pointer to +// the counter for the error. +func (e *ErrorsTotalMap) retrievePointerFor(err Error) *uint64 { + serr := ErrorsTotalMapEntry{ + ErrorCode: err.ErrorCode, + StatusCode: err.HTTPResponse.StatusCode, + } + + e.lock.RLock() + ptr, ok := e.counter[serr] + e.lock.RUnlock() + if ok { + return ptr + } + + // For pointer creation, a write-lock is required + e.lock.Lock() + // We ensure that the pointer wasn't created in the meantime + if ptr, ok = e.counter[serr]; !ok { + ptr = new(uint64) + e.counter[serr] = ptr + } + e.lock.Unlock() + + return ptr +} + +// Load retrieves the map of the counter pointers atomically +func (e *ErrorsTotalMap) Load() map[ErrorsTotalMapEntry]*uint64 { + m := make(map[ErrorsTotalMapEntry]*uint64, len(e.counter)) + e.lock.RLock() + for err, ptr := range e.counter { + m[err] = ptr + } + e.lock.RUnlock() + + return m +} diff --git a/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go b/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go new file mode 100644 index 0000000000..73be46437e --- /dev/null +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go @@ -0,0 +1,1569 @@ +package handler + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "io" + "math" + "mime" + "net/http" + "regexp" + "strconv" + "strings" + "time" + + "golang.org/x/exp/slog" +) + +const UploadLengthDeferred = "1" + +type draftVersion string + +// These are the different interoperability versions defines in the different +// versions of the resumable uploads draft from the HTTP working group. +// See https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/ +const ( + interopVersion3 draftVersion = "3" // From draft version -01 + interopVersion4 draftVersion = "4" // From draft version -02 + interopVersion5 draftVersion = "5" // From draft version -03 +) + +var ( + reForwardedHost = regexp.MustCompile(`host="?([^;"]+)`) + reForwardedProto = regexp.MustCompile(`proto=(https?)`) + reMimeType = regexp.MustCompile(`^[a-z]+\/[a-z0-9\-\+\.]+$`) + // We only allow certain URL-safe characters in upload IDs. URL-safe in this means + // that their are allowed in a URI's path component according to RFC 3986. + // See https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 + reValidUploadId = regexp.MustCompile(`^[A-Za-z0-9\-._~%!$'()*+,;=/:@]*$`) +) + +var ( + ErrUnsupportedVersion = NewError("ERR_UNSUPPORTED_VERSION", "missing, invalid or unsupported Tus-Resumable header", http.StatusPreconditionFailed) + ErrMaxSizeExceeded = NewError("ERR_MAX_SIZE_EXCEEDED", "maximum size exceeded", http.StatusRequestEntityTooLarge) + ErrInvalidContentType = NewError("ERR_INVALID_CONTENT_TYPE", "missing or invalid Content-Type header", http.StatusBadRequest) + ErrInvalidUploadLength = NewError("ERR_INVALID_UPLOAD_LENGTH", "missing or invalid Upload-Length header", http.StatusBadRequest) + ErrInvalidOffset = NewError("ERR_INVALID_OFFSET", "missing or invalid Upload-Offset header", http.StatusBadRequest) + ErrNotFound = NewError("ERR_UPLOAD_NOT_FOUND", "upload not found", http.StatusNotFound) + ErrFileLocked = NewError("ERR_UPLOAD_LOCKED", "file currently locked", http.StatusLocked) + ErrLockTimeout = NewError("ERR_LOCK_TIMEOUT", "failed to acquire lock before timeout", http.StatusInternalServerError) + ErrMismatchOffset = NewError("ERR_MISMATCHED_OFFSET", "mismatched offset", http.StatusConflict) + ErrSizeExceeded = NewError("ERR_UPLOAD_SIZE_EXCEEDED", "upload's size exceeded", http.StatusRequestEntityTooLarge) + ErrNotImplemented = NewError("ERR_NOT_IMPLEMENTED", "feature not implemented", http.StatusNotImplemented) + ErrUploadNotFinished = NewError("ERR_UPLOAD_NOT_FINISHED", "one of the partial uploads is not finished", http.StatusBadRequest) + ErrInvalidConcat = NewError("ERR_INVALID_CONCAT", "invalid Upload-Concat header", http.StatusBadRequest) + ErrModifyFinal = NewError("ERR_MODIFY_FINAL", "modifying a final upload is not allowed", http.StatusForbidden) + ErrUploadLengthAndUploadDeferLength = NewError("ERR_AMBIGUOUS_UPLOAD_LENGTH", "provided both Upload-Length and Upload-Defer-Length", http.StatusBadRequest) + ErrInvalidUploadDeferLength = NewError("ERR_INVALID_UPLOAD_LENGTH_DEFER", "invalid Upload-Defer-Length header", http.StatusBadRequest) + ErrUploadStoppedByServer = NewError("ERR_UPLOAD_STOPPED", "upload has been stopped by server", http.StatusBadRequest) + ErrUploadRejectedByServer = NewError("ERR_UPLOAD_REJECTED", "upload creation has been rejected by server", http.StatusBadRequest) + ErrUploadInterrupted = NewError("ERR_UPLOAD_INTERRUPTED", "upload has been interrupted by another request for this upload resource", http.StatusBadRequest) + ErrServerShutdown = NewError("ERR_SERVER_SHUTDOWN", "request has been interrupted because the server is shutting down", http.StatusServiceUnavailable) + ErrOriginNotAllowed = NewError("ERR_ORIGIN_NOT_ALLOWED", "request origin is not allowed", http.StatusForbidden) + ErrUnexpectedEOF = NewError("ERR_UNEXPECTED_EOF", "server expected to receive more bytes", http.StatusBadRequest) + + // These two responses are 500 for backwards compatability. Clients might receive a timeout response + // when the upload got interrupted. Most clients will not retry 4XX but only 5XX, so we responsd with 500 here. + ErrReadTimeout = NewError("ERR_READ_TIMEOUT", "timeout while reading request body", http.StatusInternalServerError) + ErrConnectionReset = NewError("ERR_CONNECTION_RESET", "TCP connection reset by peer", http.StatusInternalServerError) +) + +// UnroutedHandler exposes methods to handle requests as part of the tus protocol, +// such as PostFile, HeadFile, PatchFile and DelFile. In addition the GetFile method +// is provided which is, however, not part of the specification. +type UnroutedHandler struct { + config Config + composer *StoreComposer + isBasePathAbs bool + basePath string + logger *slog.Logger + extensions string + + // CompleteUploads is used to send notifications whenever an upload is + // completed by a user. The HookEvent will contain information about this + // upload after it is completed. Sending to this channel will only + // happen if the NotifyCompleteUploads field is set to true in the Config + // structure. Notifications will also be sent for completions using the + // Concatenation extension. + CompleteUploads chan HookEvent + // TerminatedUploads is used to send notifications whenever an upload is + // terminated by a user. The HookEvent will contain information about this + // upload gathered before the termination. Sending to this channel will only + // happen if the NotifyTerminatedUploads field is set to true in the Config + // structure. + TerminatedUploads chan HookEvent + // UploadProgress is used to send notifications about the progress of the + // currently running uploads. For each open PATCH request, every second + // a HookEvent instance will be send over this channel with the Offset field + // being set to the number of bytes which have been transfered to the server. + // Please be aware that this number may be higher than the number of bytes + // which have been stored by the data store! Sending to this channel will only + // happen if the NotifyUploadProgress field is set to true in the Config + // structure. + UploadProgress chan HookEvent + // CreatedUploads is used to send notifications about the uploads having been + // created. It triggers post creation and therefore has all the HookEvent incl. + // the ID available already. It facilitates the post-create hook. Sending to + // this channel will only happen if the NotifyCreatedUploads field is set to + // true in the Config structure. + CreatedUploads chan HookEvent + // Metrics provides numbers of the usage for this handler. + Metrics Metrics +} + +// NewUnroutedHandler creates a new handler without routing using the given +// configuration. It exposes the http handlers which need to be combined with +// a router (aka mux) of your choice. If you are looking for preconfigured +// handler see NewHandler. +func NewUnroutedHandler(config Config) (*UnroutedHandler, error) { + if err := config.validate(); err != nil { + return nil, err + } + + // Only promote extesions using the Tus-Extension header which are implemented + extensions := "creation,creation-with-upload" + if config.StoreComposer.UsesTerminater { + extensions += ",termination" + } + if config.StoreComposer.UsesConcater { + extensions += ",concatenation" + } + if config.StoreComposer.UsesLengthDeferrer { + extensions += ",creation-defer-length" + } + + handler := &UnroutedHandler{ + config: config, + composer: config.StoreComposer, + basePath: config.BasePath, + isBasePathAbs: config.isAbs, + CompleteUploads: make(chan HookEvent), + TerminatedUploads: make(chan HookEvent), + UploadProgress: make(chan HookEvent), + CreatedUploads: make(chan HookEvent), + logger: config.Logger, + extensions: extensions, + Metrics: newMetrics(), + } + + return handler, nil +} + +// SupportedExtensions returns a comma-separated list of the supported tus extensions. +// The availability of an extension usually depends on whether the provided data store +// implements some additional interfaces. +func (handler *UnroutedHandler) SupportedExtensions() string { + return handler.extensions +} + +// Middleware checks various aspects of the request and ensures that it +// conforms with the spec. Also handles method overriding for clients which +// cannot make PATCH AND DELETE requests. If you are using the tusd handlers +// directly you will need to wrap at least the POST and PATCH endpoints in +// this middleware. +func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Construct our own context and make it available in the request. Successive logic + // should use handler.getContext to retrieve it + c := handler.newContext(w, r) + r = r.WithContext(c) + + // Set the initial read deadline for consuming the request body. All headers have already been read, + // so this is only for reading the request body. While reading, we regularly update the read deadline + // so this deadline is usually not final. See the bodyReader and writeChunk. + // We also update the write deadline, but makes sure that it is larger than the read deadline, so we + // can still write a response in the case of a read timeout. + if err := c.resC.SetReadDeadline(time.Now().Add(handler.config.NetworkTimeout)); err != nil { + c.log.Warn("NetworkControlError", "error", err) + } + if err := c.resC.SetWriteDeadline(time.Now().Add(2 * handler.config.NetworkTimeout)); err != nil { + c.log.Warn("NetworkControlError", "error", err) + } + + // Allow overriding the HTTP method. The reason for this is + // that some libraries/environments do not support PATCH and + // DELETE requests, e.g. Flash in a browser and parts of Java. + if newMethod := r.Header.Get("X-HTTP-Method-Override"); r.Method == "POST" && newMethod != "" { + r.Method = newMethod + } + + c.log.Info("RequestIncoming") + + handler.Metrics.incRequestsTotal(r.Method) + + header := w.Header() + + cors := handler.config.Cors + if origin := r.Header.Get("Origin"); !cors.Disable && origin != "" { + originIsAllowed := cors.AllowOrigin.MatchString(origin) + if !originIsAllowed { + handler.sendError(c, ErrOriginNotAllowed) + return + } + + header.Set("Access-Control-Allow-Origin", origin) + header.Set("Vary", "Origin") + + if cors.AllowCredentials { + header.Add("Access-Control-Allow-Credentials", "true") + } + + if r.Method == "OPTIONS" { + // Preflight request + header.Add("Access-Control-Allow-Methods", cors.AllowMethods) + header.Add("Access-Control-Allow-Headers", cors.AllowHeaders) + header.Set("Access-Control-Max-Age", cors.MaxAge) + } else { + // Actual request + header.Add("Access-Control-Expose-Headers", cors.ExposeHeaders) + } + } + + // Detect requests with tus v1 protocol vs the IETF resumable upload draft + isTusV1 := !handler.usesIETFDraft(r) + + if isTusV1 { + // Set current version used by the server + header.Set("Tus-Resumable", "1.0.0") + } + + // Add nosniff to all responses https://golang.org/src/net/http/server.go#L1429 + header.Set("X-Content-Type-Options", "nosniff") + + // Set appropriated headers in case of OPTIONS method allowing protocol + // discovery and end with an 204 No Content + if r.Method == "OPTIONS" { + if handler.config.MaxSize > 0 { + header.Set("Tus-Max-Size", strconv.FormatInt(handler.config.MaxSize, 10)) + } + + header.Set("Tus-Version", "1.0.0") + header.Set("Tus-Extension", handler.extensions) + + // Although the 204 No Content status code is a better fit in this case, + // since we do not have a response body included, we cannot use it here + // as some browsers only accept 200 OK as successful response to a + // preflight request. If we send them the 204 No Content the response + // will be ignored or interpreted as a rejection. + // For example, the Presto engine, which is used in older versions of + // Opera, Opera Mobile and Opera Mini, handles CORS this way. + handler.sendResp(c, HTTPResponse{ + StatusCode: http.StatusOK, + }) + return + } + + // Test if the version sent by the client is supported + // GET and HEAD methods are not checked since a browser may visit this URL and does + // not include this header. GET requests are not part of the specification. + if r.Method != "GET" && r.Method != "HEAD" && r.Header.Get("Tus-Resumable") != "1.0.0" && isTusV1 { + handler.sendError(c, ErrUnsupportedVersion) + return + } + + // Proceed with routing the request + h.ServeHTTP(w, r) + }) +} + +// PostFile creates a new file upload using the datastore after validating the +// length and parsing the metadata. +func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) { + if handler.usesIETFDraft(r) { + handler.PostFileV2(w, r) + return + } + + c := handler.getContext(w, r) + + // Check for presence of application/offset+octet-stream. If another content + // type is defined, it will be ignored and treated as none was set because + // some HTTP clients may enforce a default value for this header. + containsChunk := r.Header.Get("Content-Type") == "application/offset+octet-stream" + + // Only use the proper Upload-Concat header if the concatenation extension + // is even supported by the data store. + var concatHeader string + if handler.composer.UsesConcater { + concatHeader = r.Header.Get("Upload-Concat") + } + + // Parse Upload-Concat header + isPartial, isFinal, partialUploadIDs, err := parseConcat(concatHeader, handler.basePath) + if err != nil { + handler.sendError(c, err) + return + } + + // If the upload is a final upload created by concatenation multiple partial + // uploads the size is sum of all sizes of these files (no need for + // Upload-Length header) + var size int64 + var sizeIsDeferred bool + var partialUploads []Upload + if isFinal { + // A final upload must not contain a chunk within the creation request + if containsChunk { + handler.sendError(c, ErrModifyFinal) + return + } + + partialUploads, size, err = handler.sizeOfUploads(c, partialUploadIDs) + if err != nil { + handler.sendError(c, err) + return + } + } else { + uploadLengthHeader := r.Header.Get("Upload-Length") + uploadDeferLengthHeader := r.Header.Get("Upload-Defer-Length") + size, sizeIsDeferred, err = handler.validateNewUploadLengthHeaders(uploadLengthHeader, uploadDeferLengthHeader) + if err != nil { + handler.sendError(c, err) + return + } + } + + // Test whether the size is still allowed + if handler.config.MaxSize > 0 && size > handler.config.MaxSize { + handler.sendError(c, ErrMaxSizeExceeded) + return + } + + // Parse metadata + meta := ParseMetadataHeader(r.Header.Get("Upload-Metadata")) + + info := FileInfo{ + Size: size, + SizeIsDeferred: sizeIsDeferred, + MetaData: meta, + IsPartial: isPartial, + IsFinal: isFinal, + PartialUploads: partialUploadIDs, + } + + resp := HTTPResponse{ + StatusCode: http.StatusCreated, + Header: HTTPHeader{}, + } + + if handler.config.PreUploadCreateCallback != nil { + resp2, changes, err := handler.config.PreUploadCreateCallback(newHookEvent(c, info)) + if err != nil { + handler.sendError(c, err) + return + } + resp = resp.MergeWith(resp2) + + // Apply changes returned from the pre-create hook. + if changes.ID != "" { + if err := validateUploadId(changes.ID); err != nil { + handler.sendError(c, err) + return + } + + info.ID = changes.ID + } + + if changes.MetaData != nil { + info.MetaData = changes.MetaData + } + + if changes.Storage != nil { + info.Storage = changes.Storage + } + } + + upload, err := handler.composer.Core.NewUpload(c, info) + if err != nil { + handler.sendError(c, err) + return + } + + info, err = upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + id := info.ID + + // Add the Location header directly after creating the new resource to even + // include it in cases of failure when an error is returned + url := handler.absFileURL(r, id) + resp.Header["Location"] = url + + handler.Metrics.incUploadsCreated() + c.log = c.log.With("id", id) + c.log.Info("UploadCreated", "id", id, "size", size, "url", url) + + if handler.config.NotifyCreatedUploads { + handler.CreatedUploads <- newHookEvent(c, info) + } + + if isFinal { + concatableUpload := handler.composer.Concater.AsConcatableUpload(upload) + if err := concatableUpload.ConcatUploads(c, partialUploads); err != nil { + handler.sendError(c, err) + return + } + info.Offset = size + + if handler.config.NotifyCompleteUploads { + handler.CompleteUploads <- newHookEvent(c, info) + } + } + + if containsChunk { + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + resp, err = handler.writeChunk(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + } else if !sizeIsDeferred && size == 0 { + // Directly finish the upload if the upload is empty (i.e. has a size of 0). + // This statement is in an else-if block to avoid causing duplicate calls + // to finishUploadIfComplete if an upload is empty and contains a chunk. + resp, err = handler.finishUploadIfComplete(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + + } + + handler.sendResp(c, resp) +} + +// PostFile creates a new file upload using the datastore after validating the +// length and parsing the metadata. +func (handler *UnroutedHandler) PostFileV2(w http.ResponseWriter, r *http.Request) { + currentUploadDraftInteropVersion := getIETFDraftInteropVersion(r) + c := handler.getContext(w, r) + + // Parse headers + contentType := r.Header.Get("Content-Type") + contentDisposition := r.Header.Get("Content-Disposition") + willCompleteUpload := isIETFDraftUploadComplete(r) + + info := FileInfo{ + MetaData: make(MetaData), + } + if willCompleteUpload && r.ContentLength != -1 { + // If the client wants to perform the upload in one request with Content-Length, we know the final upload size. + info.Size = r.ContentLength + } else { + // Error out if the storage does not support upload length deferring, but we need it. + if !handler.composer.UsesLengthDeferrer { + handler.sendError(c, ErrNotImplemented) + return + } + + info.SizeIsDeferred = true + } + + // Parse Content-Type and Content-Disposition to get file type or file name + if contentType != "" { + fileType, _, err := mime.ParseMediaType(contentType) + if err != nil { + handler.sendError(c, err) + return + } + + info.MetaData["filetype"] = fileType + } + + if contentDisposition != "" { + _, values, err := mime.ParseMediaType(contentDisposition) + if err != nil { + handler.sendError(c, err) + return + } + + if values["filename"] != "" { + info.MetaData["filename"] = values["filename"] + } + } + + resp := HTTPResponse{ + StatusCode: http.StatusCreated, + Header: HTTPHeader{}, + } + + // 1. Create upload resource + if handler.config.PreUploadCreateCallback != nil { + resp2, changes, err := handler.config.PreUploadCreateCallback(newHookEvent(c, info)) + if err != nil { + handler.sendError(c, err) + return + } + resp = resp.MergeWith(resp2) + + // Apply changes returned from the pre-create hook. + if changes.ID != "" { + if err := validateUploadId(changes.ID); err != nil { + handler.sendError(c, err) + return + } + + info.ID = changes.ID + } + + if changes.MetaData != nil { + info.MetaData = changes.MetaData + } + + if changes.Storage != nil { + info.Storage = changes.Storage + } + } + + upload, err := handler.composer.Core.NewUpload(c, info) + if err != nil { + handler.sendError(c, err) + return + } + + info, err = upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + id := info.ID + url := handler.absFileURL(r, id) + resp.Header["Location"] = url + + // Send 104 response + w.Header().Set("Location", url) + w.Header().Set("Upload-Draft-Interop-Version", string(currentUploadDraftInteropVersion)) + w.WriteHeader(104) + + handler.Metrics.incUploadsCreated() + c.log = c.log.With("id", id) + c.log.Info("UploadCreated", "size", info.Size, "url", url) + + if handler.config.NotifyCreatedUploads { + handler.CreatedUploads <- newHookEvent(c, info) + } + + // 2. Lock upload + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + // 3. Write chunk + resp, err = handler.writeChunk(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + + // 4. Finish upload, if necessary + if willCompleteUpload && info.SizeIsDeferred { + info, err = upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + uploadLength := info.Offset + + lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) + if err := lengthDeclarableUpload.DeclareLength(c, uploadLength); err != nil { + handler.sendError(c, err) + return + } + + info.Size = uploadLength + info.SizeIsDeferred = false + + resp, err = handler.finishUploadIfComplete(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + + } + + handler.sendResp(c, resp) +} + +// HeadFile returns the length and offset for the HEAD request +func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) { + c := handler.getContext(w, r) + + id, err := extractIDFromPath(r.URL.Path) + if err != nil { + handler.sendError(c, err) + return + } + c.log = c.log.With("id", id) + + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + upload, err := handler.composer.Core.GetUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + info, err := upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + resp := HTTPResponse{ + Header: HTTPHeader{ + "Cache-Control": "no-store", + "Upload-Offset": strconv.FormatInt(info.Offset, 10), + }, + } + + if !handler.usesIETFDraft(r) { + // Add Upload-Concat header if possible + if info.IsPartial { + resp.Header["Upload-Concat"] = "partial" + } + + if info.IsFinal { + v := "final;" + for _, uploadID := range info.PartialUploads { + v += handler.absFileURL(r, uploadID) + " " + } + // Remove trailing space + v = v[:len(v)-1] + + resp.Header["Upload-Concat"] = v + } + + if len(info.MetaData) != 0 { + resp.Header["Upload-Metadata"] = SerializeMetadataHeader(info.MetaData) + } + + if info.SizeIsDeferred { + resp.Header["Upload-Defer-Length"] = UploadLengthDeferred + } else { + resp.Header["Upload-Length"] = strconv.FormatInt(info.Size, 10) + resp.Header["Content-Length"] = strconv.FormatInt(info.Size, 10) + } + + resp.StatusCode = http.StatusOK + } else { + isUploadCompleteNow := !info.SizeIsDeferred && info.Offset == info.Size + setIETFDraftUploadComplete(r, resp, isUploadCompleteNow) + resp.Header["Upload-Draft-Interop-Version"] = string(getIETFDraftInteropVersion(r)) + + // Draft -01 and -02 require a 204 No Content response. Version -03 allows 200 OK as well, + // but we stick to 204 to not make the logic less complex. + resp.StatusCode = http.StatusNoContent + } + + handler.sendResp(c, resp) +} + +// PatchFile adds a chunk to an upload. This operation is only allowed +// if enough space in the upload is left. +func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request) { + c := handler.getContext(w, r) + + isTusV1 := !handler.usesIETFDraft(r) + + // Check for presence of application/offset+octet-stream + if isTusV1 && r.Header.Get("Content-Type") != "application/offset+octet-stream" { + handler.sendError(c, ErrInvalidContentType) + return + } + + // Check for presence of a valid Upload-Offset Header + offset, err := strconv.ParseInt(r.Header.Get("Upload-Offset"), 10, 64) + if err != nil || offset < 0 { + handler.sendError(c, ErrInvalidOffset) + return + } + + id, err := extractIDFromPath(r.URL.Path) + if err != nil { + handler.sendError(c, err) + return + } + c.log = c.log.With("id", id) + + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + upload, err := handler.composer.Core.GetUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + info, err := upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + // Modifying a final upload is not allowed + if info.IsFinal { + handler.sendError(c, ErrModifyFinal) + return + } + + if offset != info.Offset { + handler.sendError(c, ErrMismatchOffset) + return + } + + // TODO: If (Upload-Incomplete: ?0 OR Upload-Complete: ?1) and (Content-Length is set), we can + // - declare the length already here + // - validate that the length from this request matches info.Size if !info.SizeIsDeferred + + resp := HTTPResponse{ + StatusCode: http.StatusNoContent, + Header: make(HTTPHeader, 1), // Initialize map, so writeChunk can set the Upload-Offset header. + } + + // Do not proxy the call to the data store if the upload is already completed + if !info.SizeIsDeferred && info.Offset == info.Size { + resp.Header["Upload-Offset"] = strconv.FormatInt(offset, 10) + handler.sendResp(c, resp) + return + } + + if r.Header.Get("Upload-Length") != "" { + if !handler.composer.UsesLengthDeferrer { + handler.sendError(c, ErrNotImplemented) + return + } + if !info.SizeIsDeferred { + handler.sendError(c, ErrInvalidUploadLength) + return + } + uploadLength, err := strconv.ParseInt(r.Header.Get("Upload-Length"), 10, 64) + if err != nil || uploadLength < 0 || uploadLength < info.Offset || (handler.config.MaxSize > 0 && uploadLength > handler.config.MaxSize) { + handler.sendError(c, ErrInvalidUploadLength) + return + } + + lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) + if err := lengthDeclarableUpload.DeclareLength(c, uploadLength); err != nil { + handler.sendError(c, err) + return + } + + info.Size = uploadLength + info.SizeIsDeferred = false + } + + resp, err = handler.writeChunk(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + + willCompleteUpload := isIETFDraftUploadComplete(r) + if willCompleteUpload && info.SizeIsDeferred { + info, err = upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + uploadLength := info.Offset + + lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) + if err := lengthDeclarableUpload.DeclareLength(c, uploadLength); err != nil { + handler.sendError(c, err) + return + } + + info.Size = uploadLength + info.SizeIsDeferred = false + + resp, err = handler.finishUploadIfComplete(c, resp, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + } + + handler.sendResp(c, resp) +} + +// writeChunk reads the body from the requests r and appends it to the upload +// with the corresponding id. Afterwards, it will set the necessary response +// headers but will not send the response. +func (handler *UnroutedHandler) writeChunk(c *httpContext, resp HTTPResponse, upload Upload, info FileInfo) (HTTPResponse, error) { + // Get Content-Length if possible + r := c.req + length := r.ContentLength + offset := info.Offset + + // Test if this upload fits into the file's size + if !info.SizeIsDeferred && offset+length > info.Size { + return resp, ErrSizeExceeded + } + + maxSize := info.Size - offset + // If the upload's length is deferred and the PATCH request does not contain the Content-Length + // header (which is allowed if 'Transfer-Encoding: chunked' is used), we still need to set limits for + // the body size. + if info.SizeIsDeferred { + if handler.config.MaxSize > 0 { + // Ensure that the upload does not exceed the maximum upload size + maxSize = handler.config.MaxSize - offset + } else { + // If no upload limit is given, we allow arbitrary sizes + maxSize = math.MaxInt64 + } + } + if length > 0 { + maxSize = length + } + + c.log.Info("ChunkWriteStart", "maxSize", maxSize, "offset", offset) + + var bytesWritten int64 + var err error + // Prevent a nil pointer dereference when accessing the body which may not be + // available in the case of a malicious request. + if r.Body != nil { + // Limit the data read from the request's body to the allowed maximum. We use + // http.MaxBytesReader instead of io.LimitedReader because it returns an error + // if too much data is provided (handled in bodyReader) and also stops the server + // from reading the remaining request body. + c.body = newBodyReader(c, maxSize) + c.body.onReadDone = func() { + // Update the read deadline for every successful read operation. This ensures that the request handler + // keeps going while data is transmitted but that dead connections can also time out and be cleaned up. + if err := c.resC.SetReadDeadline(time.Now().Add(handler.config.NetworkTimeout)); err != nil { + c.log.Warn("NetworkTimeoutError", "error", err) + } + + // The write deadline is updated accordingly to ensure that we can also write responses. + if err := c.resC.SetWriteDeadline(time.Now().Add(2 * handler.config.NetworkTimeout)); err != nil { + c.log.Warn("NetworkTimeoutError", "error", err) + } + } + + // We use a callback to allow the hook system to cancel an upload. The callback + // cancels the request context causing the request body to be closed with the + // provided error. + info.stopUpload = func(res HTTPResponse) { + cause := ErrUploadStoppedByServer + cause.HTTPResponse = cause.HTTPResponse.MergeWith(res) + c.cancel(cause) + } + + if handler.config.NotifyUploadProgress { + handler.sendProgressMessages(c, info) + } + + bytesWritten, err = upload.WriteChunk(c, offset, c.body) + + // If we encountered an error while reading the body from the HTTP request, log it, but only include + // it in the response, if the store did not also return an error. + bodyErr := c.body.hasError() + if bodyErr != nil { + c.log.Error("BodyReadError", "error", bodyErr.Error()) + if err == nil { + err = bodyErr + } + } + + // Terminate the upload if it was stopped, as indicated by the ErrUploadStoppedByServer error. + terminateUpload := errors.Is(bodyErr, ErrUploadStoppedByServer) + if terminateUpload && handler.composer.UsesTerminater { + if terminateErr := handler.terminateUpload(c, upload, info); terminateErr != nil { + // We only log this error and not show it to the user since this + // termination error is not relevant to the uploading client + c.log.Error("UploadStopTerminateError", "error", terminateErr.Error()) + } + } + } + + c.log.Info("ChunkWriteComplete", "bytesWritten", bytesWritten) + + // Send new offset to client + newOffset := offset + bytesWritten + resp.Header["Upload-Offset"] = strconv.FormatInt(newOffset, 10) + handler.Metrics.incBytesReceived(uint64(bytesWritten)) + info.Offset = newOffset + + // We try to finish the upload, even if an error occurred. If we have a previous error, + // we return it and its HTTP response. + finishResp, finishErr := handler.finishUploadIfComplete(c, resp, upload, info) + if err != nil { + return resp, err + } + + return finishResp, finishErr +} + +// finishUploadIfComplete checks whether an upload is completed (i.e. upload offset +// matches upload size) and if so, it will call the data store's FinishUpload +// function and send the necessary message on the CompleteUpload channel. +func (handler *UnroutedHandler) finishUploadIfComplete(c *httpContext, resp HTTPResponse, upload Upload, info FileInfo) (HTTPResponse, error) { + // If the upload is completed, ... + if !info.SizeIsDeferred && info.Offset == info.Size { + // ... allow the data storage to finish and cleanup the upload + if err := upload.FinishUpload(c); err != nil { + return resp, err + } + + // ... allow the hook callback to run before sending the response + if handler.config.PreFinishResponseCallback != nil { + resp2, err := handler.config.PreFinishResponseCallback(newHookEvent(c, info)) + if err != nil { + return resp, err + } + resp = resp.MergeWith(resp2) + } + + c.log.Info("UploadFinished", "size", info.Size) + handler.Metrics.incUploadsFinished() + + // ... send the info out to the channel + if handler.config.NotifyCompleteUploads { + handler.CompleteUploads <- newHookEvent(c, info) + } + } + + return resp, nil +} + +// GetFile handles requests to download a file using a GET request. This is not +// part of the specification. +func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request) { + c := handler.getContext(w, r) + + id, err := extractIDFromPath(r.URL.Path) + if err != nil { + handler.sendError(c, err) + return + } + c.log = c.log.With("id", id) + + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + upload, err := handler.composer.Core.GetUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + info, err := upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + + contentType, contentDisposition := filterContentType(info) + resp := HTTPResponse{ + StatusCode: http.StatusOK, + Header: HTTPHeader{ + "Content-Length": strconv.FormatInt(info.Offset, 10), + "Content-Type": contentType, + "Content-Disposition": contentDisposition, + }, + Body: "", // Body is intentionally left empty, and we copy it manually in later. + } + + // If no data has been uploaded yet, respond with an empty "204 No Content" status. + if info.Offset == 0 { + resp.StatusCode = http.StatusNoContent + handler.sendResp(c, resp) + return + } + + src, err := upload.GetReader(c) + if err != nil { + handler.sendError(c, err) + return + } + + handler.sendResp(c, resp) + io.Copy(w, src) + + src.Close() +} + +// mimeInlineBrowserWhitelist is a map containing MIME types which should be +// allowed to be rendered by browser inline, instead of being forced to be +// downloaded. For example, HTML or SVG files are not allowed, since they may +// contain malicious JavaScript. In a similiar fashion PDF is not on this list +// as their parsers commonly contain vulnerabilities which can be exploited. +// The values of this map does not convey any meaning and are therefore just +// empty structs. +var mimeInlineBrowserWhitelist = map[string]struct{}{ + "text/plain": {}, + + "image/png": {}, + "image/jpeg": {}, + "image/gif": {}, + "image/bmp": {}, + "image/webp": {}, + + "audio/wave": {}, + "audio/wav": {}, + "audio/x-wav": {}, + "audio/x-pn-wav": {}, + "audio/webm": {}, + "video/webm": {}, + "audio/ogg": {}, + "video/ogg": {}, + "application/ogg": {}, +} + +// filterContentType returns the values for the Content-Type and +// Content-Disposition headers for a given upload. These values should be used +// in responses for GET requests to ensure that only non-malicious file types +// are shown directly in the browser. It will extract the file name and type +// from the "fileame" and "filetype". +// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition +func filterContentType(info FileInfo) (contentType string, contentDisposition string) { + filetype := info.MetaData["filetype"] + + if reMimeType.MatchString(filetype) { + // If the filetype from metadata is well formed, we forward use this + // for the Content-Type header. However, only whitelisted mime types + // will be allowed to be shown inline in the browser + contentType = filetype + if _, isWhitelisted := mimeInlineBrowserWhitelist[filetype]; isWhitelisted { + contentDisposition = "inline" + } else { + contentDisposition = "attachment" + } + } else { + // If the filetype from the metadata is not well formed, we use a + // default type and force the browser to download the content. + contentType = "application/octet-stream" + contentDisposition = "attachment" + } + + // Add a filename to Content-Disposition if one is available in the metadata + if filename, ok := info.MetaData["filename"]; ok { + contentDisposition += ";filename=" + strconv.Quote(filename) + } + + return contentType, contentDisposition +} + +// DelFile terminates an upload permanently. +func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request) { + c := handler.getContext(w, r) + + // Abort the request handling if the required interface is not implemented + if !handler.composer.UsesTerminater { + handler.sendError(c, ErrNotImplemented) + return + } + + id, err := extractIDFromPath(r.URL.Path) + if err != nil { + handler.sendError(c, err) + return + } + c.log = c.log.With("id", id) + + if handler.composer.UsesLocker { + lock, err := handler.lockUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + defer lock.Unlock() + } + + upload, err := handler.composer.Core.GetUpload(c, id) + if err != nil { + handler.sendError(c, err) + return + } + + var info FileInfo + if handler.config.NotifyTerminatedUploads { + info, err = upload.GetInfo(c) + if err != nil { + handler.sendError(c, err) + return + } + } + + err = handler.terminateUpload(c, upload, info) + if err != nil { + handler.sendError(c, err) + return + } + + handler.sendResp(c, HTTPResponse{ + StatusCode: http.StatusNoContent, + }) +} + +// terminateUpload passes a given upload to the DataStore's Terminater, +// send the corresponding upload info on the TerminatedUploads channnel +// and updates the statistics. +// Note the the info argument is only needed if the terminated uploads +// notifications are enabled. +func (handler *UnroutedHandler) terminateUpload(c *httpContext, upload Upload, info FileInfo) error { + terminatableUpload := handler.composer.Terminater.AsTerminatableUpload(upload) + + err := terminatableUpload.Terminate(c) + if err != nil { + return err + } + + if handler.config.NotifyTerminatedUploads { + handler.TerminatedUploads <- newHookEvent(c, info) + } + + c.log.Info("UploadTerminated") + handler.Metrics.incUploadsTerminated() + + return nil +} + +// Send the error in the response body. The status code will be looked up in +// ErrStatusCodes. If none is found 500 Internal Error will be used. +func (handler *UnroutedHandler) sendError(c *httpContext, err error) { + r := c.req + + detailedErr, ok := err.(Error) + if !ok { + c.log.Error("InternalServerError", "message", err.Error()) + detailedErr = NewError("ERR_INTERNAL_SERVER_ERROR", err.Error(), http.StatusInternalServerError) + } + + // If we are sending the response for a HEAD request, ensure that we are not including + // any response body. + if r.Method == "HEAD" { + detailedErr.HTTPResponse.Body = "" + } + + handler.sendResp(c, detailedErr.HTTPResponse) + handler.Metrics.incErrorsTotal(detailedErr) +} + +// sendResp writes the header to w with the specified status code. +func (handler *UnroutedHandler) sendResp(c *httpContext, resp HTTPResponse) { + resp.writeTo(c.res) + + c.log.Info("ResponseOutgoing", "status", resp.StatusCode, "body", resp.Body) +} + +// Make an absolute URLs to the given upload id. If the base path is absolute +// it will be prepended else the host and protocol from the request is used. +func (handler *UnroutedHandler) absFileURL(r *http.Request, id string) string { + if handler.isBasePathAbs { + return handler.basePath + id + } + + // Read origin and protocol from request + host, proto := getHostAndProtocol(r, handler.config.RespectForwardedHeaders) + + url := proto + "://" + host + handler.basePath + id + + return url +} + +// sendProgressMessage will send a notification over the UploadProgress channel +// indicating how much data has been transfered to the server. +// It will stop sending these instances once the provided context is done. +func (handler *UnroutedHandler) sendProgressMessages(c *httpContext, info FileInfo) { + hook := newHookEvent(c, info) + + previousOffset := int64(0) + originalOffset := hook.Upload.Offset + + emitProgress := func() { + hook.Upload.Offset = originalOffset + c.body.bytesRead() + if hook.Upload.Offset != previousOffset { + handler.UploadProgress <- hook + previousOffset = hook.Upload.Offset + } + } + + go func() { + for { + select { + case <-c.Done(): + emitProgress() + return + case <-time.After(handler.config.UploadProgressInterval): + emitProgress() + } + } + }() +} + +// getHostAndProtocol extracts the host and used protocol (either HTTP or HTTPS) +// from the given request. If `allowForwarded` is set, the X-Forwarded-Host, +// X-Forwarded-Proto and Forwarded headers will also be checked to +// support proxies. +func getHostAndProtocol(r *http.Request, allowForwarded bool) (host, proto string) { + if r.TLS != nil { + proto = "https" + } else { + proto = "http" + } + + host = r.Host + + if !allowForwarded { + return + } + + if h := r.Header.Get("X-Forwarded-Host"); h != "" { + host = h + } + + if h := r.Header.Get("X-Forwarded-Proto"); h == "http" || h == "https" { + proto = h + } + + if h := r.Header.Get("Forwarded"); h != "" { + if r := reForwardedHost.FindStringSubmatch(h); len(r) == 2 { + host = r[1] + } + + if r := reForwardedProto.FindStringSubmatch(h); len(r) == 2 { + proto = r[1] + } + } + + return +} + +// The get sum of all sizes for a list of upload ids while checking whether +// all of these uploads are finished yet. This is used to calculate the size +// of a final resource. +func (handler *UnroutedHandler) sizeOfUploads(ctx context.Context, ids []string) (partialUploads []Upload, size int64, err error) { + partialUploads = make([]Upload, len(ids)) + + for i, id := range ids { + upload, err := handler.composer.Core.GetUpload(ctx, id) + if err != nil { + return nil, 0, err + } + + info, err := upload.GetInfo(ctx) + if err != nil { + return nil, 0, err + } + + if info.SizeIsDeferred || info.Offset != info.Size { + err = ErrUploadNotFinished + return nil, 0, err + } + + size += info.Size + partialUploads[i] = upload + } + + return +} + +// Verify that the Upload-Length and Upload-Defer-Length headers are acceptable for creating a +// new upload +func (handler *UnroutedHandler) validateNewUploadLengthHeaders(uploadLengthHeader string, uploadDeferLengthHeader string) (uploadLength int64, uploadLengthDeferred bool, err error) { + haveBothLengthHeaders := uploadLengthHeader != "" && uploadDeferLengthHeader != "" + haveInvalidDeferHeader := uploadDeferLengthHeader != "" && uploadDeferLengthHeader != UploadLengthDeferred + lengthIsDeferred := uploadDeferLengthHeader == UploadLengthDeferred + + if lengthIsDeferred && !handler.composer.UsesLengthDeferrer { + err = ErrNotImplemented + } else if haveBothLengthHeaders { + err = ErrUploadLengthAndUploadDeferLength + } else if haveInvalidDeferHeader { + err = ErrInvalidUploadDeferLength + } else if lengthIsDeferred { + uploadLengthDeferred = true + } else { + uploadLength, err = strconv.ParseInt(uploadLengthHeader, 10, 64) + if err != nil || uploadLength < 0 { + err = ErrInvalidUploadLength + } + } + + return +} + +// lockUpload creates a new lock for the given upload ID and attempts to lock it. +// The created lock is returned if it was aquired successfully. +func (handler *UnroutedHandler) lockUpload(c *httpContext, id string) (Lock, error) { + lock, err := handler.composer.Locker.NewLock(id) + if err != nil { + return nil, err + } + + ctx, cancelContext := context.WithTimeout(c, handler.config.AcquireLockTimeout) + defer cancelContext() + + // No need to wrap this in a sync.OnceFunc because c.cancel will be a noop after the first call. + releaseLock := func() { + c.log.Info("UploadInterrupted") + c.cancel(ErrUploadInterrupted) + } + + if err := lock.Lock(ctx, releaseLock); err != nil { + return nil, err + } + + return lock, nil +} + +// usesIETFDraft returns whether a HTTP request uses a supported version of the resumable upload draft from IETF +// (instead of tus v1) and support has been enabled in tusd. +func (handler UnroutedHandler) usesIETFDraft(r *http.Request) bool { + interopVersionHeader := getIETFDraftInteropVersion(r) + return handler.config.EnableExperimentalProtocol && interopVersionHeader != "" +} + +// getIETFDraftInteropVersion returns the resumable upload draft interop version from the headers. +func getIETFDraftInteropVersion(r *http.Request) draftVersion { + version := draftVersion(r.Header.Get("Upload-Draft-Interop-Version")) + switch version { + case interopVersion3, interopVersion4, interopVersion5: + return version + default: + return "" + } +} + +// isIETFDraftUploadComplete returns whether a HTTP request upload is complete +// according to the set resumable upload draft version from IETF. +func isIETFDraftUploadComplete(r *http.Request) bool { + currentUploadDraftInteropVersion := getIETFDraftInteropVersion(r) + switch currentUploadDraftInteropVersion { + case interopVersion4, interopVersion5: + return r.Header.Get("Upload-Complete") == "?1" + case interopVersion3: + return r.Header.Get("Upload-Incomplete") == "?0" + default: + return false + } +} + +// setIETFDraftUploadComplete sets the Upload-Complete (Upload-Incomplete) to the provided +// value, depending on the interop version used in the request. +func setIETFDraftUploadComplete(r *http.Request, resp HTTPResponse, isComplete bool) { + currentUploadDraftInteropVersion := getIETFDraftInteropVersion(r) + + switch currentUploadDraftInteropVersion { + case interopVersion3: + if isComplete { + resp.Header["Upload-Incomplete"] = "?0" + } else { + resp.Header["Upload-Incomplete"] = "?1" + } + case interopVersion4, interopVersion5: + if isComplete { + resp.Header["Upload-Complete"] = "?1" + } else { + resp.Header["Upload-Complete"] = "?0" + } + } +} + +// ParseMetadataHeader parses the Upload-Metadata header as defined in the +// File Creation extension. +// e.g. Upload-Metadata: name bHVucmpzLnBuZw==,type aW1hZ2UvcG5n +func ParseMetadataHeader(header string) map[string]string { + meta := make(map[string]string) + + for _, element := range strings.Split(header, ",") { + element := strings.TrimSpace(element) + + parts := strings.Split(element, " ") + + if len(parts) > 2 { + continue + } + + key := parts[0] + if key == "" { + continue + } + + value := "" + if len(parts) == 2 { + // Ignore current element if the value is no valid base64 + dec, err := base64.StdEncoding.DecodeString(parts[1]) + if err != nil { + continue + } + + value = string(dec) + } + + meta[key] = value + } + + return meta +} + +// SerializeMetadataHeader serializes a map of strings into the Upload-Metadata +// header format used in the response for HEAD requests. +// e.g. Upload-Metadata: name bHVucmpzLnBuZw==,type aW1hZ2UvcG5n +func SerializeMetadataHeader(meta map[string]string) string { + header := "" + for key, value := range meta { + valueBase64 := base64.StdEncoding.EncodeToString([]byte(value)) + header += key + " " + valueBase64 + "," + } + + // Remove trailing comma + if len(header) > 0 { + header = header[:len(header)-1] + } + + return header +} + +// Parse the Upload-Concat header, e.g. +// Upload-Concat: partial +// Upload-Concat: final;http://tus.io/files/a /files/b/ +func parseConcat(header string, basePath string) (isPartial bool, isFinal bool, partialUploads []string, err error) { + if len(header) == 0 { + return + } + + if header == "partial" { + isPartial = true + return + } + + l := len("final;") + if strings.HasPrefix(header, "final;") && len(header) > l { + isFinal = true + + list := strings.Split(header[l:], " ") + for _, value := range list { + value := strings.TrimSpace(value) + if value == "" { + continue + } + + id, extractErr := extractIDFromURL(value, basePath) + if extractErr != nil { + err = extractErr + return + } + + partialUploads = append(partialUploads, id) + } + } + + // If no valid partial upload ids are extracted this is not a final upload. + if len(partialUploads) == 0 { + isFinal = false + err = ErrInvalidConcat + } + + return +} + +// extractIDFromPath extracts the upload ID from a path, which has already +// been stripped of the base path (done by the user). Effectively, we only +// remove leading and trailing slashes. +func extractIDFromPath(path string) (string, error) { + return strings.Trim(path, "/"), nil +} + +// extractIDFromURL extracts the upload ID from a full URL or a full path +// (including the base path). For example: +// +// https://example.com/files/1234/5678 -> 1234/5678 +// /files/1234/5678 -> 1234/5678 +func extractIDFromURL(url string, basePath string) (string, error) { + _, id, ok := strings.Cut(url, basePath) + if !ok { + return "", ErrNotFound + } + + return extractIDFromPath(id) +} + +// getRequestId returns the value of the X-Request-ID header, if available, +// and also takes care of truncating the input. +func getRequestId(r *http.Request) string { + reqId := r.Header.Get("X-Request-ID") + if reqId == "" { + return "" + } + + // Limit the length of the request ID to 36 characters, which is enough + // to fit a UUID. + if len(reqId) > 36 { + reqId = reqId[:36] + } + + return reqId +} + +// validateUploadId checks whether an ID included in a FileInfoChange struct is allowed. +func validateUploadId(newId string) error { + if newId == "" { + // An empty ID from FileInfoChanges is allowed. The store will then + // just pick an ID. + return nil + } + + if strings.HasPrefix(newId, "/") || strings.HasSuffix(newId, "/") { + // Disallow leading and trailing slashes, as these would be + // stripped away by extractIDFromPath, which can cause problems and confusion. + return fmt.Errorf("validation error in FileInfoChanges: ID must not begin or end with a forward slash (got: %s)", newId) + } + + if !reValidUploadId.MatchString(newId) { + // Disallow some non-URL-safe characters in the upload ID to + // prevent issues with URL parsing, which are though to debug for users. + return fmt.Errorf("validation error in FileInfoChanges: ID must contain only URL-safe character: %s (got: %s)", reValidUploadId.String(), newId) + } + + return nil +} diff --git a/vendor/golang.org/x/exp/slog/attr.go b/vendor/golang.org/x/exp/slog/attr.go new file mode 100644 index 0000000000..a180d0e1d3 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/attr.go @@ -0,0 +1,102 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "fmt" + "time" +) + +// An Attr is a key-value pair. +type Attr struct { + Key string + Value Value +} + +// String returns an Attr for a string value. +func String(key, value string) Attr { + return Attr{key, StringValue(value)} +} + +// Int64 returns an Attr for an int64. +func Int64(key string, value int64) Attr { + return Attr{key, Int64Value(value)} +} + +// Int converts an int to an int64 and returns +// an Attr with that value. +func Int(key string, value int) Attr { + return Int64(key, int64(value)) +} + +// Uint64 returns an Attr for a uint64. +func Uint64(key string, v uint64) Attr { + return Attr{key, Uint64Value(v)} +} + +// Float64 returns an Attr for a floating-point number. +func Float64(key string, v float64) Attr { + return Attr{key, Float64Value(v)} +} + +// Bool returns an Attr for a bool. +func Bool(key string, v bool) Attr { + return Attr{key, BoolValue(v)} +} + +// Time returns an Attr for a time.Time. +// It discards the monotonic portion. +func Time(key string, v time.Time) Attr { + return Attr{key, TimeValue(v)} +} + +// Duration returns an Attr for a time.Duration. +func Duration(key string, v time.Duration) Attr { + return Attr{key, DurationValue(v)} +} + +// Group returns an Attr for a Group Value. +// The first argument is the key; the remaining arguments +// are converted to Attrs as in [Logger.Log]. +// +// Use Group to collect several key-value pairs under a single +// key on a log line, or as the result of LogValue +// in order to log a single value as multiple Attrs. +func Group(key string, args ...any) Attr { + return Attr{key, GroupValue(argsToAttrSlice(args)...)} +} + +func argsToAttrSlice(args []any) []Attr { + var ( + attr Attr + attrs []Attr + ) + for len(args) > 0 { + attr, args = argsToAttr(args) + attrs = append(attrs, attr) + } + return attrs +} + +// Any returns an Attr for the supplied value. +// See [Value.AnyValue] for how values are treated. +func Any(key string, value any) Attr { + return Attr{key, AnyValue(value)} +} + +// Equal reports whether a and b have equal keys and values. +func (a Attr) Equal(b Attr) bool { + return a.Key == b.Key && a.Value.Equal(b.Value) +} + +func (a Attr) String() string { + return fmt.Sprintf("%s=%s", a.Key, a.Value) +} + +// isEmpty reports whether a has an empty key and a nil value. +// That can be written as Attr{} or Any("", nil). +func (a Attr) isEmpty() bool { + return a.Key == "" && a.Value.num == 0 && a.Value.any == nil +} diff --git a/vendor/golang.org/x/exp/slog/doc.go b/vendor/golang.org/x/exp/slog/doc.go new file mode 100644 index 0000000000..4beaf86748 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/doc.go @@ -0,0 +1,316 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package slog provides structured logging, +in which log records include a message, +a severity level, and various other attributes +expressed as key-value pairs. + +It defines a type, [Logger], +which provides several methods (such as [Logger.Info] and [Logger.Error]) +for reporting events of interest. + +Each Logger is associated with a [Handler]. +A Logger output method creates a [Record] from the method arguments +and passes it to the Handler, which decides how to handle it. +There is a default Logger accessible through top-level functions +(such as [Info] and [Error]) that call the corresponding Logger methods. + +A log record consists of a time, a level, a message, and a set of key-value +pairs, where the keys are strings and the values may be of any type. +As an example, + + slog.Info("hello", "count", 3) + +creates a record containing the time of the call, +a level of Info, the message "hello", and a single +pair with key "count" and value 3. + +The [Info] top-level function calls the [Logger.Info] method on the default Logger. +In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. +Besides these convenience methods for common levels, +there is also a [Logger.Log] method which takes the level as an argument. +Each of these methods has a corresponding top-level function that uses the +default logger. + +The default handler formats the log record's message, time, level, and attributes +as a string and passes it to the [log] package. + + 2022/11/08 15:28:26 INFO hello count=3 + +For more control over the output format, create a logger with a different handler. +This statement uses [New] to create a new logger with a TextHandler +that writes structured records in text form to standard error: + + logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) + +[TextHandler] output is a sequence of key=value pairs, easily and unambiguously +parsed by machine. This statement: + + logger.Info("hello", "count", 3) + +produces this output: + + time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 + +The package also provides [JSONHandler], whose output is line-delimited JSON: + + logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) + logger.Info("hello", "count", 3) + +produces this output: + + {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} + +Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. +There are options for setting the minimum level (see Levels, below), +displaying the source file and line of the log call, and +modifying attributes before they are logged. + +Setting a logger as the default with + + slog.SetDefault(logger) + +will cause the top-level functions like [Info] to use it. +[SetDefault] also updates the default logger used by the [log] package, +so that existing applications that use [log.Printf] and related functions +will send log records to the logger's handler without needing to be rewritten. + +Some attributes are common to many log calls. +For example, you may wish to include the URL or trace identifier of a server request +with all log events arising from the request. +Rather than repeat the attribute with every log call, you can use [Logger.With] +to construct a new Logger containing the attributes: + + logger2 := logger.With("url", r.URL) + +The arguments to With are the same key-value pairs used in [Logger.Info]. +The result is a new Logger with the same handler as the original, but additional +attributes that will appear in the output of every call. + +# Levels + +A [Level] is an integer representing the importance or severity of a log event. +The higher the level, the more severe the event. +This package defines constants for the most common levels, +but any int can be used as a level. + +In an application, you may wish to log messages only at a certain level or greater. +One common configuration is to log messages at Info or higher levels, +suppressing debug logging until it is needed. +The built-in handlers can be configured with the minimum level to output by +setting [HandlerOptions.Level]. +The program's `main` function typically does this. +The default value is LevelInfo. + +Setting the [HandlerOptions.Level] field to a [Level] value +fixes the handler's minimum level throughout its lifetime. +Setting it to a [LevelVar] allows the level to be varied dynamically. +A LevelVar holds a Level and is safe to read or write from multiple +goroutines. +To vary the level dynamically for an entire program, first initialize +a global LevelVar: + + var programLevel = new(slog.LevelVar) // Info by default + +Then use the LevelVar to construct a handler, and make it the default: + + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) + slog.SetDefault(slog.New(h)) + +Now the program can change its logging level with a single statement: + + programLevel.Set(slog.LevelDebug) + +# Groups + +Attributes can be collected into groups. +A group has a name that is used to qualify the names of its attributes. +How this qualification is displayed depends on the handler. +[TextHandler] separates the group and attribute names with a dot. +[JSONHandler] treats each group as a separate JSON object, with the group name as the key. + +Use [Group] to create a Group attribute from a name and a list of key-value pairs: + + slog.Group("request", + "method", r.Method, + "url", r.URL) + +TextHandler would display this group as + + request.method=GET request.url=http://example.com + +JSONHandler would display it as + + "request":{"method":"GET","url":"http://example.com"} + +Use [Logger.WithGroup] to qualify all of a Logger's output +with a group name. Calling WithGroup on a Logger results in a +new Logger with the same Handler as the original, but with all +its attributes qualified by the group name. + +This can help prevent duplicate attribute keys in large systems, +where subsystems might use the same keys. +Pass each subsystem a different Logger with its own group name so that +potential duplicates are qualified: + + logger := slog.Default().With("id", systemID) + parserLogger := logger.WithGroup("parser") + parseInput(input, parserLogger) + +When parseInput logs with parserLogger, its keys will be qualified with "parser", +so even if it uses the common key "id", the log line will have distinct keys. + +# Contexts + +Some handlers may wish to include information from the [context.Context] that is +available at the call site. One example of such information +is the identifier for the current span when tracing is enabled. + +The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first +argument, as do their corresponding top-level functions. + +Although the convenience methods on Logger (Info and so on) and the +corresponding top-level functions do not take a context, the alternatives ending +in "Context" do. For example, + + slog.InfoContext(ctx, "message") + +It is recommended to pass a context to an output method if one is available. + +# Attrs and Values + +An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as +alternating keys and values. The statement + + slog.Info("hello", slog.Int("count", 3)) + +behaves the same as + + slog.Info("hello", "count", 3) + +There are convenience constructors for [Attr] such as [Int], [String], and [Bool] +for common types, as well as the function [Any] for constructing Attrs of any +type. + +The value part of an Attr is a type called [Value]. +Like an [any], a Value can hold any Go value, +but it can represent typical values, including all numbers and strings, +without an allocation. + +For the most efficient log output, use [Logger.LogAttrs]. +It is similar to [Logger.Log] but accepts only Attrs, not alternating +keys and values; this allows it, too, to avoid allocation. + +The call + + logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) + +is the most efficient way to achieve the same output as + + slog.Info("hello", "count", 3) + +# Customizing a type's logging behavior + +If a type implements the [LogValuer] interface, the [Value] returned from its LogValue +method is used for logging. You can use this to control how values of the type +appear in logs. For example, you can redact secret information like passwords, +or gather a struct's fields in a Group. See the examples under [LogValuer] for +details. + +A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] +method handles these cases carefully, avoiding infinite loops and unbounded recursion. +Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. + +# Wrapping output methods + +The logger functions use reflection over the call stack to find the file name +and line number of the logging call within the application. This can produce +incorrect source information for functions that wrap slog. For instance, if you +define this function in file mylog.go: + + func Infof(format string, args ...any) { + slog.Default().Info(fmt.Sprintf(format, args...)) + } + +and you call it like this in main.go: + + Infof(slog.Default(), "hello, %s", "world") + +then slog will report the source file as mylog.go, not main.go. + +A correct implementation of Infof will obtain the source location +(pc) and pass it to NewRecord. +The Infof function in the package-level example called "wrapping" +demonstrates how to do this. + +# Working with Records + +Sometimes a Handler will need to modify a Record +before passing it on to another Handler or backend. +A Record contains a mixture of simple public fields (e.g. Time, Level, Message) +and hidden fields that refer to state (such as attributes) indirectly. This +means that modifying a simple copy of a Record (e.g. by calling +[Record.Add] or [Record.AddAttrs] to add attributes) +may have unexpected effects on the original. +Before modifying a Record, use [Clone] to +create a copy that shares no state with the original, +or create a new Record with [NewRecord] +and build up its Attrs by traversing the old ones with [Record.Attrs]. + +# Performance considerations + +If profiling your application demonstrates that logging is taking significant time, +the following suggestions may help. + +If many log lines have a common attribute, use [Logger.With] to create a Logger with +that attribute. The built-in handlers will format that attribute only once, at the +call to [Logger.With]. The [Handler] interface is designed to allow that optimization, +and a well-written Handler should take advantage of it. + +The arguments to a log call are always evaluated, even if the log event is discarded. +If possible, defer computation so that it happens only if the value is actually logged. +For example, consider the call + + slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily + +The URL.String method will be called even if the logger discards Info-level events. +Instead, pass the URL directly: + + slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed + +The built-in [TextHandler] will call its String method, but only +if the log event is enabled. +Avoiding the call to String also preserves the structure of the underlying value. +For example [JSONHandler] emits the components of the parsed URL as a JSON object. +If you want to avoid eagerly paying the cost of the String call +without causing the handler to potentially inspect the structure of the value, +wrap the value in a fmt.Stringer implementation that hides its Marshal methods. + +You can also use the [LogValuer] interface to avoid unnecessary work in disabled log +calls. Say you need to log some expensive value: + + slog.Debug("frobbing", "value", computeExpensiveValue(arg)) + +Even if this line is disabled, computeExpensiveValue will be called. +To avoid that, define a type implementing LogValuer: + + type expensive struct { arg int } + + func (e expensive) LogValue() slog.Value { + return slog.AnyValue(computeExpensiveValue(e.arg)) + } + +Then use a value of that type in log calls: + + slog.Debug("frobbing", "value", expensive{arg}) + +Now computeExpensiveValue will only be called when the line is enabled. + +The built-in handlers acquire a lock before calling [io.Writer.Write] +to ensure that each record is written in one piece. User-defined +handlers are responsible for their own locking. +*/ +package slog diff --git a/vendor/golang.org/x/exp/slog/handler.go b/vendor/golang.org/x/exp/slog/handler.go new file mode 100644 index 0000000000..bd635cb818 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/handler.go @@ -0,0 +1,577 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "context" + "fmt" + "io" + "reflect" + "strconv" + "sync" + "time" + + "golang.org/x/exp/slices" + "golang.org/x/exp/slog/internal/buffer" +) + +// A Handler handles log records produced by a Logger.. +// +// A typical handler may print log records to standard error, +// or write them to a file or database, or perhaps augment them +// with additional attributes and pass them on to another handler. +// +// Any of the Handler's methods may be called concurrently with itself +// or with other methods. It is the responsibility of the Handler to +// manage this concurrency. +// +// Users of the slog package should not invoke Handler methods directly. +// They should use the methods of [Logger] instead. +type Handler interface { + // Enabled reports whether the handler handles records at the given level. + // The handler ignores records whose level is lower. + // It is called early, before any arguments are processed, + // to save effort if the log event should be discarded. + // If called from a Logger method, the first argument is the context + // passed to that method, or context.Background() if nil was passed + // or the method does not take a context. + // The context is passed so Enabled can use its values + // to make a decision. + Enabled(context.Context, Level) bool + + // Handle handles the Record. + // It will only be called when Enabled returns true. + // The Context argument is as for Enabled. + // It is present solely to provide Handlers access to the context's values. + // Canceling the context should not affect record processing. + // (Among other things, log messages may be necessary to debug a + // cancellation-related problem.) + // + // Handle methods that produce output should observe the following rules: + // - If r.Time is the zero time, ignore the time. + // - If r.PC is zero, ignore it. + // - Attr's values should be resolved. + // - If an Attr's key and value are both the zero value, ignore the Attr. + // This can be tested with attr.Equal(Attr{}). + // - If a group's key is empty, inline the group's Attrs. + // - If a group has no Attrs (even if it has a non-empty key), + // ignore it. + Handle(context.Context, Record) error + + // WithAttrs returns a new Handler whose attributes consist of + // both the receiver's attributes and the arguments. + // The Handler owns the slice: it may retain, modify or discard it. + WithAttrs(attrs []Attr) Handler + + // WithGroup returns a new Handler with the given group appended to + // the receiver's existing groups. + // The keys of all subsequent attributes, whether added by With or in a + // Record, should be qualified by the sequence of group names. + // + // How this qualification happens is up to the Handler, so long as + // this Handler's attribute keys differ from those of another Handler + // with a different sequence of group names. + // + // A Handler should treat WithGroup as starting a Group of Attrs that ends + // at the end of the log event. That is, + // + // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) + // + // should behave like + // + // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) + // + // If the name is empty, WithGroup returns the receiver. + WithGroup(name string) Handler +} + +type defaultHandler struct { + ch *commonHandler + // log.Output, except for testing + output func(calldepth int, message string) error +} + +func newDefaultHandler(output func(int, string) error) *defaultHandler { + return &defaultHandler{ + ch: &commonHandler{json: false}, + output: output, + } +} + +func (*defaultHandler) Enabled(_ context.Context, l Level) bool { + return l >= LevelInfo +} + +// Collect the level, attributes and message in a string and +// write it with the default log.Logger. +// Let the log.Logger handle time and file/line. +func (h *defaultHandler) Handle(ctx context.Context, r Record) error { + buf := buffer.New() + buf.WriteString(r.Level.String()) + buf.WriteByte(' ') + buf.WriteString(r.Message) + state := h.ch.newHandleState(buf, true, " ", nil) + defer state.free() + state.appendNonBuiltIns(r) + + // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] + return h.output(4, buf.String()) +} + +func (h *defaultHandler) WithAttrs(as []Attr) Handler { + return &defaultHandler{h.ch.withAttrs(as), h.output} +} + +func (h *defaultHandler) WithGroup(name string) Handler { + return &defaultHandler{h.ch.withGroup(name), h.output} +} + +// HandlerOptions are options for a TextHandler or JSONHandler. +// A zero HandlerOptions consists entirely of default values. +type HandlerOptions struct { + // AddSource causes the handler to compute the source code position + // of the log statement and add a SourceKey attribute to the output. + AddSource bool + + // Level reports the minimum record level that will be logged. + // The handler discards records with lower levels. + // If Level is nil, the handler assumes LevelInfo. + // The handler calls Level.Level for each record processed; + // to adjust the minimum level dynamically, use a LevelVar. + Level Leveler + + // ReplaceAttr is called to rewrite each non-group attribute before it is logged. + // The attribute's value has been resolved (see [Value.Resolve]). + // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. + // + // The built-in attributes with keys "time", "level", "source", and "msg" + // are passed to this function, except that time is omitted + // if zero, and source is omitted if AddSource is false. + // + // The first argument is a list of currently open groups that contain the + // Attr. It must not be retained or modified. ReplaceAttr is never called + // for Group attributes, only their contents. For example, the attribute + // list + // + // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) + // + // results in consecutive calls to ReplaceAttr with the following arguments: + // + // nil, Int("a", 1) + // []string{"g"}, Int("b", 2) + // nil, Int("c", 3) + // + // ReplaceAttr can be used to change the default keys of the built-in + // attributes, convert types (for example, to replace a `time.Time` with the + // integer seconds since the Unix epoch), sanitize personal information, or + // remove attributes from the output. + ReplaceAttr func(groups []string, a Attr) Attr +} + +// Keys for "built-in" attributes. +const ( + // TimeKey is the key used by the built-in handlers for the time + // when the log method is called. The associated Value is a [time.Time]. + TimeKey = "time" + // LevelKey is the key used by the built-in handlers for the level + // of the log call. The associated value is a [Level]. + LevelKey = "level" + // MessageKey is the key used by the built-in handlers for the + // message of the log call. The associated value is a string. + MessageKey = "msg" + // SourceKey is the key used by the built-in handlers for the source file + // and line of the log call. The associated value is a string. + SourceKey = "source" +) + +type commonHandler struct { + json bool // true => output JSON; false => output text + opts HandlerOptions + preformattedAttrs []byte + groupPrefix string // for text: prefix of groups opened in preformatting + groups []string // all groups started from WithGroup + nOpenGroups int // the number of groups opened in preformattedAttrs + mu sync.Mutex + w io.Writer +} + +func (h *commonHandler) clone() *commonHandler { + // We can't use assignment because we can't copy the mutex. + return &commonHandler{ + json: h.json, + opts: h.opts, + preformattedAttrs: slices.Clip(h.preformattedAttrs), + groupPrefix: h.groupPrefix, + groups: slices.Clip(h.groups), + nOpenGroups: h.nOpenGroups, + w: h.w, + } +} + +// enabled reports whether l is greater than or equal to the +// minimum level. +func (h *commonHandler) enabled(l Level) bool { + minLevel := LevelInfo + if h.opts.Level != nil { + minLevel = h.opts.Level.Level() + } + return l >= minLevel +} + +func (h *commonHandler) withAttrs(as []Attr) *commonHandler { + h2 := h.clone() + // Pre-format the attributes as an optimization. + prefix := buffer.New() + defer prefix.Free() + prefix.WriteString(h.groupPrefix) + state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) + defer state.free() + if len(h2.preformattedAttrs) > 0 { + state.sep = h.attrSep() + } + state.openGroups() + for _, a := range as { + state.appendAttr(a) + } + // Remember the new prefix for later keys. + h2.groupPrefix = state.prefix.String() + // Remember how many opened groups are in preformattedAttrs, + // so we don't open them again when we handle a Record. + h2.nOpenGroups = len(h2.groups) + return h2 +} + +func (h *commonHandler) withGroup(name string) *commonHandler { + if name == "" { + return h + } + h2 := h.clone() + h2.groups = append(h2.groups, name) + return h2 +} + +func (h *commonHandler) handle(r Record) error { + state := h.newHandleState(buffer.New(), true, "", nil) + defer state.free() + if h.json { + state.buf.WriteByte('{') + } + // Built-in attributes. They are not in a group. + stateGroups := state.groups + state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. + rep := h.opts.ReplaceAttr + // time + if !r.Time.IsZero() { + key := TimeKey + val := r.Time.Round(0) // strip monotonic to match Attr behavior + if rep == nil { + state.appendKey(key) + state.appendTime(val) + } else { + state.appendAttr(Time(key, val)) + } + } + // level + key := LevelKey + val := r.Level + if rep == nil { + state.appendKey(key) + state.appendString(val.String()) + } else { + state.appendAttr(Any(key, val)) + } + // source + if h.opts.AddSource { + state.appendAttr(Any(SourceKey, r.source())) + } + key = MessageKey + msg := r.Message + if rep == nil { + state.appendKey(key) + state.appendString(msg) + } else { + state.appendAttr(String(key, msg)) + } + state.groups = stateGroups // Restore groups passed to ReplaceAttrs. + state.appendNonBuiltIns(r) + state.buf.WriteByte('\n') + + h.mu.Lock() + defer h.mu.Unlock() + _, err := h.w.Write(*state.buf) + return err +} + +func (s *handleState) appendNonBuiltIns(r Record) { + // preformatted Attrs + if len(s.h.preformattedAttrs) > 0 { + s.buf.WriteString(s.sep) + s.buf.Write(s.h.preformattedAttrs) + s.sep = s.h.attrSep() + } + // Attrs in Record -- unlike the built-in ones, they are in groups started + // from WithGroup. + s.prefix = buffer.New() + defer s.prefix.Free() + s.prefix.WriteString(s.h.groupPrefix) + s.openGroups() + r.Attrs(func(a Attr) bool { + s.appendAttr(a) + return true + }) + if s.h.json { + // Close all open groups. + for range s.h.groups { + s.buf.WriteByte('}') + } + // Close the top-level object. + s.buf.WriteByte('}') + } +} + +// attrSep returns the separator between attributes. +func (h *commonHandler) attrSep() string { + if h.json { + return "," + } + return " " +} + +// handleState holds state for a single call to commonHandler.handle. +// The initial value of sep determines whether to emit a separator +// before the next key, after which it stays true. +type handleState struct { + h *commonHandler + buf *buffer.Buffer + freeBuf bool // should buf be freed? + sep string // separator to write before next key + prefix *buffer.Buffer // for text: key prefix + groups *[]string // pool-allocated slice of active groups, for ReplaceAttr +} + +var groupPool = sync.Pool{New: func() any { + s := make([]string, 0, 10) + return &s +}} + +func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { + s := handleState{ + h: h, + buf: buf, + freeBuf: freeBuf, + sep: sep, + prefix: prefix, + } + if h.opts.ReplaceAttr != nil { + s.groups = groupPool.Get().(*[]string) + *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) + } + return s +} + +func (s *handleState) free() { + if s.freeBuf { + s.buf.Free() + } + if gs := s.groups; gs != nil { + *gs = (*gs)[:0] + groupPool.Put(gs) + } +} + +func (s *handleState) openGroups() { + for _, n := range s.h.groups[s.h.nOpenGroups:] { + s.openGroup(n) + } +} + +// Separator for group names and keys. +const keyComponentSep = '.' + +// openGroup starts a new group of attributes +// with the given name. +func (s *handleState) openGroup(name string) { + if s.h.json { + s.appendKey(name) + s.buf.WriteByte('{') + s.sep = "" + } else { + s.prefix.WriteString(name) + s.prefix.WriteByte(keyComponentSep) + } + // Collect group names for ReplaceAttr. + if s.groups != nil { + *s.groups = append(*s.groups, name) + } +} + +// closeGroup ends the group with the given name. +func (s *handleState) closeGroup(name string) { + if s.h.json { + s.buf.WriteByte('}') + } else { + (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] + } + s.sep = s.h.attrSep() + if s.groups != nil { + *s.groups = (*s.groups)[:len(*s.groups)-1] + } +} + +// appendAttr appends the Attr's key and value using app. +// It handles replacement and checking for an empty key. +// after replacement). +func (s *handleState) appendAttr(a Attr) { + if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { + var gs []string + if s.groups != nil { + gs = *s.groups + } + // Resolve before calling ReplaceAttr, so the user doesn't have to. + a.Value = a.Value.Resolve() + a = rep(gs, a) + } + a.Value = a.Value.Resolve() + // Elide empty Attrs. + if a.isEmpty() { + return + } + // Special case: Source. + if v := a.Value; v.Kind() == KindAny { + if src, ok := v.Any().(*Source); ok { + if s.h.json { + a.Value = src.group() + } else { + a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) + } + } + } + if a.Value.Kind() == KindGroup { + attrs := a.Value.Group() + // Output only non-empty groups. + if len(attrs) > 0 { + // Inline a group with an empty key. + if a.Key != "" { + s.openGroup(a.Key) + } + for _, aa := range attrs { + s.appendAttr(aa) + } + if a.Key != "" { + s.closeGroup(a.Key) + } + } + } else { + s.appendKey(a.Key) + s.appendValue(a.Value) + } +} + +func (s *handleState) appendError(err error) { + s.appendString(fmt.Sprintf("!ERROR:%v", err)) +} + +func (s *handleState) appendKey(key string) { + s.buf.WriteString(s.sep) + if s.prefix != nil { + // TODO: optimize by avoiding allocation. + s.appendString(string(*s.prefix) + key) + } else { + s.appendString(key) + } + if s.h.json { + s.buf.WriteByte(':') + } else { + s.buf.WriteByte('=') + } + s.sep = s.h.attrSep() +} + +func (s *handleState) appendString(str string) { + if s.h.json { + s.buf.WriteByte('"') + *s.buf = appendEscapedJSONString(*s.buf, str) + s.buf.WriteByte('"') + } else { + // text + if needsQuoting(str) { + *s.buf = strconv.AppendQuote(*s.buf, str) + } else { + s.buf.WriteString(str) + } + } +} + +func (s *handleState) appendValue(v Value) { + defer func() { + if r := recover(); r != nil { + // If it panics with a nil pointer, the most likely cases are + // an encoding.TextMarshaler or error fails to guard against nil, + // in which case "" seems to be the feasible choice. + // + // Adapted from the code in fmt/print.go. + if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { + s.appendString("") + return + } + + // Otherwise just print the original panic message. + s.appendString(fmt.Sprintf("!PANIC: %v", r)) + } + }() + + var err error + if s.h.json { + err = appendJSONValue(s, v) + } else { + err = appendTextValue(s, v) + } + if err != nil { + s.appendError(err) + } +} + +func (s *handleState) appendTime(t time.Time) { + if s.h.json { + appendJSONTime(s, t) + } else { + writeTimeRFC3339Millis(s.buf, t) + } +} + +// This takes half the time of Time.AppendFormat. +func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { + year, month, day := t.Date() + buf.WritePosIntWidth(year, 4) + buf.WriteByte('-') + buf.WritePosIntWidth(int(month), 2) + buf.WriteByte('-') + buf.WritePosIntWidth(day, 2) + buf.WriteByte('T') + hour, min, sec := t.Clock() + buf.WritePosIntWidth(hour, 2) + buf.WriteByte(':') + buf.WritePosIntWidth(min, 2) + buf.WriteByte(':') + buf.WritePosIntWidth(sec, 2) + ns := t.Nanosecond() + buf.WriteByte('.') + buf.WritePosIntWidth(ns/1e6, 3) + _, offsetSeconds := t.Zone() + if offsetSeconds == 0 { + buf.WriteByte('Z') + } else { + offsetMinutes := offsetSeconds / 60 + if offsetMinutes < 0 { + buf.WriteByte('-') + offsetMinutes = -offsetMinutes + } else { + buf.WriteByte('+') + } + buf.WritePosIntWidth(offsetMinutes/60, 2) + buf.WriteByte(':') + buf.WritePosIntWidth(offsetMinutes%60, 2) + } +} diff --git a/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go new file mode 100644 index 0000000000..7786c166e0 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go @@ -0,0 +1,84 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package buffer provides a pool-allocated byte buffer. +package buffer + +import ( + "sync" +) + +// Buffer adapted from go/src/fmt/print.go +type Buffer []byte + +// Having an initial size gives a dramatic speedup. +var bufPool = sync.Pool{ + New: func() any { + b := make([]byte, 0, 1024) + return (*Buffer)(&b) + }, +} + +func New() *Buffer { + return bufPool.Get().(*Buffer) +} + +func (b *Buffer) Free() { + // To reduce peak allocation, return only smaller buffers to the pool. + const maxBufferSize = 16 << 10 + if cap(*b) <= maxBufferSize { + *b = (*b)[:0] + bufPool.Put(b) + } +} + +func (b *Buffer) Reset() { + *b = (*b)[:0] +} + +func (b *Buffer) Write(p []byte) (int, error) { + *b = append(*b, p...) + return len(p), nil +} + +func (b *Buffer) WriteString(s string) { + *b = append(*b, s...) +} + +func (b *Buffer) WriteByte(c byte) { + *b = append(*b, c) +} + +func (b *Buffer) WritePosInt(i int) { + b.WritePosIntWidth(i, 0) +} + +// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left +// by zeroes to the given width. Use a width of 0 to omit padding. +func (b *Buffer) WritePosIntWidth(i, width int) { + // Cheap integer to fixed-width decimal ASCII. + // Copied from log/log.go. + + if i < 0 { + panic("negative int") + } + + // Assemble decimal in reverse order. + var bb [20]byte + bp := len(bb) - 1 + for i >= 10 || width > 1 { + width-- + q := i / 10 + bb[bp] = byte('0' + i - q*10) + bp-- + i = q + } + // i < 10 + bb[bp] = byte('0' + i) + b.Write(bb[bp:]) +} + +func (b *Buffer) String() string { + return string(*b) +} diff --git a/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/vendor/golang.org/x/exp/slog/internal/ignorepc.go new file mode 100644 index 0000000000..d1256426ff --- /dev/null +++ b/vendor/golang.org/x/exp/slog/internal/ignorepc.go @@ -0,0 +1,9 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +// If IgnorePC is true, do not invoke runtime.Callers to get the pc. +// This is solely for benchmarking the slowdown from runtime.Callers. +var IgnorePC = false diff --git a/vendor/golang.org/x/exp/slog/json_handler.go b/vendor/golang.org/x/exp/slog/json_handler.go new file mode 100644 index 0000000000..157ada8692 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/json_handler.go @@ -0,0 +1,336 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "strconv" + "time" + "unicode/utf8" + + "golang.org/x/exp/slog/internal/buffer" +) + +// JSONHandler is a Handler that writes Records to an io.Writer as +// line-delimited JSON objects. +type JSONHandler struct { + *commonHandler +} + +// NewJSONHandler creates a JSONHandler that writes to w, +// using the given options. +// If opts is nil, the default options are used. +func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { + if opts == nil { + opts = &HandlerOptions{} + } + return &JSONHandler{ + &commonHandler{ + json: true, + w: w, + opts: *opts, + }, + } +} + +// Enabled reports whether the handler handles records at the given level. +// The handler ignores records whose level is lower. +func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { + return h.commonHandler.enabled(level) +} + +// WithAttrs returns a new JSONHandler whose attributes consists +// of h's attributes followed by attrs. +func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { + return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} +} + +func (h *JSONHandler) WithGroup(name string) Handler { + return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} +} + +// Handle formats its argument Record as a JSON object on a single line. +// +// If the Record's time is zero, the time is omitted. +// Otherwise, the key is "time" +// and the value is output as with json.Marshal. +// +// If the Record's level is zero, the level is omitted. +// Otherwise, the key is "level" +// and the value of [Level.String] is output. +// +// If the AddSource option is set and source information is available, +// the key is "source" +// and the value is output as "FILE:LINE". +// +// The message's key is "msg". +// +// To modify these or other attributes, or remove them from the output, use +// [HandlerOptions.ReplaceAttr]. +// +// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), +// with two exceptions. +// +// First, an Attr whose Value is of type error is formatted as a string, by +// calling its Error method. Only errors in Attrs receive this special treatment, +// not errors embedded in structs, slices, maps or other data structures that +// are processed by the encoding/json package. +// +// Second, an encoding failure does not cause Handle to return an error. +// Instead, the error message is formatted as a string. +// +// Each call to Handle results in a single serialized call to io.Writer.Write. +func (h *JSONHandler) Handle(_ context.Context, r Record) error { + return h.commonHandler.handle(r) +} + +// Adapted from time.Time.MarshalJSON to avoid allocation. +func appendJSONTime(s *handleState, t time.Time) { + if y := t.Year(); y < 0 || y >= 10000 { + // RFC 3339 is clear that years are 4 digits exactly. + // See golang.org/issue/4556#c15 for more discussion. + s.appendError(errors.New("time.Time year outside of range [0,9999]")) + } + s.buf.WriteByte('"') + *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) + s.buf.WriteByte('"') +} + +func appendJSONValue(s *handleState, v Value) error { + switch v.Kind() { + case KindString: + s.appendString(v.str()) + case KindInt64: + *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) + case KindUint64: + *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) + case KindFloat64: + // json.Marshal is funny about floats; it doesn't + // always match strconv.AppendFloat. So just call it. + // That's expensive, but floats are rare. + if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { + return err + } + case KindBool: + *s.buf = strconv.AppendBool(*s.buf, v.Bool()) + case KindDuration: + // Do what json.Marshal does. + *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) + case KindTime: + s.appendTime(v.Time()) + case KindAny: + a := v.Any() + _, jm := a.(json.Marshaler) + if err, ok := a.(error); ok && !jm { + s.appendString(err.Error()) + } else { + return appendJSONMarshal(s.buf, a) + } + default: + panic(fmt.Sprintf("bad kind: %s", v.Kind())) + } + return nil +} + +func appendJSONMarshal(buf *buffer.Buffer, v any) error { + // Use a json.Encoder to avoid escaping HTML. + var bb bytes.Buffer + enc := json.NewEncoder(&bb) + enc.SetEscapeHTML(false) + if err := enc.Encode(v); err != nil { + return err + } + bs := bb.Bytes() + buf.Write(bs[:len(bs)-1]) // remove final newline + return nil +} + +// appendEscapedJSONString escapes s for JSON and appends it to buf. +// It does not surround the string in quotation marks. +// +// Modified from encoding/json/encode.go:encodeState.string, +// with escapeHTML set to false. +func appendEscapedJSONString(buf []byte, s string) []byte { + char := func(b byte) { buf = append(buf, b) } + str := func(s string) { buf = append(buf, s...) } + + start := 0 + for i := 0; i < len(s); { + if b := s[i]; b < utf8.RuneSelf { + if safeSet[b] { + i++ + continue + } + if start < i { + str(s[start:i]) + } + char('\\') + switch b { + case '\\', '"': + char(b) + case '\n': + char('n') + case '\r': + char('r') + case '\t': + char('t') + default: + // This encodes bytes < 0x20 except for \t, \n and \r. + str(`u00`) + char(hex[b>>4]) + char(hex[b&0xF]) + } + i++ + start = i + continue + } + c, size := utf8.DecodeRuneInString(s[i:]) + if c == utf8.RuneError && size == 1 { + if start < i { + str(s[start:i]) + } + str(`\ufffd`) + i += size + start = i + continue + } + // U+2028 is LINE SEPARATOR. + // U+2029 is PARAGRAPH SEPARATOR. + // They are both technically valid characters in JSON strings, + // but don't work in JSONP, which has to be evaluated as JavaScript, + // and can lead to security holes there. It is valid JSON to + // escape them, so we do so unconditionally. + // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. + if c == '\u2028' || c == '\u2029' { + if start < i { + str(s[start:i]) + } + str(`\u202`) + char(hex[c&0xF]) + i += size + start = i + continue + } + i += size + } + if start < len(s) { + str(s[start:]) + } + return buf +} + +var hex = "0123456789abcdef" + +// Copied from encoding/json/tables.go. +// +// safeSet holds the value true if the ASCII character with the given array +// position can be represented inside a JSON string without any further +// escaping. +// +// All values are true except for the ASCII control characters (0-31), the +// double quote ("), and the backslash character ("\"). +var safeSet = [utf8.RuneSelf]bool{ + ' ': true, + '!': true, + '"': false, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '(': true, + ')': true, + '*': true, + '+': true, + ',': true, + '-': true, + '.': true, + '/': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + ':': true, + ';': true, + '<': true, + '=': true, + '>': true, + '?': true, + '@': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'V': true, + 'W': true, + 'X': true, + 'Y': true, + 'Z': true, + '[': true, + '\\': false, + ']': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '{': true, + '|': true, + '}': true, + '~': true, + '\u007f': true, +} diff --git a/vendor/golang.org/x/exp/slog/level.go b/vendor/golang.org/x/exp/slog/level.go new file mode 100644 index 0000000000..b2365f0aa5 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/level.go @@ -0,0 +1,201 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "errors" + "fmt" + "strconv" + "strings" + "sync/atomic" +) + +// A Level is the importance or severity of a log event. +// The higher the level, the more important or severe the event. +type Level int + +// Level numbers are inherently arbitrary, +// but we picked them to satisfy three constraints. +// Any system can map them to another numbering scheme if it wishes. +// +// First, we wanted the default level to be Info, Since Levels are ints, Info is +// the default value for int, zero. +// + +// Second, we wanted to make it easy to use levels to specify logger verbosity. +// Since a larger level means a more severe event, a logger that accepts events +// with smaller (or more negative) level means a more verbose logger. Logger +// verbosity is thus the negation of event severity, and the default verbosity +// of 0 accepts all events at least as severe as INFO. +// +// Third, we wanted some room between levels to accommodate schemes with named +// levels between ours. For example, Google Cloud Logging defines a Notice level +// between Info and Warn. Since there are only a few of these intermediate +// levels, the gap between the numbers need not be large. Our gap of 4 matches +// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the +// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog +// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog +// does not. But those OpenTelemetry levels can still be represented as slog +// Levels by using the appropriate integers. +// +// Names for common levels. +const ( + LevelDebug Level = -4 + LevelInfo Level = 0 + LevelWarn Level = 4 + LevelError Level = 8 +) + +// String returns a name for the level. +// If the level has a name, then that name +// in uppercase is returned. +// If the level is between named values, then +// an integer is appended to the uppercased name. +// Examples: +// +// LevelWarn.String() => "WARN" +// (LevelInfo+2).String() => "INFO+2" +func (l Level) String() string { + str := func(base string, val Level) string { + if val == 0 { + return base + } + return fmt.Sprintf("%s%+d", base, val) + } + + switch { + case l < LevelInfo: + return str("DEBUG", l-LevelDebug) + case l < LevelWarn: + return str("INFO", l-LevelInfo) + case l < LevelError: + return str("WARN", l-LevelWarn) + default: + return str("ERROR", l-LevelError) + } +} + +// MarshalJSON implements [encoding/json.Marshaler] +// by quoting the output of [Level.String]. +func (l Level) MarshalJSON() ([]byte, error) { + // AppendQuote is sufficient for JSON-encoding all Level strings. + // They don't contain any runes that would produce invalid JSON + // when escaped. + return strconv.AppendQuote(nil, l.String()), nil +} + +// UnmarshalJSON implements [encoding/json.Unmarshaler] +// It accepts any string produced by [Level.MarshalJSON], +// ignoring case. +// It also accepts numeric offsets that would result in a different string on +// output. For example, "Error-8" would marshal as "INFO". +func (l *Level) UnmarshalJSON(data []byte) error { + s, err := strconv.Unquote(string(data)) + if err != nil { + return err + } + return l.parse(s) +} + +// MarshalText implements [encoding.TextMarshaler] +// by calling [Level.String]. +func (l Level) MarshalText() ([]byte, error) { + return []byte(l.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler]. +// It accepts any string produced by [Level.MarshalText], +// ignoring case. +// It also accepts numeric offsets that would result in a different string on +// output. For example, "Error-8" would marshal as "INFO". +func (l *Level) UnmarshalText(data []byte) error { + return l.parse(string(data)) +} + +func (l *Level) parse(s string) (err error) { + defer func() { + if err != nil { + err = fmt.Errorf("slog: level string %q: %w", s, err) + } + }() + + name := s + offset := 0 + if i := strings.IndexAny(s, "+-"); i >= 0 { + name = s[:i] + offset, err = strconv.Atoi(s[i:]) + if err != nil { + return err + } + } + switch strings.ToUpper(name) { + case "DEBUG": + *l = LevelDebug + case "INFO": + *l = LevelInfo + case "WARN": + *l = LevelWarn + case "ERROR": + *l = LevelError + default: + return errors.New("unknown name") + } + *l += Level(offset) + return nil +} + +// Level returns the receiver. +// It implements Leveler. +func (l Level) Level() Level { return l } + +// A LevelVar is a Level variable, to allow a Handler level to change +// dynamically. +// It implements Leveler as well as a Set method, +// and it is safe for use by multiple goroutines. +// The zero LevelVar corresponds to LevelInfo. +type LevelVar struct { + val atomic.Int64 +} + +// Level returns v's level. +func (v *LevelVar) Level() Level { + return Level(int(v.val.Load())) +} + +// Set sets v's level to l. +func (v *LevelVar) Set(l Level) { + v.val.Store(int64(l)) +} + +func (v *LevelVar) String() string { + return fmt.Sprintf("LevelVar(%s)", v.Level()) +} + +// MarshalText implements [encoding.TextMarshaler] +// by calling [Level.MarshalText]. +func (v *LevelVar) MarshalText() ([]byte, error) { + return v.Level().MarshalText() +} + +// UnmarshalText implements [encoding.TextUnmarshaler] +// by calling [Level.UnmarshalText]. +func (v *LevelVar) UnmarshalText(data []byte) error { + var l Level + if err := l.UnmarshalText(data); err != nil { + return err + } + v.Set(l) + return nil +} + +// A Leveler provides a Level value. +// +// As Level itself implements Leveler, clients typically supply +// a Level value wherever a Leveler is needed, such as in HandlerOptions. +// Clients who need to vary the level dynamically can provide a more complex +// Leveler implementation such as *LevelVar. +type Leveler interface { + Level() Level +} diff --git a/vendor/golang.org/x/exp/slog/logger.go b/vendor/golang.org/x/exp/slog/logger.go new file mode 100644 index 0000000000..e87ec9936c --- /dev/null +++ b/vendor/golang.org/x/exp/slog/logger.go @@ -0,0 +1,343 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "context" + "log" + "runtime" + "sync/atomic" + "time" + + "golang.org/x/exp/slog/internal" +) + +var defaultLogger atomic.Value + +func init() { + defaultLogger.Store(New(newDefaultHandler(log.Output))) +} + +// Default returns the default Logger. +func Default() *Logger { return defaultLogger.Load().(*Logger) } + +// SetDefault makes l the default Logger. +// After this call, output from the log package's default Logger +// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. +func SetDefault(l *Logger) { + defaultLogger.Store(l) + // If the default's handler is a defaultHandler, then don't use a handleWriter, + // or we'll deadlock as they both try to acquire the log default mutex. + // The defaultHandler will use whatever the log default writer is currently + // set to, which is correct. + // This can occur with SetDefault(Default()). + // See TestSetDefault. + if _, ok := l.Handler().(*defaultHandler); !ok { + capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 + log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) + log.SetFlags(0) // we want just the log message, no time or location + } +} + +// handlerWriter is an io.Writer that calls a Handler. +// It is used to link the default log.Logger to the default slog.Logger. +type handlerWriter struct { + h Handler + level Level + capturePC bool +} + +func (w *handlerWriter) Write(buf []byte) (int, error) { + if !w.h.Enabled(context.Background(), w.level) { + return 0, nil + } + var pc uintptr + if !internal.IgnorePC && w.capturePC { + // skip [runtime.Callers, w.Write, Logger.Output, log.Print] + var pcs [1]uintptr + runtime.Callers(4, pcs[:]) + pc = pcs[0] + } + + // Remove final newline. + origLen := len(buf) // Report that the entire buf was written. + if len(buf) > 0 && buf[len(buf)-1] == '\n' { + buf = buf[:len(buf)-1] + } + r := NewRecord(time.Now(), w.level, string(buf), pc) + return origLen, w.h.Handle(context.Background(), r) +} + +// A Logger records structured information about each call to its +// Log, Debug, Info, Warn, and Error methods. +// For each call, it creates a Record and passes it to a Handler. +// +// To create a new Logger, call [New] or a Logger method +// that begins "With". +type Logger struct { + handler Handler // for structured logging +} + +func (l *Logger) clone() *Logger { + c := *l + return &c +} + +// Handler returns l's Handler. +func (l *Logger) Handler() Handler { return l.handler } + +// With returns a new Logger that includes the given arguments, converted to +// Attrs as in [Logger.Log]. +// The Attrs will be added to each output from the Logger. +// The new Logger shares the old Logger's context. +// The new Logger's handler is the result of calling WithAttrs on the receiver's +// handler. +func (l *Logger) With(args ...any) *Logger { + c := l.clone() + c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) + return c +} + +// WithGroup returns a new Logger that starts a group. The keys of all +// attributes added to the Logger will be qualified by the given name. +// (How that qualification happens depends on the [Handler.WithGroup] +// method of the Logger's Handler.) +// The new Logger shares the old Logger's context. +// +// The new Logger's handler is the result of calling WithGroup on the receiver's +// handler. +func (l *Logger) WithGroup(name string) *Logger { + c := l.clone() + c.handler = l.handler.WithGroup(name) + return c + +} + +// New creates a new Logger with the given non-nil Handler and a nil context. +func New(h Handler) *Logger { + if h == nil { + panic("nil Handler") + } + return &Logger{handler: h} +} + +// With calls Logger.With on the default logger. +func With(args ...any) *Logger { + return Default().With(args...) +} + +// Enabled reports whether l emits log records at the given context and level. +func (l *Logger) Enabled(ctx context.Context, level Level) bool { + if ctx == nil { + ctx = context.Background() + } + return l.Handler().Enabled(ctx, level) +} + +// NewLogLogger returns a new log.Logger such that each call to its Output method +// dispatches a Record to the specified handler. The logger acts as a bridge from +// the older log API to newer structured logging handlers. +func NewLogLogger(h Handler, level Level) *log.Logger { + return log.New(&handlerWriter{h, level, true}, "", 0) +} + +// Log emits a log record with the current time and the given level and message. +// The Record's Attrs consist of the Logger's attributes followed by +// the Attrs specified by args. +// +// The attribute arguments are processed as follows: +// - If an argument is an Attr, it is used as is. +// - If an argument is a string and this is not the last argument, +// the following argument is treated as the value and the two are combined +// into an Attr. +// - Otherwise, the argument is treated as a value with key "!BADKEY". +func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { + l.log(ctx, level, msg, args...) +} + +// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. +func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { + l.logAttrs(ctx, level, msg, attrs...) +} + +// Debug logs at LevelDebug. +func (l *Logger) Debug(msg string, args ...any) { + l.log(nil, LevelDebug, msg, args...) +} + +// DebugContext logs at LevelDebug with the given context. +func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelDebug, msg, args...) +} + +// DebugCtx logs at LevelDebug with the given context. +// Deprecated: Use Logger.DebugContext. +func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelDebug, msg, args...) +} + +// Info logs at LevelInfo. +func (l *Logger) Info(msg string, args ...any) { + l.log(nil, LevelInfo, msg, args...) +} + +// InfoContext logs at LevelInfo with the given context. +func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelInfo, msg, args...) +} + +// InfoCtx logs at LevelInfo with the given context. +// Deprecated: Use Logger.InfoContext. +func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelInfo, msg, args...) +} + +// Warn logs at LevelWarn. +func (l *Logger) Warn(msg string, args ...any) { + l.log(nil, LevelWarn, msg, args...) +} + +// WarnContext logs at LevelWarn with the given context. +func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelWarn, msg, args...) +} + +// WarnCtx logs at LevelWarn with the given context. +// Deprecated: Use Logger.WarnContext. +func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelWarn, msg, args...) +} + +// Error logs at LevelError. +func (l *Logger) Error(msg string, args ...any) { + l.log(nil, LevelError, msg, args...) +} + +// ErrorContext logs at LevelError with the given context. +func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelError, msg, args...) +} + +// ErrorCtx logs at LevelError with the given context. +// Deprecated: Use Logger.ErrorContext. +func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { + l.log(ctx, LevelError, msg, args...) +} + +// log is the low-level logging method for methods that take ...any. +// It must always be called directly by an exported logging method +// or function, because it uses a fixed call depth to obtain the pc. +func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { + if !l.Enabled(ctx, level) { + return + } + var pc uintptr + if !internal.IgnorePC { + var pcs [1]uintptr + // skip [runtime.Callers, this function, this function's caller] + runtime.Callers(3, pcs[:]) + pc = pcs[0] + } + r := NewRecord(time.Now(), level, msg, pc) + r.Add(args...) + if ctx == nil { + ctx = context.Background() + } + _ = l.Handler().Handle(ctx, r) +} + +// logAttrs is like [Logger.log], but for methods that take ...Attr. +func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { + if !l.Enabled(ctx, level) { + return + } + var pc uintptr + if !internal.IgnorePC { + var pcs [1]uintptr + // skip [runtime.Callers, this function, this function's caller] + runtime.Callers(3, pcs[:]) + pc = pcs[0] + } + r := NewRecord(time.Now(), level, msg, pc) + r.AddAttrs(attrs...) + if ctx == nil { + ctx = context.Background() + } + _ = l.Handler().Handle(ctx, r) +} + +// Debug calls Logger.Debug on the default logger. +func Debug(msg string, args ...any) { + Default().log(nil, LevelDebug, msg, args...) +} + +// DebugContext calls Logger.DebugContext on the default logger. +func DebugContext(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelDebug, msg, args...) +} + +// Info calls Logger.Info on the default logger. +func Info(msg string, args ...any) { + Default().log(nil, LevelInfo, msg, args...) +} + +// InfoContext calls Logger.InfoContext on the default logger. +func InfoContext(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelInfo, msg, args...) +} + +// Warn calls Logger.Warn on the default logger. +func Warn(msg string, args ...any) { + Default().log(nil, LevelWarn, msg, args...) +} + +// WarnContext calls Logger.WarnContext on the default logger. +func WarnContext(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelWarn, msg, args...) +} + +// Error calls Logger.Error on the default logger. +func Error(msg string, args ...any) { + Default().log(nil, LevelError, msg, args...) +} + +// ErrorContext calls Logger.ErrorContext on the default logger. +func ErrorContext(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelError, msg, args...) +} + +// DebugCtx calls Logger.DebugContext on the default logger. +// Deprecated: call DebugContext. +func DebugCtx(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelDebug, msg, args...) +} + +// InfoCtx calls Logger.InfoContext on the default logger. +// Deprecated: call InfoContext. +func InfoCtx(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelInfo, msg, args...) +} + +// WarnCtx calls Logger.WarnContext on the default logger. +// Deprecated: call WarnContext. +func WarnCtx(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelWarn, msg, args...) +} + +// ErrorCtx calls Logger.ErrorContext on the default logger. +// Deprecated: call ErrorContext. +func ErrorCtx(ctx context.Context, msg string, args ...any) { + Default().log(ctx, LevelError, msg, args...) +} + +// Log calls Logger.Log on the default logger. +func Log(ctx context.Context, level Level, msg string, args ...any) { + Default().log(ctx, level, msg, args...) +} + +// LogAttrs calls Logger.LogAttrs on the default logger. +func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { + Default().logAttrs(ctx, level, msg, attrs...) +} diff --git a/vendor/golang.org/x/exp/slog/noplog.bench b/vendor/golang.org/x/exp/slog/noplog.bench new file mode 100644 index 0000000000..ed9296ff61 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/noplog.bench @@ -0,0 +1,36 @@ +goos: linux +goarch: amd64 +pkg: golang.org/x/exp/slog +cpu: Intel(R) Xeon(R) CPU @ 2.20GHz +BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op +BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op +PASS +ok golang.org/x/exp/slog 40.566s diff --git a/vendor/golang.org/x/exp/slog/record.go b/vendor/golang.org/x/exp/slog/record.go new file mode 100644 index 0000000000..38b3440f77 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/record.go @@ -0,0 +1,207 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "runtime" + "time" + + "golang.org/x/exp/slices" +) + +const nAttrsInline = 5 + +// A Record holds information about a log event. +// Copies of a Record share state. +// Do not modify a Record after handing out a copy to it. +// Use [Record.Clone] to create a copy with no shared state. +type Record struct { + // The time at which the output method (Log, Info, etc.) was called. + Time time.Time + + // The log message. + Message string + + // The level of the event. + Level Level + + // The program counter at the time the record was constructed, as determined + // by runtime.Callers. If zero, no program counter is available. + // + // The only valid use for this value is as an argument to + // [runtime.CallersFrames]. In particular, it must not be passed to + // [runtime.FuncForPC]. + PC uintptr + + // Allocation optimization: an inline array sized to hold + // the majority of log calls (based on examination of open-source + // code). It holds the start of the list of Attrs. + front [nAttrsInline]Attr + + // The number of Attrs in front. + nFront int + + // The list of Attrs except for those in front. + // Invariants: + // - len(back) > 0 iff nFront == len(front) + // - Unused array elements are zero. Used to detect mistakes. + back []Attr +} + +// NewRecord creates a Record from the given arguments. +// Use [Record.AddAttrs] to add attributes to the Record. +// +// NewRecord is intended for logging APIs that want to support a [Handler] as +// a backend. +func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { + return Record{ + Time: t, + Message: msg, + Level: level, + PC: pc, + } +} + +// Clone returns a copy of the record with no shared state. +// The original record and the clone can both be modified +// without interfering with each other. +func (r Record) Clone() Record { + r.back = slices.Clip(r.back) // prevent append from mutating shared array + return r +} + +// NumAttrs returns the number of attributes in the Record. +func (r Record) NumAttrs() int { + return r.nFront + len(r.back) +} + +// Attrs calls f on each Attr in the Record. +// Iteration stops if f returns false. +func (r Record) Attrs(f func(Attr) bool) { + for i := 0; i < r.nFront; i++ { + if !f(r.front[i]) { + return + } + } + for _, a := range r.back { + if !f(a) { + return + } + } +} + +// AddAttrs appends the given Attrs to the Record's list of Attrs. +func (r *Record) AddAttrs(attrs ...Attr) { + n := copy(r.front[r.nFront:], attrs) + r.nFront += n + // Check if a copy was modified by slicing past the end + // and seeing if the Attr there is non-zero. + if cap(r.back) > len(r.back) { + end := r.back[:len(r.back)+1][len(r.back)] + if !end.isEmpty() { + panic("copies of a slog.Record were both modified") + } + } + r.back = append(r.back, attrs[n:]...) +} + +// Add converts the args to Attrs as described in [Logger.Log], +// then appends the Attrs to the Record's list of Attrs. +func (r *Record) Add(args ...any) { + var a Attr + for len(args) > 0 { + a, args = argsToAttr(args) + if r.nFront < len(r.front) { + r.front[r.nFront] = a + r.nFront++ + } else { + if r.back == nil { + r.back = make([]Attr, 0, countAttrs(args)) + } + r.back = append(r.back, a) + } + } + +} + +// countAttrs returns the number of Attrs that would be created from args. +func countAttrs(args []any) int { + n := 0 + for i := 0; i < len(args); i++ { + n++ + if _, ok := args[i].(string); ok { + i++ + } + } + return n +} + +const badKey = "!BADKEY" + +// argsToAttr turns a prefix of the nonempty args slice into an Attr +// and returns the unconsumed portion of the slice. +// If args[0] is an Attr, it returns it. +// If args[0] is a string, it treats the first two elements as +// a key-value pair. +// Otherwise, it treats args[0] as a value with a missing key. +func argsToAttr(args []any) (Attr, []any) { + switch x := args[0].(type) { + case string: + if len(args) == 1 { + return String(badKey, x), nil + } + return Any(x, args[1]), args[2:] + + case Attr: + return x, args[1:] + + default: + return Any(badKey, x), args[1:] + } +} + +// Source describes the location of a line of source code. +type Source struct { + // Function is the package path-qualified function name containing the + // source line. If non-empty, this string uniquely identifies a single + // function in the program. This may be the empty string if not known. + Function string `json:"function"` + // File and Line are the file name and line number (1-based) of the source + // line. These may be the empty string and zero, respectively, if not known. + File string `json:"file"` + Line int `json:"line"` +} + +// attrs returns the non-zero fields of s as a slice of attrs. +// It is similar to a LogValue method, but we don't want Source +// to implement LogValuer because it would be resolved before +// the ReplaceAttr function was called. +func (s *Source) group() Value { + var as []Attr + if s.Function != "" { + as = append(as, String("function", s.Function)) + } + if s.File != "" { + as = append(as, String("file", s.File)) + } + if s.Line != 0 { + as = append(as, Int("line", s.Line)) + } + return GroupValue(as...) +} + +// source returns a Source for the log event. +// If the Record was created without the necessary information, +// or if the location is unavailable, it returns a non-nil *Source +// with zero fields. +func (r Record) source() *Source { + fs := runtime.CallersFrames([]uintptr{r.PC}) + f, _ := fs.Next() + return &Source{ + Function: f.Function, + File: f.File, + Line: f.Line, + } +} diff --git a/vendor/golang.org/x/exp/slog/text_handler.go b/vendor/golang.org/x/exp/slog/text_handler.go new file mode 100644 index 0000000000..75b66b716f --- /dev/null +++ b/vendor/golang.org/x/exp/slog/text_handler.go @@ -0,0 +1,161 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "context" + "encoding" + "fmt" + "io" + "reflect" + "strconv" + "unicode" + "unicode/utf8" +) + +// TextHandler is a Handler that writes Records to an io.Writer as a +// sequence of key=value pairs separated by spaces and followed by a newline. +type TextHandler struct { + *commonHandler +} + +// NewTextHandler creates a TextHandler that writes to w, +// using the given options. +// If opts is nil, the default options are used. +func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { + if opts == nil { + opts = &HandlerOptions{} + } + return &TextHandler{ + &commonHandler{ + json: false, + w: w, + opts: *opts, + }, + } +} + +// Enabled reports whether the handler handles records at the given level. +// The handler ignores records whose level is lower. +func (h *TextHandler) Enabled(_ context.Context, level Level) bool { + return h.commonHandler.enabled(level) +} + +// WithAttrs returns a new TextHandler whose attributes consists +// of h's attributes followed by attrs. +func (h *TextHandler) WithAttrs(attrs []Attr) Handler { + return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} +} + +func (h *TextHandler) WithGroup(name string) Handler { + return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} +} + +// Handle formats its argument Record as a single line of space-separated +// key=value items. +// +// If the Record's time is zero, the time is omitted. +// Otherwise, the key is "time" +// and the value is output in RFC3339 format with millisecond precision. +// +// If the Record's level is zero, the level is omitted. +// Otherwise, the key is "level" +// and the value of [Level.String] is output. +// +// If the AddSource option is set and source information is available, +// the key is "source" and the value is output as FILE:LINE. +// +// The message's key is "msg". +// +// To modify these or other attributes, or remove them from the output, use +// [HandlerOptions.ReplaceAttr]. +// +// If a value implements [encoding.TextMarshaler], the result of MarshalText is +// written. Otherwise, the result of fmt.Sprint is written. +// +// Keys and values are quoted with [strconv.Quote] if they contain Unicode space +// characters, non-printing characters, '"' or '='. +// +// Keys inside groups consist of components (keys or group names) separated by +// dots. No further escaping is performed. +// Thus there is no way to determine from the key "a.b.c" whether there +// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", +// or single group "a" and a key "b.c". +// If it is necessary to reconstruct the group structure of a key +// even in the presence of dots inside components, use +// [HandlerOptions.ReplaceAttr] to encode that information in the key. +// +// Each call to Handle results in a single serialized call to +// io.Writer.Write. +func (h *TextHandler) Handle(_ context.Context, r Record) error { + return h.commonHandler.handle(r) +} + +func appendTextValue(s *handleState, v Value) error { + switch v.Kind() { + case KindString: + s.appendString(v.str()) + case KindTime: + s.appendTime(v.time()) + case KindAny: + if tm, ok := v.any.(encoding.TextMarshaler); ok { + data, err := tm.MarshalText() + if err != nil { + return err + } + // TODO: avoid the conversion to string. + s.appendString(string(data)) + return nil + } + if bs, ok := byteSlice(v.any); ok { + // As of Go 1.19, this only allocates for strings longer than 32 bytes. + s.buf.WriteString(strconv.Quote(string(bs))) + return nil + } + s.appendString(fmt.Sprintf("%+v", v.Any())) + default: + *s.buf = v.append(*s.buf) + } + return nil +} + +// byteSlice returns its argument as a []byte if the argument's +// underlying type is []byte, along with a second return value of true. +// Otherwise it returns nil, false. +func byteSlice(a any) ([]byte, bool) { + if bs, ok := a.([]byte); ok { + return bs, true + } + // Like Printf's %s, we allow both the slice type and the byte element type to be named. + t := reflect.TypeOf(a) + if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { + return reflect.ValueOf(a).Bytes(), true + } + return nil, false +} + +func needsQuoting(s string) bool { + if len(s) == 0 { + return true + } + for i := 0; i < len(s); { + b := s[i] + if b < utf8.RuneSelf { + // Quote anything except a backslash that would need quoting in a + // JSON string, as well as space and '=' + if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { + return true + } + i++ + continue + } + r, size := utf8.DecodeRuneInString(s[i:]) + if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { + return true + } + i += size + } + return false +} diff --git a/vendor/golang.org/x/exp/slog/value.go b/vendor/golang.org/x/exp/slog/value.go new file mode 100644 index 0000000000..3550c46fc0 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/value.go @@ -0,0 +1,456 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slog + +import ( + "fmt" + "math" + "runtime" + "strconv" + "strings" + "time" + "unsafe" + + "golang.org/x/exp/slices" +) + +// A Value can represent any Go value, but unlike type any, +// it can represent most small values without an allocation. +// The zero Value corresponds to nil. +type Value struct { + _ [0]func() // disallow == + // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, + // the string length for KindString, and nanoseconds since the epoch for KindTime. + num uint64 + // If any is of type Kind, then the value is in num as described above. + // If any is of type *time.Location, then the Kind is Time and time.Time value + // can be constructed from the Unix nanos in num and the location (monotonic time + // is not preserved). + // If any is of type stringptr, then the Kind is String and the string value + // consists of the length in num and the pointer in any. + // Otherwise, the Kind is Any and any is the value. + // (This implies that Attrs cannot store values of type Kind, *time.Location + // or stringptr.) + any any +} + +// Kind is the kind of a Value. +type Kind int + +// The following list is sorted alphabetically, but it's also important that +// KindAny is 0 so that a zero Value represents nil. + +const ( + KindAny Kind = iota + KindBool + KindDuration + KindFloat64 + KindInt64 + KindString + KindTime + KindUint64 + KindGroup + KindLogValuer +) + +var kindStrings = []string{ + "Any", + "Bool", + "Duration", + "Float64", + "Int64", + "String", + "Time", + "Uint64", + "Group", + "LogValuer", +} + +func (k Kind) String() string { + if k >= 0 && int(k) < len(kindStrings) { + return kindStrings[k] + } + return "" +} + +// Unexported version of Kind, just so we can store Kinds in Values. +// (No user-provided value has this type.) +type kind Kind + +// Kind returns v's Kind. +func (v Value) Kind() Kind { + switch x := v.any.(type) { + case Kind: + return x + case stringptr: + return KindString + case timeLocation: + return KindTime + case groupptr: + return KindGroup + case LogValuer: + return KindLogValuer + case kind: // a kind is just a wrapper for a Kind + return KindAny + default: + return KindAny + } +} + +//////////////// Constructors + +// IntValue returns a Value for an int. +func IntValue(v int) Value { + return Int64Value(int64(v)) +} + +// Int64Value returns a Value for an int64. +func Int64Value(v int64) Value { + return Value{num: uint64(v), any: KindInt64} +} + +// Uint64Value returns a Value for a uint64. +func Uint64Value(v uint64) Value { + return Value{num: v, any: KindUint64} +} + +// Float64Value returns a Value for a floating-point number. +func Float64Value(v float64) Value { + return Value{num: math.Float64bits(v), any: KindFloat64} +} + +// BoolValue returns a Value for a bool. +func BoolValue(v bool) Value { + u := uint64(0) + if v { + u = 1 + } + return Value{num: u, any: KindBool} +} + +// Unexported version of *time.Location, just so we can store *time.Locations in +// Values. (No user-provided value has this type.) +type timeLocation *time.Location + +// TimeValue returns a Value for a time.Time. +// It discards the monotonic portion. +func TimeValue(v time.Time) Value { + if v.IsZero() { + // UnixNano on the zero time is undefined, so represent the zero time + // with a nil *time.Location instead. time.Time.Location method never + // returns nil, so a Value with any == timeLocation(nil) cannot be + // mistaken for any other Value, time.Time or otherwise. + return Value{any: timeLocation(nil)} + } + return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} +} + +// DurationValue returns a Value for a time.Duration. +func DurationValue(v time.Duration) Value { + return Value{num: uint64(v.Nanoseconds()), any: KindDuration} +} + +// AnyValue returns a Value for the supplied value. +// +// If the supplied value is of type Value, it is returned +// unmodified. +// +// Given a value of one of Go's predeclared string, bool, or +// (non-complex) numeric types, AnyValue returns a Value of kind +// String, Bool, Uint64, Int64, or Float64. The width of the +// original numeric type is not preserved. +// +// Given a time.Time or time.Duration value, AnyValue returns a Value of kind +// KindTime or KindDuration. The monotonic time is not preserved. +// +// For nil, or values of all other types, including named types whose +// underlying type is numeric, AnyValue returns a value of kind KindAny. +func AnyValue(v any) Value { + switch v := v.(type) { + case string: + return StringValue(v) + case int: + return Int64Value(int64(v)) + case uint: + return Uint64Value(uint64(v)) + case int64: + return Int64Value(v) + case uint64: + return Uint64Value(v) + case bool: + return BoolValue(v) + case time.Duration: + return DurationValue(v) + case time.Time: + return TimeValue(v) + case uint8: + return Uint64Value(uint64(v)) + case uint16: + return Uint64Value(uint64(v)) + case uint32: + return Uint64Value(uint64(v)) + case uintptr: + return Uint64Value(uint64(v)) + case int8: + return Int64Value(int64(v)) + case int16: + return Int64Value(int64(v)) + case int32: + return Int64Value(int64(v)) + case float64: + return Float64Value(v) + case float32: + return Float64Value(float64(v)) + case []Attr: + return GroupValue(v...) + case Kind: + return Value{any: kind(v)} + case Value: + return v + default: + return Value{any: v} + } +} + +//////////////// Accessors + +// Any returns v's value as an any. +func (v Value) Any() any { + switch v.Kind() { + case KindAny: + if k, ok := v.any.(kind); ok { + return Kind(k) + } + return v.any + case KindLogValuer: + return v.any + case KindGroup: + return v.group() + case KindInt64: + return int64(v.num) + case KindUint64: + return v.num + case KindFloat64: + return v.float() + case KindString: + return v.str() + case KindBool: + return v.bool() + case KindDuration: + return v.duration() + case KindTime: + return v.time() + default: + panic(fmt.Sprintf("bad kind: %s", v.Kind())) + } +} + +// Int64 returns v's value as an int64. It panics +// if v is not a signed integer. +func (v Value) Int64() int64 { + if g, w := v.Kind(), KindInt64; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + return int64(v.num) +} + +// Uint64 returns v's value as a uint64. It panics +// if v is not an unsigned integer. +func (v Value) Uint64() uint64 { + if g, w := v.Kind(), KindUint64; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + return v.num +} + +// Bool returns v's value as a bool. It panics +// if v is not a bool. +func (v Value) Bool() bool { + if g, w := v.Kind(), KindBool; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + return v.bool() +} + +func (v Value) bool() bool { + return v.num == 1 +} + +// Duration returns v's value as a time.Duration. It panics +// if v is not a time.Duration. +func (v Value) Duration() time.Duration { + if g, w := v.Kind(), KindDuration; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + + return v.duration() +} + +func (v Value) duration() time.Duration { + return time.Duration(int64(v.num)) +} + +// Float64 returns v's value as a float64. It panics +// if v is not a float64. +func (v Value) Float64() float64 { + if g, w := v.Kind(), KindFloat64; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + + return v.float() +} + +func (v Value) float() float64 { + return math.Float64frombits(v.num) +} + +// Time returns v's value as a time.Time. It panics +// if v is not a time.Time. +func (v Value) Time() time.Time { + if g, w := v.Kind(), KindTime; g != w { + panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) + } + return v.time() +} + +func (v Value) time() time.Time { + loc := v.any.(timeLocation) + if loc == nil { + return time.Time{} + } + return time.Unix(0, int64(v.num)).In(loc) +} + +// LogValuer returns v's value as a LogValuer. It panics +// if v is not a LogValuer. +func (v Value) LogValuer() LogValuer { + return v.any.(LogValuer) +} + +// Group returns v's value as a []Attr. +// It panics if v's Kind is not KindGroup. +func (v Value) Group() []Attr { + if sp, ok := v.any.(groupptr); ok { + return unsafe.Slice((*Attr)(sp), v.num) + } + panic("Group: bad kind") +} + +func (v Value) group() []Attr { + return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) +} + +//////////////// Other + +// Equal reports whether v and w represent the same Go value. +func (v Value) Equal(w Value) bool { + k1 := v.Kind() + k2 := w.Kind() + if k1 != k2 { + return false + } + switch k1 { + case KindInt64, KindUint64, KindBool, KindDuration: + return v.num == w.num + case KindString: + return v.str() == w.str() + case KindFloat64: + return v.float() == w.float() + case KindTime: + return v.time().Equal(w.time()) + case KindAny, KindLogValuer: + return v.any == w.any // may panic if non-comparable + case KindGroup: + return slices.EqualFunc(v.group(), w.group(), Attr.Equal) + default: + panic(fmt.Sprintf("bad kind: %s", k1)) + } +} + +// append appends a text representation of v to dst. +// v is formatted as with fmt.Sprint. +func (v Value) append(dst []byte) []byte { + switch v.Kind() { + case KindString: + return append(dst, v.str()...) + case KindInt64: + return strconv.AppendInt(dst, int64(v.num), 10) + case KindUint64: + return strconv.AppendUint(dst, v.num, 10) + case KindFloat64: + return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) + case KindBool: + return strconv.AppendBool(dst, v.bool()) + case KindDuration: + return append(dst, v.duration().String()...) + case KindTime: + return append(dst, v.time().String()...) + case KindGroup: + return fmt.Append(dst, v.group()) + case KindAny, KindLogValuer: + return fmt.Append(dst, v.any) + default: + panic(fmt.Sprintf("bad kind: %s", v.Kind())) + } +} + +// A LogValuer is any Go value that can convert itself into a Value for logging. +// +// This mechanism may be used to defer expensive operations until they are +// needed, or to expand a single value into a sequence of components. +type LogValuer interface { + LogValue() Value +} + +const maxLogValues = 100 + +// Resolve repeatedly calls LogValue on v while it implements LogValuer, +// and returns the result. +// If v resolves to a group, the group's attributes' values are not recursively +// resolved. +// If the number of LogValue calls exceeds a threshold, a Value containing an +// error is returned. +// Resolve's return value is guaranteed not to be of Kind KindLogValuer. +func (v Value) Resolve() (rv Value) { + orig := v + defer func() { + if r := recover(); r != nil { + rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) + } + }() + + for i := 0; i < maxLogValues; i++ { + if v.Kind() != KindLogValuer { + return v + } + v = v.LogValuer().LogValue() + } + err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) + return AnyValue(err) +} + +func stack(skip, nFrames int) string { + pcs := make([]uintptr, nFrames+1) + n := runtime.Callers(skip+1, pcs) + if n == 0 { + return "(no stack)" + } + frames := runtime.CallersFrames(pcs[:n]) + var b strings.Builder + i := 0 + for { + frame, more := frames.Next() + fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) + if !more { + break + } + i++ + if i >= nFrames { + fmt.Fprintf(&b, "(rest of stack elided)\n") + break + } + } + return b.String() +} diff --git a/vendor/golang.org/x/exp/slog/value_119.go b/vendor/golang.org/x/exp/slog/value_119.go new file mode 100644 index 0000000000..29b0d73292 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/value_119.go @@ -0,0 +1,53 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.19 && !go1.20 + +package slog + +import ( + "reflect" + "unsafe" +) + +type ( + stringptr unsafe.Pointer // used in Value.any when the Value is a string + groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr +) + +// StringValue returns a new Value for a string. +func StringValue(value string) Value { + hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) + return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} +} + +func (v Value) str() string { + var s string + hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) + hdr.Data = uintptr(v.any.(stringptr)) + hdr.Len = int(v.num) + return s +} + +// String returns Value's value as a string, formatted like fmt.Sprint. Unlike +// the methods Int64, Float64, and so on, which panic if v is of the +// wrong kind, String never panics. +func (v Value) String() string { + if sp, ok := v.any.(stringptr); ok { + // Inlining this code makes a huge difference. + var s string + hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) + hdr.Data = uintptr(sp) + hdr.Len = int(v.num) + return s + } + return string(v.append(nil)) +} + +// GroupValue returns a new Value for a list of Attrs. +// The caller must not subsequently mutate the argument slice. +func GroupValue(as ...Attr) Value { + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) + return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} +} diff --git a/vendor/golang.org/x/exp/slog/value_120.go b/vendor/golang.org/x/exp/slog/value_120.go new file mode 100644 index 0000000000..f7d4c09325 --- /dev/null +++ b/vendor/golang.org/x/exp/slog/value_120.go @@ -0,0 +1,39 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.20 + +package slog + +import "unsafe" + +type ( + stringptr *byte // used in Value.any when the Value is a string + groupptr *Attr // used in Value.any when the Value is a []Attr +) + +// StringValue returns a new Value for a string. +func StringValue(value string) Value { + return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} +} + +// GroupValue returns a new Value for a list of Attrs. +// The caller must not subsequently mutate the argument slice. +func GroupValue(as ...Attr) Value { + return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} +} + +// String returns Value's value as a string, formatted like fmt.Sprint. Unlike +// the methods Int64, Float64, and so on, which panic if v is of the +// wrong kind, String never panics. +func (v Value) String() string { + if sp, ok := v.any.(stringptr); ok { + return unsafe.String(sp, v.num) + } + return string(v.append(nil)) +} + +func (v Value) str() string { + return unsafe.String(v.any.(stringptr), v.num) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 044d64cd95..8992dc2f0a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -370,7 +370,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.22.1-0.20240730105121-548644c31544 +# github.com/cs3org/reva/v2 v2.22.1-0.20240806075425-8bcdd93dfa20 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime @@ -659,6 +659,7 @@ github.com/cs3org/reva/v2/pkg/storage/fs/eos github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpc github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpchome github.com/cs3org/reva/v2/pkg/storage/fs/eoshome +github.com/cs3org/reva/v2/pkg/storage/fs/hello github.com/cs3org/reva/v2/pkg/storage/fs/loader github.com/cs3org/reva/v2/pkg/storage/fs/local github.com/cs3org/reva/v2/pkg/storage/fs/localhome @@ -1884,6 +1885,9 @@ github.com/trustelem/zxcvbn/scoring # github.com/tus/tusd v1.13.0 ## explicit; go 1.16 github.com/tus/tusd/pkg/handler +# github.com/tus/tusd/v2 v2.4.0 +## explicit; go 1.20 +github.com/tus/tusd/v2/pkg/handler # github.com/unrolled/secure v1.14.0 => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c ## explicit; go 1.13 github.com/unrolled/secure @@ -2156,6 +2160,9 @@ golang.org/x/crypto/ssh/knownhosts golang.org/x/exp/constraints golang.org/x/exp/maps golang.org/x/exp/slices +golang.org/x/exp/slog +golang.org/x/exp/slog/internal +golang.org/x/exp/slog/internal/buffer # golang.org/x/image v0.18.0 ## explicit; go 1.18 golang.org/x/image/bmp From e7fd04bbe354c9d171d48c4d66d27df58007577d Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 30 Jul 2024 14:02:17 +0200 Subject: [PATCH 2/2] feat(tusd): bump tusd pkg to v2.4.0 Signed-off-by: jkoberg --- changelog/unreleased/bump-tusd.md | 5 + go.mod | 5 +- go.sum | 1338 --------------- services/proxy/pkg/middleware/policies.go | 2 +- vendor/github.com/bmizerany/pat/.gitignore | 3 - vendor/github.com/bmizerany/pat/LICENSE | 19 - vendor/github.com/bmizerany/pat/README.md | 82 - vendor/github.com/bmizerany/pat/mux.go | 314 ---- vendor/github.com/tus/tusd/LICENSE.txt | 19 - .../tus/tusd/pkg/handler/body_reader.go | 53 - .../tus/tusd/pkg/handler/composer.go | 87 - .../tus/tusd/pkg/handler/composer.mgo | 74 - .../github.com/tus/tusd/pkg/handler/config.go | 158 -- .../tus/tusd/pkg/handler/datastore.go | 156 -- vendor/github.com/tus/tusd/pkg/handler/doc.go | 69 - .../tus/tusd/pkg/handler/handler.go | 53 - vendor/github.com/tus/tusd/pkg/handler/log.go | 27 - .../tus/tusd/pkg/handler/metrics.go | 137 -- .../tus/tusd/pkg/handler/unrouted_handler.go | 1468 ----------------- vendor/modules.txt | 8 +- 20 files changed, 10 insertions(+), 4067 deletions(-) create mode 100644 changelog/unreleased/bump-tusd.md delete mode 100644 vendor/github.com/bmizerany/pat/.gitignore delete mode 100644 vendor/github.com/bmizerany/pat/LICENSE delete mode 100644 vendor/github.com/bmizerany/pat/README.md delete mode 100644 vendor/github.com/bmizerany/pat/mux.go delete mode 100644 vendor/github.com/tus/tusd/LICENSE.txt delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/body_reader.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/composer.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/composer.mgo delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/config.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/datastore.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/doc.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/handler.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/log.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/metrics.go delete mode 100644 vendor/github.com/tus/tusd/pkg/handler/unrouted_handler.go diff --git a/changelog/unreleased/bump-tusd.md b/changelog/unreleased/bump-tusd.md new file mode 100644 index 0000000000..2d4c3b7a98 --- /dev/null +++ b/changelog/unreleased/bump-tusd.md @@ -0,0 +1,5 @@ +Enhancement: Bump tusd pkg to v2 + +Bumps the tusd pkg to v2.4.0 + +https://github.com/owncloud/ocis/pull/9714 diff --git a/go.mod b/go.mod index dbc22712f9..112e1b5333 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,7 @@ require ( github.com/test-go/testify v1.1.4 github.com/thejerf/suture/v4 v4.0.5 github.com/tidwall/gjson v1.17.1 - github.com/tus/tusd v1.13.0 + github.com/tus/tusd/v2 v2.4.0 github.com/unrolled/secure v1.14.0 github.com/urfave/cli/v2 v2.27.2 github.com/xhit/go-simple-mail/v2 v2.16.0 @@ -156,7 +156,6 @@ require ( github.com/blevesearch/zapx/v15 v15.3.13 // indirect github.com/blevesearch/zapx/v16 v16.1.5 // indirect github.com/bluele/gcache v0.0.2 // indirect - github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f // indirect github.com/bombsimon/logrusr/v3 v3.1.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/ceph/go-ceph v0.18.0 // indirect @@ -226,6 +225,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gomodule/redigo v1.8.9 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect github.com/google/renameio/v2 v2.0.0 // indirect @@ -323,7 +323,6 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect github.com/trustelem/zxcvbn v1.0.1 // indirect - github.com/tus/tusd/v2 v2.4.0 // indirect github.com/wk8/go-ordered-map v1.0.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect diff --git a/go.sum b/go.sum index 3f1fe00df2..6052d050cc 100644 --- a/go.sum +++ b/go.sum @@ -5,7 +5,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,781 +15,51 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/accesscontextmanager v1.8.0/go.mod h1:uI+AI/r1oyWK99NN8cQ3UK76AMelMzgZCvJfsi2c+ps= -cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= -cloud.google.com/go/aiplatform v1.48.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/analytics v0.21.3/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/baremetalsolution v1.1.1/go.mod h1:D1AV6xwOksJMV4OSlWHtWuFNZZYujJknMAP4Qa27QIA= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/batch v1.3.1/go.mod h1:VguXeQKXIYaeeIYbuozUmBR13AfL4SJP7IltNPS+A4A= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/beyondcorp v0.6.1/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= -cloud.google.com/go/bigquery v1.53.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/cloudbuild v1.13.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/cloudtasks v1.12.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/contactcenterinsights v1.10.0/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= -cloud.google.com/go/container v1.24.0/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/datacatalog v1.14.0/go.mod h1:h0PrGtlihoutNMp/uvwhawLQ9+c63Kz65UFqh49Yo+E= -cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= -cloud.google.com/go/datacatalog v1.16.0/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataplex v1.9.0/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataproc/v2 v2.0.1/go.mod h1:7Ez3KRHdFGcfY7GcevBbvozX+zyWGcwLJvvAMwCaoZ4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastore v1.12.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= -cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= -cloud.google.com/go/datastore v1.13.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/datastream v1.10.0/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/deploy v1.13.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= -cloud.google.com/go/dialogflow v1.40.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= -cloud.google.com/go/documentai v1.22.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/eventarc v1.13.0/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gaming v1.10.1/go.mod h1:XQQvtfP8Rb9Rxnxm5wFVpAp9zCQkJi2bLIb7iHGwB3s= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkebackup v1.3.0/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/gkemulticloud v1.0.0/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8= -cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM= -cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -cloud.google.com/go/kms v1.15.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= -cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/maps v1.3.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/maps v1.4.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/metastore v1.12.0/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/orgpolicy v1.11.0/go.mod h1:2RK748+FtVvnfuynxBzdnyu7sygtoZa1za/0ZfpOs1M= -cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/osconfig v1.12.0/go.mod h1:8f/PaYzoS3JMVfdfTubkowZYGmAhUCjjwnjqWI7NVBc= -cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= -cloud.google.com/go/policytroubleshooter v1.8.0/go.mod h1:tmn5Ir5EToWe384EuboTcVQT7nTag2+DuH3uHmKd1HU= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicedirectory v1.11.0/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/speech v1.19.0/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storage v1.32.0/go.mod h1:Hhh/dogNRGca7IWv1RC2YqEn0c0G77ctA/OxflYkiD8= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/translate v1.8.2/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= -cloud.google.com/go/video v1.19.0/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vmwareengine v1.0.0/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/Acconut/go-httptest-recorder v1.0.0 h1:TAv2dfnqp/l+SUvIaMAUK4GeN4+wqb6KZsFFFTGhoJg= github.com/Acconut/go-httptest-recorder v1.0.0/go.mod h1:CwQyhTH1kq/gLyWiRieo7c0uokpu3PXeyF/nZjUNtmM= -github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -802,7 +71,6 @@ github.com/CiscoM31/godata v1.0.10/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchK github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c h1:ocsNvQ2tNHme4v/lTs17HROamc7mFzZfzWcg4m+UXN0= github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/KimMachineGun/automemlimit v0.6.1 h1:ILa9j1onAAMadBsyyUJv5cack8Y1WT26yLj/V+ulKp8= github.com/KimMachineGun/automemlimit v0.6.1/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -834,12 +102,7 @@ github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRB github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.0/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8= -github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= 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= @@ -853,15 +116,9 @@ github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6Ct github.com/aliyun/alibaba-cloud-sdk-go v1.61.976/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/4wKeNvD/IQla3U3SUa61U7ul+xM4= github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -938,14 +195,9 @@ github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= -github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/bombsimon/logrusr/v3 v3.1.0 h1:zORbLM943D+hDMGgyjMhSAz/iDz86ZV72qaak/CA0zQ= github.com/bombsimon/logrusr/v3 v3.1.0/go.mod h1:PksPPgSFEL2I52pla2glgCyyd2OqOHAnFF5E+g8Ixco= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -959,15 +211,12 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/ceph/go-ceph v0.18.0 h1:4WM6yAq/iqBDaeeADDiPKLqKiP0iZ4fffdgCr1lnOL4= github.com/ceph/go-ceph v0.18.0/go.mod h1:cflETVTBNAQM6jdr7hpNHHFHKYiJiWWcAeRDrRx/1ng= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 h1:q1g9lSyo/nOIC3W5E3FK3Unrz8b9LdLXCyuC+ZcpPC0= @@ -985,19 +234,6 @@ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vc github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= @@ -1062,7 +298,6 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -1082,20 +317,7 @@ github.com/emvi/iso-639-1 v1.1.0/go.mod h1:CSA53/Tx0xF9bk2DEA0Mr0wTdIxq7pqoVZgBO github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/evanphx/json-patch/v5 v5.5.0 h1:bAmFiUJ+o0o2B4OiTFeE3MqCOtyo+jjPP9iZ0VRxYUc= @@ -1110,9 +332,6 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= @@ -1148,11 +367,6 @@ github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= @@ -1176,8 +390,6 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ= github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk= @@ -1229,8 +441,6 @@ github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0 h1:e2hgtWMNqJ3 github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0/go.mod h1:BBqL7ckGNb7rFfk3vU2Yj/CILVsz/WF19CkAyveQl8A= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -1263,7 +473,6 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ= github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -1287,12 +496,9 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1308,7 +514,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20170622202551-6a1fa9404c0a/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1327,13 +532,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= @@ -1356,14 +558,11 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= -github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -1372,9 +571,6 @@ github.com/google/go-tika v0.3.1/go.mod h1:DJh5N8qxXIl85QkqmXknd+PeeRkUOTbvwyYf7 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -1382,53 +578,17 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/gookit/config/v2 v2.2.5 h1:RECbYYbtherywmzn3LNeu9NA5ZqhD7MSKEMsJ7l+MpU= @@ -1459,9 +619,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vb github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= @@ -1529,11 +686,9 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= @@ -1591,23 +746,18 @@ github.com/juliangruber/go-intersect v1.1.0 h1:sc+y5dCjMMx0pAdYk/N6KBm00tD/f3tq+ github.com/juliangruber/go-intersect v1.1.0/go.mod h1:WMau+1kAmnlQnKiikekNJbtGtfmILU/mMU6H7AgKbWQ= 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/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240724102745-4bc93ffd7ab6 h1:NNXx1/XWR6Ryud6qNanwrl/JuRx2KdCW1jS2/Cf/TO8= @@ -1653,9 +803,6 @@ github.com/longsleep/go-metrics v1.0.0 h1:o2A6Dbu4MhLpZuL444WFoZzM7X7igewrj2Mouw github.com/longsleep/go-metrics v1.0.0/go.mod h1:w6QO1LBkVla70FZrrF6XcB0YN+jTEYugjkn3+6RYTSM= github.com/longsleep/rndm v1.2.0 h1:wPl+kIMyIUTUFW5+2b327DmM1Rlj+gmexsiyOTB7rzM= github.com/longsleep/rndm v1.2.0/go.mod h1:5qyvM6CXNteKgz6djqqwZOP4+KcPsewrfKyLWd1dCFY= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= @@ -1671,7 +818,6 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= @@ -1680,7 +826,6 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -1688,14 +833,11 @@ github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b h1:Q53idHrTuQDDHyXaxZ6pUl0I9uyD6Z6uKFK3ocX6LzI= github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b/go.mod h1:KirJrATYGbTyUwVR26xIkaipRqRcMRXBf8N5dacvGus= github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 h1:Z/i1e+gTZrmcGeZyWckaLfucYG6KYOXLWo4co8pZYNY= @@ -1708,8 +850,6 @@ github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/mileusna/useragent v1.3.4 h1:MiuRRuvGjEie1+yZHO88UBYg8YBC/ddF6T7F56i3PCk= github.com/mileusna/useragent v1.3.4/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= @@ -1822,9 +962,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -1836,7 +973,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE= github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= @@ -1862,8 +998,6 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1872,7 +1006,6 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20170706130215-fb369f752a7f/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -1887,7 +1020,6 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20170703101242-e645f4e5aaa8/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1901,7 +1033,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= @@ -1914,15 +1045,12 @@ github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKc github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/riandyrn/otelchi v0.8.0 h1:q60HKpwt1MmGjOWgM7m5gGyXYAY3DfTSdfBdBt6ICV4= github.com/riandyrn/otelchi v0.8.0/go.mod h1:ErTae2TG7lrOtEPFsd5/hYLOHJpkk0NNyMaeTMWxl0U= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= @@ -1940,8 +1068,6 @@ github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWy github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8= @@ -1955,7 +1081,6 @@ github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aep github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sethgrid/pester v1.2.0/go.mod h1:hEUINb4RqvDxtoCaU0BNT/HV4ig5kfgOasrf1xcvr0A= github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= github.com/shamaton/msgpack/v2 v2.2.0 h1:IP1m01pHwCrMa6ZccP9B3bqxEMKMSmMVAVKk54g3L/Y= @@ -1989,10 +1114,7 @@ github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 h1:0jjO github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784/go.mod h1:ff/5myEGgtsAwf26goQCO905GrEm5ugEZSd6OWTsrhM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -2024,9 +1146,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= @@ -2056,8 +1175,6 @@ github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXz github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/trustelem/zxcvbn v1.0.1 h1:mp4JFtzdDYGj9WYSD3KQSkwwUumWNFzXaAjckaTYpsc= github.com/trustelem/zxcvbn v1.0.1/go.mod h1:zonUyKeh7sw6psPf/e3DtRqkRyZvAbOfjNz/aO7YQ5s= -github.com/tus/tusd v1.13.0 h1:W7rtb1XPSpde/GPZAgdfUS3vus2Jt2KmckS6OUd3CU8= -github.com/tus/tusd v1.13.0/go.mod h1:1tX4CDGlx8koHGFJdSaJ5ybUIm2NeVloJgZEPSKRcQA= github.com/tus/tusd/v2 v2.4.0 h1:SpXmzQPCtiedkhNPl5Gn4ApQXLChPLdYrWbZQI42uJE= github.com/tus/tusd/v2 v2.4.0/go.mod h1:X+fc/MU+T+NDD5gNJHHE58jo6cQj1vlMstlT16+xlrg= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -2069,7 +1186,6 @@ github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y4 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/vimeo/go-util v1.4.1/go.mod h1:r+yspV//C48HeMXV8nEvtUeNiIiGfVv3bbEHzOgudwE= github.com/vinyldns/go-vinyldns v0.0.0-20200917153823-148a5f6b8f14/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg= github.com/vultr/govultr/v2 v2.0.0/go.mod h1:2PsEeg+gs3p/Fo5Pw8F9mv+DUBEOlrNZ8GmCTGmhOhs= github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8= @@ -2090,7 +1206,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA= github.com/xhit/go-simple-mail/v2 v2.16.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98= -github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= @@ -2102,13 +1217,9 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go-micro.dev/v4 v4.11.0 h1:DZ2xcr0pnZJDlp6MJiCLhw4tXRxLw9xrJlPT91kubr0= go-micro.dev/v4 v4.11.0/go.mod h1:eE/tD53n3KbVrzrWxKLxdkGw45Fg1qaNLWjpJMvIUF4= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -2127,7 +1238,6 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= @@ -2151,9 +1261,6 @@ go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kT go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -2186,57 +1293,32 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo= golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -2250,7 +1332,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 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= @@ -2259,16 +1340,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2309,45 +1382,22 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= @@ -2359,33 +1409,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2401,11 +1426,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2438,7 +1459,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2460,77 +1480,38 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -2542,15 +1523,9 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= @@ -2562,19 +1537,13 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= @@ -2585,17 +1554,12 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/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= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -2611,7 +1575,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2642,47 +1605,19 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -2700,62 +1635,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= -google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= -google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= -google.golang.org/api v0.132.0/go.mod h1:AeTBC6GpJnJSRJjktDcPX0QwtS8pGYZOV6MSuSCusw0= -google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -2780,147 +1665,16 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230711160842-782d3b101e98/go.mod h1:3QoBVwTHkXbY1oRGzlhwhOykfcATQN43LJ6iT8Wy8kE= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2937,42 +1691,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU= google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -2987,15 +1708,10 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= @@ -3007,7 +1723,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= -gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -3048,60 +1763,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= -modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g= -modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= -modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= -modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= -modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= -modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/sqlite v1.18.2/go.mod h1:kvrTLEWgxUcHa2GfHBQtanR1H9ht3hTJNtKpzH9k1u0= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/services/proxy/pkg/middleware/policies.go b/services/proxy/pkg/middleware/policies.go index 590eb96f64..4861df0105 100644 --- a/services/proxy/pkg/middleware/policies.go +++ b/services/proxy/pkg/middleware/policies.go @@ -10,7 +10,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/render" - tusd "github.com/tus/tusd/pkg/handler" + tusd "github.com/tus/tusd/v2/pkg/handler" "google.golang.org/grpc/metadata" revactx "github.com/cs3org/reva/v2/pkg/ctx" diff --git a/vendor/github.com/bmizerany/pat/.gitignore b/vendor/github.com/bmizerany/pat/.gitignore deleted file mode 100644 index 72f13bd555..0000000000 --- a/vendor/github.com/bmizerany/pat/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.prof -*.out -example/example diff --git a/vendor/github.com/bmizerany/pat/LICENSE b/vendor/github.com/bmizerany/pat/LICENSE deleted file mode 100644 index ba109c7242..0000000000 --- a/vendor/github.com/bmizerany/pat/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2012 by Keith Rarick, Blake Mizerany - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/bmizerany/pat/README.md b/vendor/github.com/bmizerany/pat/README.md deleted file mode 100644 index 2bb12fa685..0000000000 --- a/vendor/github.com/bmizerany/pat/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# pat (formerly pat.go) - A Sinatra style pattern muxer for Go's net/http library - -[![GoDoc](https://godoc.org/github.com/bmizerany/pat?status.svg)](https://godoc.org/github.com/bmizerany/pat) - -## INSTALL - - $ go get github.com/bmizerany/pat - -## USE - -```go -package main - -import ( - "io" - "net/http" - "github.com/bmizerany/pat" - "log" -) - -// hello world, the web server -func HelloServer(w http.ResponseWriter, req *http.Request) { - io.WriteString(w, "hello, "+req.URL.Query().Get(":name")+"!\n") -} - -func main() { - m := pat.New() - m.Get("/hello/:name", http.HandlerFunc(HelloServer)) - - // Register this pat with the default serve mux so that other packages - // may also be exported. (i.e. /debug/pprof/*) - http.Handle("/", m) - err := http.ListenAndServe(":12345", nil) - if err != nil { - log.Fatal("ListenAndServe: ", err) - } -} -``` - -It's that simple. - -For more information, see: -http://godoc.org/github.com/bmizerany/pat - -## CONTRIBUTORS - -* Alexis Svinartchouk (@zvin) -* Blake Mizerany (@bmizerany) -* Brian Ketelsen (@bketelsen) -* Bryan Matsuo (@bmatsuo) -* Caleb Spare (@cespare) -* Evan Shaw (@edsrzf) -* Gary Burd (@garyburd) -* George Rogers (@georgerogers42) -* Keith Rarick (@kr) -* Matt Williams (@mattyw) -* Mike Stipicevic (@wickedchicken) -* Nick Saika (@nesv) -* Timothy Cyrus (@tcyrus) -* binqin (@binku87) - -## LICENSE - -Copyright (C) 2012 by Keith Rarick, Blake Mizerany - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/bmizerany/pat/mux.go b/vendor/github.com/bmizerany/pat/mux.go deleted file mode 100644 index 3009e9795a..0000000000 --- a/vendor/github.com/bmizerany/pat/mux.go +++ /dev/null @@ -1,314 +0,0 @@ -// Package pat implements a simple URL pattern muxer -package pat - -import ( - "net/http" - "net/url" - "strings" -) - -// PatternServeMux is an HTTP request multiplexer. It matches the URL of each -// incoming request against a list of registered patterns with their associated -// methods and calls the handler for the pattern that most closely matches the -// URL. -// -// Pattern matching attempts each pattern in the order in which they were -// registered. -// -// Patterns may contain literals or captures. Capture names start with a colon -// and consist of letters A-Z, a-z, _, and 0-9. The rest of the pattern -// matches literally. The portion of the URL matching each name ends with an -// occurrence of the character in the pattern immediately following the name, -// or a /, whichever comes first. It is possible for a name to match the empty -// string. -// -// Example pattern with one capture: -// /hello/:name -// Will match: -// /hello/blake -// /hello/keith -// Will not match: -// /hello/blake/ -// /hello/blake/foo -// /foo -// /foo/bar -// -// Example 2: -// /hello/:name/ -// Will match: -// /hello/blake/ -// /hello/keith/foo -// /hello/blake -// /hello/keith -// Will not match: -// /foo -// /foo/bar -// -// A pattern ending with a slash will add an implicit redirect for its non-slash -// version. For example: Get("/foo/", handler) also registers -// Get("/foo", handler) as a redirect. You may override it by registering -// Get("/foo", anotherhandler) before the slash version. -// -// Retrieve the capture from the r.URL.Query().Get(":name") in a handler (note -// the colon). If a capture name appears more than once, the additional values -// are appended to the previous values (see -// http://golang.org/pkg/net/url/#Values) -// -// A trivial example server is: -// -// package main -// -// import ( -// "io" -// "net/http" -// "github.com/bmizerany/pat" -// "log" -// ) -// -// // hello world, the web server -// func HelloServer(w http.ResponseWriter, req *http.Request) { -// io.WriteString(w, "hello, "+req.URL.Query().Get(":name")+"!\n") -// } -// -// func main() { -// m := pat.New() -// m.Get("/hello/:name", http.HandlerFunc(HelloServer)) -// -// // Register this pat with the default serve mux so that other packages -// // may also be exported. (i.e. /debug/pprof/*) -// http.Handle("/", m) -// err := http.ListenAndServe(":12345", nil) -// if err != nil { -// log.Fatal("ListenAndServe: ", err) -// } -// } -// -// When "Method Not Allowed": -// -// Pat knows what methods are allowed given a pattern and a URI. For -// convenience, PatternServeMux will add the Allow header for requests that -// match a pattern for a method other than the method requested and set the -// Status to "405 Method Not Allowed". -// -// If the NotFound handler is set, then it is used whenever the pattern doesn't -// match the request path for the current method (and the Allow header is not -// altered). -type PatternServeMux struct { - // NotFound, if set, is used whenever the request doesn't match any - // pattern for its method. NotFound should be set before serving any - // requests. - NotFound http.Handler - handlers map[string][]*patHandler -} - -// New returns a new PatternServeMux. -func New() *PatternServeMux { - return &PatternServeMux{handlers: make(map[string][]*patHandler)} -} - -// ServeHTTP matches r.URL.Path against its routing table using the rules -// described above. -func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { - for _, ph := range p.handlers[r.Method] { - if params, ok := ph.try(r.URL.EscapedPath()); ok { - if len(params) > 0 && !ph.redirect { - r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery - } - ph.ServeHTTP(w, r) - return - } - } - - if p.NotFound != nil { - p.NotFound.ServeHTTP(w, r) - return - } - - allowed := make([]string, 0, len(p.handlers)) - for meth, handlers := range p.handlers { - if meth == r.Method { - continue - } - - for _, ph := range handlers { - if _, ok := ph.try(r.URL.EscapedPath()); ok { - allowed = append(allowed, meth) - } - } - } - - if len(allowed) == 0 { - http.NotFound(w, r) - return - } - - w.Header().Add("Allow", strings.Join(allowed, ", ")) - http.Error(w, "Method Not Allowed", 405) -} - -// Head will register a pattern with a handler for HEAD requests. -func (p *PatternServeMux) Head(pat string, h http.Handler) { - p.Add("HEAD", pat, h) -} - -// Get will register a pattern with a handler for GET requests. -// It also registers pat for HEAD requests. If this needs to be overridden, use -// Head before Get with pat. -func (p *PatternServeMux) Get(pat string, h http.Handler) { - p.Add("HEAD", pat, h) - p.Add("GET", pat, h) -} - -// Post will register a pattern with a handler for POST requests. -func (p *PatternServeMux) Post(pat string, h http.Handler) { - p.Add("POST", pat, h) -} - -// Put will register a pattern with a handler for PUT requests. -func (p *PatternServeMux) Put(pat string, h http.Handler) { - p.Add("PUT", pat, h) -} - -// Del will register a pattern with a handler for DELETE requests. -func (p *PatternServeMux) Del(pat string, h http.Handler) { - p.Add("DELETE", pat, h) -} - -// Options will register a pattern with a handler for OPTIONS requests. -func (p *PatternServeMux) Options(pat string, h http.Handler) { - p.Add("OPTIONS", pat, h) -} - -// Patch will register a pattern with a handler for PATCH requests. -func (p *PatternServeMux) Patch(pat string, h http.Handler) { - p.Add("PATCH", pat, h) -} - -// Add will register a pattern with a handler for meth requests. -func (p *PatternServeMux) Add(meth, pat string, h http.Handler) { - p.add(meth, pat, h, false) -} - -func (p *PatternServeMux) add(meth, pat string, h http.Handler, redirect bool) { - handlers := p.handlers[meth] - for _, p1 := range handlers { - if p1.pat == pat { - return // found existing pattern; do nothing - } - } - handler := &patHandler{ - pat: pat, - Handler: h, - redirect: redirect, - } - p.handlers[meth] = append(handlers, handler) - - n := len(pat) - if n > 0 && pat[n-1] == '/' { - p.add(meth, pat[:n-1], http.HandlerFunc(addSlashRedirect), true) - } -} - -func addSlashRedirect(w http.ResponseWriter, r *http.Request) { - u := *r.URL - u.Path += "/" - http.Redirect(w, r, u.String(), http.StatusMovedPermanently) -} - -// Tail returns the trailing string in path after the final slash for a pat ending with a slash. -// -// Examples: -// -// Tail("/hello/:title/", "/hello/mr/mizerany") == "mizerany" -// Tail("/:a/", "/x/y/z") == "y/z" -// -func Tail(pat, path string) string { - var i, j int - for i < len(path) { - switch { - case j >= len(pat): - if pat[len(pat)-1] == '/' { - return path[i:] - } - return "" - case pat[j] == ':': - var nextc byte - _, nextc, j = match(pat, isAlnum, j+1) - _, _, i = match(path, matchPart(nextc), i) - case path[i] == pat[j]: - i++ - j++ - default: - return "" - } - } - return "" -} - -type patHandler struct { - pat string - http.Handler - redirect bool -} - -func (ph *patHandler) try(path string) (url.Values, bool) { - p := make(url.Values) - var i, j int - for i < len(path) { - switch { - case j >= len(ph.pat): - if ph.pat != "/" && len(ph.pat) > 0 && ph.pat[len(ph.pat)-1] == '/' { - return p, true - } - return nil, false - case ph.pat[j] == ':': - var name, val string - var nextc byte - name, nextc, j = match(ph.pat, isAlnum, j+1) - val, _, i = match(path, matchPart(nextc), i) - escval, err := url.QueryUnescape(val) - if err != nil { - return nil, false - } - p.Add(":"+name, escval) - case path[i] == ph.pat[j]: - i++ - j++ - default: - return nil, false - } - } - if j != len(ph.pat) { - return nil, false - } - return p, true -} - -func matchPart(b byte) func(byte) bool { - return func(c byte) bool { - return c != b && c != '/' - } -} - -func match(s string, f func(byte) bool, i int) (matched string, next byte, j int) { - j = i - for j < len(s) && f(s[j]) { - j++ - } - if j < len(s) { - next = s[j] - } - return s[i:j], next, j -} - -func isAlpha(ch byte) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' -} - -func isDigit(ch byte) bool { - return '0' <= ch && ch <= '9' -} - -func isAlnum(ch byte) bool { - return isAlpha(ch) || isDigit(ch) -} diff --git a/vendor/github.com/tus/tusd/LICENSE.txt b/vendor/github.com/tus/tusd/LICENSE.txt deleted file mode 100644 index bdf13822ce..0000000000 --- a/vendor/github.com/tus/tusd/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013-2017 Transloadit Ltd and Contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/tus/tusd/pkg/handler/body_reader.go b/vendor/github.com/tus/tusd/pkg/handler/body_reader.go deleted file mode 100644 index 7374b89720..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/body_reader.go +++ /dev/null @@ -1,53 +0,0 @@ -package handler - -import ( - "io" - "sync/atomic" -) - -// bodyReader is an io.Reader, which is intended to wrap the request -// body reader. If an error occurr during reading the request body, it -// will not return this error to the reading entity, but instead store -// the error and close the io.Reader, so that the error can be checked -// afterwards. This is helpful, so that the stores do not have to handle -// the error but this can instead be done in the handler. -// In addition, the bodyReader keeps track of how many bytes were read. -type bodyReader struct { - reader io.Reader - err error - bytesCounter int64 -} - -func newBodyReader(r io.Reader) *bodyReader { - return &bodyReader{ - reader: r, - } -} - -func (r *bodyReader) Read(b []byte) (int, error) { - if r.err != nil { - return 0, io.EOF - } - - n, err := r.reader.Read(b) - atomic.AddInt64(&r.bytesCounter, int64(n)) - r.err = err - - if err == io.EOF { - return n, io.EOF - } else { - return n, nil - } -} - -func (r bodyReader) hasError() error { - if r.err == io.EOF { - return nil - } - - return r.err -} - -func (r *bodyReader) bytesRead() int64 { - return atomic.LoadInt64(&r.bytesCounter) -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/composer.go b/vendor/github.com/tus/tusd/pkg/handler/composer.go deleted file mode 100644 index abea0a6900..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/composer.go +++ /dev/null @@ -1,87 +0,0 @@ -package handler - -// StoreComposer represents a composable data store. It consists of the core -// data store and optional extensions. Please consult the package's overview -// for a more detailed introduction in how to use this structure. -type StoreComposer struct { - Core DataStore - - UsesTerminater bool - Terminater TerminaterDataStore - UsesLocker bool - Locker Locker - UsesConcater bool - Concater ConcaterDataStore - UsesLengthDeferrer bool - LengthDeferrer LengthDeferrerDataStore -} - -// NewStoreComposer creates a new and empty store composer. -func NewStoreComposer() *StoreComposer { - return &StoreComposer{} -} - -// Capabilities returns a string representing the provided extensions in a -// human-readable format meant for debugging. -func (store *StoreComposer) Capabilities() string { - str := "Core: " - - if store.Core != nil { - str += "✓" - } else { - str += "✗" - } - - str += ` Terminater: ` - if store.UsesTerminater { - str += "✓" - } else { - str += "✗" - } - str += ` Locker: ` - if store.UsesLocker { - str += "✓" - } else { - str += "✗" - } - str += ` Concater: ` - if store.UsesConcater { - str += "✓" - } else { - str += "✗" - } - str += ` LengthDeferrer: ` - if store.UsesLengthDeferrer { - str += "✓" - } else { - str += "✗" - } - - return str -} - -// UseCore will set the used core data store. If the argument is nil, the -// property will be unset. -func (store *StoreComposer) UseCore(core DataStore) { - store.Core = core -} - -func (store *StoreComposer) UseTerminater(ext TerminaterDataStore) { - store.UsesTerminater = ext != nil - store.Terminater = ext -} - -func (store *StoreComposer) UseLocker(ext Locker) { - store.UsesLocker = ext != nil - store.Locker = ext -} - -func (store *StoreComposer) UseConcater(ext ConcaterDataStore) { - store.UsesConcater = ext != nil - store.Concater = ext -} - -func (store *StoreComposer) UseLengthDeferrer(ext LengthDeferrerDataStore) { - store.UsesLengthDeferrer = ext != nil - store.LengthDeferrer = ext -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/composer.mgo b/vendor/github.com/tus/tusd/pkg/handler/composer.mgo deleted file mode 100644 index f4fc3ef87b..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/composer.mgo +++ /dev/null @@ -1,74 +0,0 @@ -package handler - -#define USE_FUNC(TYPE) \ -func (store *StoreComposer) Use ## TYPE(ext TYPE ## DataStore) { \ - store.Uses ## TYPE = ext != nil; \ - store.TYPE = ext; \ -} - -#define USE_FIELD(TYPE) Uses ## TYPE bool; \ - TYPE TYPE ## DataStore - -#define USE_FROM(TYPE) if mod, ok := store.(TYPE ## DataStore); ok { \ - composer.Use ## TYPE (mod) \ -} - -#define USE_CAP(TYPE) str += ` TYPE: `; \ -if store.Uses ## TYPE { \ - str += "✓" \ -} else { \ - str += "✗" \ -} - -// StoreComposer represents a composable data store. It consists of the core -// data store and optional extensions. Please consult the package's overview -// for a more detailed introduction in how to use this structure. -type StoreComposer struct { - Core DataStore - - USE_FIELD(Terminater) - USE_FIELD(Finisher) - USE_FIELD(Locker) - USE_FIELD(GetReader) - USE_FIELD(Concater) - USE_FIELD(LengthDeferrer) -} - -// NewStoreComposer creates a new and empty store composer. -func NewStoreComposer() *StoreComposer { - return &StoreComposer{} -} - -// Capabilities returns a string representing the provided extensions in a -// human-readable format meant for debugging. -func (store *StoreComposer) Capabilities() string { - str := "Core: " - - if store.Core != nil { - str += "✓" - } else { - str += "✗" - } - - USE_CAP(Terminater) - USE_CAP(Finisher) - USE_CAP(Locker) - USE_CAP(GetReader) - USE_CAP(Concater) - USE_CAP(LengthDeferrer) - - return str -} - -// UseCore will set the used core data store. If the argument is nil, the -// property will be unset. -func (store *StoreComposer) UseCore(core DataStore) { - store.Core = core -} - -USE_FUNC(Terminater) -USE_FUNC(Finisher) -USE_FUNC(Locker) -USE_FUNC(GetReader) -USE_FUNC(Concater) -USE_FUNC(LengthDeferrer) diff --git a/vendor/github.com/tus/tusd/pkg/handler/config.go b/vendor/github.com/tus/tusd/pkg/handler/config.go deleted file mode 100644 index 8c5bd7a064..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/config.go +++ /dev/null @@ -1,158 +0,0 @@ -package handler - -import ( - "errors" - "log" - "net/url" - "os" - "regexp" -) - -// Config provides a way to configure the Handler depending on your needs. -type Config struct { - // StoreComposer points to the store composer from which the core data store - // and optional dependencies should be taken. May only be nil if DataStore is - // set. - // TODO: Remove pointer? - StoreComposer *StoreComposer - // MaxSize defines how many bytes may be stored in one single upload. If its - // value is is 0 or smaller no limit will be enforced. - MaxSize int64 - // BasePath defines the URL path used for handling uploads, e.g. "/files/". - // If no trailing slash is presented it will be added. You may specify an - // absolute URL containing a scheme, e.g. "http://tus.io" - BasePath string - isAbs bool - // EnableExperimentalProtocol controls whether the new resumable upload protocol draft - // from the IETF's HTTP working group is accepted next to the current tus v1 protocol. - // See https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/ - EnableExperimentalProtocol bool - // DisableDownload indicates whether the server will refuse downloads of the - // uploaded file, by not mounting the GET handler. - DisableDownload bool - // DisableTermination indicates whether the server will refuse termination - // requests of the uploaded file, by not mounting the DELETE handler. - DisableTermination bool - // Disable cors headers. If set to true, tusd will not send any CORS related header. - // This is useful if you have a proxy sitting in front of tusd that handles CORS. - // - // Deprecated: All CORS-related settings are available in via the Cors field. Use - // Cors.Disable instead of DisableCors. - DisableCors bool - // Cors can be used to customize the handling of Cross-Origin Resource Sharing (CORS). - // See the CorsConfig struct for more details. - // Defaults to DefaultCorsConfig. - Cors *CorsConfig - // NotifyCompleteUploads indicates whether sending notifications about - // completed uploads using the CompleteUploads channel should be enabled. - NotifyCompleteUploads bool - // NotifyTerminatedUploads indicates whether sending notifications about - // terminated uploads using the TerminatedUploads channel should be enabled. - NotifyTerminatedUploads bool - // NotifyUploadProgress indicates whether sending notifications about - // the upload progress using the UploadProgress channel should be enabled. - NotifyUploadProgress bool - // NotifyCreatedUploads indicates whether sending notifications about - // the upload having been created using the CreatedUploads channel should be enabled. - NotifyCreatedUploads bool - // Logger is the logger to use internally, mostly for printing requests. - Logger *log.Logger - // Respect the X-Forwarded-Host, X-Forwarded-Proto and Forwarded headers - // potentially set by proxies when generating an absolute URL in the - // response to POST requests. - RespectForwardedHeaders bool - // PreUploadCreateCallback will be invoked before a new upload is created, if the - // property is supplied. If the callback returns nil, the upload will be created. - // Otherwise the HTTP request will be aborted. This can be used to implement - // validation of upload metadata etc. - PreUploadCreateCallback func(hook HookEvent) error - // PreFinishResponseCallback will be invoked after an upload is completed but before - // a response is returned to the client. Error responses from the callback will be passed - // back to the client. This can be used to implement post-processing validation. - PreFinishResponseCallback func(hook HookEvent) error -} - -// CorsConfig provides a way to customize the the handling of Cross-Origin Resource Sharing (CORS). -// More details about CORS are available at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS. -type CorsConfig struct { - // Disable instructs the handler to ignore all CORS-related headers and never set a - // CORS-related header in a response. This is useful if CORS is already handled by a proxy. - Disable bool - // AllowOrigin is a regular expression used to check if a request is allowed to participate in the - // CORS protocol. If the request's Origin header matches the regular expression, CORS is allowed. - // If not, a 403 Forbidden response is sent, rejecting the CORS request. - AllowOrigin *regexp.Regexp - // AllowCredentials defines whether the `Access-Control-Allow-Credentials: true` header should be - // included in CORS responses. This allows clients to share credentials using the Cookie and - // Authorization header - AllowCredentials bool - // AllowMethods defines the value for the `Access-Control-Allow-Methods` header in the response to - // preflight requests. You can add custom methods here, but make sure that all tus-specific methods - // from DefaultConfig.AllowMethods are included as well. - AllowMethods string - // AllowHeaders defines the value for the `Access-Control-Allow-Headers` header in the response to - // preflight requests. You can add custom headers here, but make sure that all tus-specific header - // from DefaultConfig.AllowHeaders are included as well. - AllowHeaders string - // MaxAge defines the value for the `Access-Control-Max-Age` header in the response to preflight - // requests. - MaxAge string - // ExposeHeaders defines the value for the `Access-Control-Expose-Headers` header in the response to - // actual requests. You can add custom headers here, but make sure that all tus-specific header - // from DefaultConfig.ExposeHeaders are included as well. - ExposeHeaders string -} - -// DefaultCorsConfig is the configuration that will be used in none is provided. -var DefaultCorsConfig = CorsConfig{ - Disable: false, - AllowOrigin: regexp.MustCompile(".*"), - AllowCredentials: false, - AllowMethods: "POST, HEAD, PATCH, OPTIONS, GET, DELETE", - AllowHeaders: "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Draft-Interop-Version", - MaxAge: "86400", - ExposeHeaders: "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Draft-Interop-Version", -} - -func (config *Config) validate() error { - if config.Logger == nil { - config.Logger = log.New(os.Stdout, "[tusd] ", log.Ldate|log.Lmicroseconds) - } - - base := config.BasePath - uri, err := url.Parse(base) - if err != nil { - return err - } - - // Ensure base path ends with slash to remove logic from absFileURL - if base != "" && string(base[len(base)-1]) != "/" { - base += "/" - } - - // Ensure base path begins with slash if not absolute (starts with scheme) - if !uri.IsAbs() && len(base) > 0 && string(base[0]) != "/" { - base = "/" + base - } - config.BasePath = base - config.isAbs = uri.IsAbs() - - if config.StoreComposer == nil { - return errors.New("tusd: StoreComposer must no be nil") - } - - if config.StoreComposer.Core == nil { - return errors.New("tusd: StoreComposer in Config needs to contain a non-nil core") - } - - if config.Cors == nil { - config.Cors = &DefaultCorsConfig - } - - // Support previous settings for disabling CORS. - if config.DisableCors { - config.Cors.Disable = true - } - - return nil -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/datastore.go b/vendor/github.com/tus/tusd/pkg/handler/datastore.go deleted file mode 100644 index 1eb4240adc..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/datastore.go +++ /dev/null @@ -1,156 +0,0 @@ -package handler - -import ( - "context" - "io" -) - -type MetaData map[string]string - -type FileInfo struct { - ID string - // Total file size in bytes specified in the NewUpload call - Size int64 - // Indicates whether the total file size is deferred until later - SizeIsDeferred bool - // Offset in bytes (zero-based) - Offset int64 - MetaData MetaData - // Indicates that this is a partial upload which will later be used to form - // a final upload by concatenation. Partial uploads should not be processed - // when they are finished since they are only incomplete chunks of files. - IsPartial bool - // Indicates that this is a final upload - IsFinal bool - // If the upload is a final one (see IsFinal) this will be a non-empty - // ordered slice containing the ids of the uploads of which the final upload - // will consist after concatenation. - PartialUploads []string - // Storage contains information about where the data storage saves the upload, - // for example a file path. The available values vary depending on what data - // store is used. This map may also be nil. - Storage map[string]string - - // stopUpload is the cancel function for the upload's context.Context. When - // invoked it will interrupt the writes to DataStore#WriteChunk. - stopUpload context.CancelFunc -} - -// StopUpload interrupts an running upload from the server-side. This means that -// the current request body is closed, so that the data store does not get any -// more data. Furthermore, a response is sent to notify the client of the -// interrupting and the upload is terminated (if supported by the data store), -// so the upload cannot be resumed anymore. -func (f FileInfo) StopUpload() { - if f.stopUpload != nil { - f.stopUpload() - } -} - -type Upload interface { - // Write the chunk read from src into the file specified by the id at the - // given offset. The handler will take care of validating the offset and - // limiting the size of the src to not overflow the file's size. It may - // return an os.ErrNotExist which will be interpreted as a 404 Not Found. - // It will also lock resources while they are written to ensure only one - // write happens per time. - // The function call must return the number of bytes written. - WriteChunk(ctx context.Context, offset int64, src io.Reader) (int64, error) - // Read the fileinformation used to validate the offset and respond to HEAD - // requests. It may return an os.ErrNotExist which will be interpreted as a - // 404 Not Found. - GetInfo(ctx context.Context) (FileInfo, error) - // GetReader returns a reader which allows iterating of the content of an - // upload specified by its ID. It should attempt to provide a reader even if - // the upload has not been finished yet but it's not required. - // If the returned reader also implements the io.Closer interface, the - // Close() method will be invoked once everything has been read. - // If the given upload could not be found, the error tusd.ErrNotFound should - // be returned. - GetReader(ctx context.Context) (io.Reader, error) - // FinisherDataStore is the interface which can be implemented by DataStores - // which need to do additional operations once an entire upload has been - // completed. These tasks may include but are not limited to freeing unused - // resources or notifying other services. For example, S3Store uses this - // interface for removing a temporary object. - // FinishUpload executes additional operations for the finished upload which - // is specified by its ID. - FinishUpload(ctx context.Context) error -} - -type DataStore interface { - // Create a new upload using the size as the file's length. The method must - // return an unique id which is used to identify the upload. If no backend - // (e.g. Riak) specifes the id you may want to use the uid package to - // generate one. The properties Size and MetaData will be filled. - NewUpload(ctx context.Context, info FileInfo) (upload Upload, err error) - - GetUpload(ctx context.Context, id string) (upload Upload, err error) -} - -type TerminatableUpload interface { - // Terminate an upload so any further requests to the resource, both reading - // and writing, must return os.ErrNotExist or similar. - Terminate(ctx context.Context) error -} - -// TerminaterDataStore is the interface which must be implemented by DataStores -// if they want to receive DELETE requests using the Handler. If this interface -// is not implemented, no request handler for this method is attached. -type TerminaterDataStore interface { - AsTerminatableUpload(upload Upload) TerminatableUpload -} - -// ConcaterDataStore is the interface required to be implemented if the -// Concatenation extension should be enabled. Only in this case, the handler -// will parse and respect the Upload-Concat header. -type ConcaterDataStore interface { - AsConcatableUpload(upload Upload) ConcatableUpload -} - -type ConcatableUpload interface { - // ConcatUploads concatenates the content from the provided partial uploads - // and writes the result in the destination upload. - // The caller (usually the handler) must and will ensure that this - // destination upload has been created before with enough space to hold all - // partial uploads. The order, in which the partial uploads are supplied, - // must be respected during concatenation. - ConcatUploads(ctx context.Context, partialUploads []Upload) error -} - -// LengthDeferrerDataStore is the interface that must be implemented if the -// creation-defer-length extension should be enabled. The extension enables a -// client to upload files when their total size is not yet known. Instead, the -// client must send the total size as soon as it becomes known. -type LengthDeferrerDataStore interface { - AsLengthDeclarableUpload(upload Upload) LengthDeclarableUpload -} - -type LengthDeclarableUpload interface { - DeclareLength(ctx context.Context, length int64) error -} - -// Locker is the interface required for custom lock persisting mechanisms. -// Common ways to store this information is in memory, on disk or using an -// external service, such as Redis. -// When multiple processes are attempting to access an upload, whether it be -// by reading or writing, a synchronization mechanism is required to prevent -// data corruption, especially to ensure correct offset values and the proper -// order of chunks inside a single upload. -type Locker interface { - // NewLock creates a new unlocked lock object for the given upload ID. - NewLock(id string) (Lock, error) -} - -// Lock is the interface for a lock as returned from a Locker. -type Lock interface { - // Lock attempts to obtain an exclusive lock for the upload specified - // by its id. - // If this operation fails because the resource is already locked, the - // tusd.ErrFileLocked must be returned. If no error is returned, the attempt - // is consider to be successful and the upload to be locked until UnlockUpload - // is invoked for the same upload. - Lock() error - // Unlock releases an existing lock for the given upload. - Unlock() error -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/doc.go b/vendor/github.com/tus/tusd/pkg/handler/doc.go deleted file mode 100644 index 7d1258b280..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/doc.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Package handler provides ways to accept tus 1.0 calls using HTTP. - -tus is a protocol based on HTTP for resumable file uploads. Resumable means that -an upload can be interrupted at any moment and can be resumed without -re-uploading the previous data again. An interruption may happen willingly, if -the user wants to pause, or by accident in case of an network issue or server -outage (http://tus.io). - -The basics of tusd - -tusd was designed in way which allows an flexible and customizable usage. We -wanted to avoid binding this package to a specific storage system – particularly -a proprietary third-party software. Therefore tusd is an abstract layer whose -only job is to accept incoming HTTP requests, validate them according to the -specification and finally passes them to the data store. - -The data store is another important component in tusd's architecture whose -purpose is to do the actual file handling. It has to write the incoming upload -to a persistent storage system and retrieve information about an upload's -current state. Therefore it is the only part of the system which communicates -directly with the underlying storage system, whether it be the local disk, a -remote FTP server or cloud providers such as AWS S3. - -Using a store composer - -The only hard requirements for a data store can be found in the DataStore -interface. It contains methods for creating uploads (NewUpload), writing to -them (WriteChunk) and retrieving their status (GetInfo). However, there -are many more features which are not mandatory but may still be used. -These are contained in their own interfaces which all share the *DataStore -suffix. For example, GetReaderDataStore which enables downloading uploads or -TerminaterDataStore which allows uploads to be terminated. - -The store composer offers a way to combine the basic data store - the core - -implementation and these additional extensions: - - composer := tusd.NewStoreComposer() - composer.UseCore(dataStore) // Implements DataStore - composer.UseTerminater(terminater) // Implements TerminaterDataStore - composer.UseLocker(locker) // Implements LockerDataStore - -The corresponding methods for adding an extension to the composer are prefixed -with Use* followed by the name of the corresponding interface. However, most -data store provide multiple extensions and adding all of them manually can be -tedious and error-prone. Therefore, all data store distributed with tusd provide -an UseIn() method which does this job automatically. For example, this is the -S3 store in action (see S3Store.UseIn): - - store := s3store.New(…) - locker := memorylocker.New() - composer := tusd.NewStoreComposer() - store.UseIn(composer) - locker.UseIn(composer) - -Finally, once you are done with composing your data store, you can pass it -inside the Config struct in order to create create a new tusd HTTP handler: - - config := tusd.Config{ - StoreComposer: composer, - BasePath: "/files/", - } - handler, err := tusd.NewHandler(config) - -This handler can then be mounted to a specific path, e.g. /files: - - http.Handle("/files/", http.StripPrefix("/files/", handler)) -*/ -package handler diff --git a/vendor/github.com/tus/tusd/pkg/handler/handler.go b/vendor/github.com/tus/tusd/pkg/handler/handler.go deleted file mode 100644 index c5030a672f..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/handler.go +++ /dev/null @@ -1,53 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/bmizerany/pat" -) - -// Handler is a ready to use handler with routing (using pat) -type Handler struct { - *UnroutedHandler - http.Handler -} - -// NewHandler creates a routed tus protocol handler. This is the simplest -// way to use tusd but may not be as configurable as you require. If you are -// integrating this into an existing app you may like to use tusd.NewUnroutedHandler -// instead. Using tusd.NewUnroutedHandler allows the tus handlers to be combined into -// your existing router (aka mux) directly. It also allows the GET and DELETE -// endpoints to be customized. These are not part of the protocol so can be -// changed depending on your needs. -func NewHandler(config Config) (*Handler, error) { - if err := config.validate(); err != nil { - return nil, err - } - - handler, err := NewUnroutedHandler(config) - if err != nil { - return nil, err - } - - routedHandler := &Handler{ - UnroutedHandler: handler, - } - - mux := pat.New() - - routedHandler.Handler = handler.Middleware(mux) - - mux.Post("", http.HandlerFunc(handler.PostFile)) - mux.Head(":id", http.HandlerFunc(handler.HeadFile)) - mux.Add("PATCH", ":id", http.HandlerFunc(handler.PatchFile)) - if !config.DisableDownload { - mux.Get(":id", http.HandlerFunc(handler.GetFile)) - } - - // Only attach the DELETE handler if the Terminate() method is provided - if config.StoreComposer.UsesTerminater && !config.DisableTermination { - mux.Del(":id", http.HandlerFunc(handler.DelFile)) - } - - return routedHandler, nil -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/log.go b/vendor/github.com/tus/tusd/pkg/handler/log.go deleted file mode 100644 index 38b67d3631..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/log.go +++ /dev/null @@ -1,27 +0,0 @@ -package handler - -import ( - "log" -) - -func (h *UnroutedHandler) log(eventName string, details ...string) { - LogEvent(h.logger, eventName, details...) -} - -func LogEvent(logger *log.Logger, eventName string, details ...string) { - result := make([]byte, 0, 100) - - result = append(result, `event="`...) - result = append(result, eventName...) - result = append(result, `" `...) - - for i := 0; i < len(details); i += 2 { - result = append(result, details[i]...) - result = append(result, `="`...) - result = append(result, details[i+1]...) - result = append(result, `" `...) - } - - result = append(result, "\n"...) - logger.Output(2, string(result)) -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/metrics.go b/vendor/github.com/tus/tusd/pkg/handler/metrics.go deleted file mode 100644 index 7115b8fff3..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/metrics.go +++ /dev/null @@ -1,137 +0,0 @@ -package handler - -import ( - "errors" - "sync" - "sync/atomic" -) - -// Metrics provides numbers about the usage of the tusd handler. Since these may -// be accessed from multiple goroutines, it is necessary to read and modify them -// atomically using the functions exposed in the sync/atomic package, such as -// atomic.LoadUint64. In addition the maps must not be modified to prevent data -// races. -type Metrics struct { - // RequestTotal counts the number of incoming requests per method - RequestsTotal map[string]*uint64 - // ErrorsTotal counts the number of returned errors by their message - ErrorsTotal *ErrorsTotalMap - BytesReceived *uint64 - UploadsFinished *uint64 - UploadsCreated *uint64 - UploadsTerminated *uint64 -} - -// incRequestsTotal increases the counter for this request method atomically by -// one. The method must be one of GET, HEAD, POST, PATCH, DELETE. -func (m Metrics) incRequestsTotal(method string) { - if ptr, ok := m.RequestsTotal[method]; ok { - atomic.AddUint64(ptr, 1) - } -} - -// incErrorsTotal increases the counter for this error atomically by one. -func (m Metrics) incErrorsTotal(err HTTPError) { - ptr := m.ErrorsTotal.retrievePointerFor(err) - atomic.AddUint64(ptr, 1) -} - -// incBytesReceived increases the number of received bytes atomically be the -// specified number. -func (m Metrics) incBytesReceived(delta uint64) { - atomic.AddUint64(m.BytesReceived, delta) -} - -// incUploadsFinished increases the counter for finished uploads atomically by one. -func (m Metrics) incUploadsFinished() { - atomic.AddUint64(m.UploadsFinished, 1) -} - -// incUploadsCreated increases the counter for completed uploads atomically by one. -func (m Metrics) incUploadsCreated() { - atomic.AddUint64(m.UploadsCreated, 1) -} - -// incUploadsTerminated increases the counter for completed uploads atomically by one. -func (m Metrics) incUploadsTerminated() { - atomic.AddUint64(m.UploadsTerminated, 1) -} - -func newMetrics() Metrics { - return Metrics{ - RequestsTotal: map[string]*uint64{ - "GET": new(uint64), - "HEAD": new(uint64), - "POST": new(uint64), - "PATCH": new(uint64), - "DELETE": new(uint64), - "OPTIONS": new(uint64), - }, - ErrorsTotal: newErrorsTotalMap(), - BytesReceived: new(uint64), - UploadsFinished: new(uint64), - UploadsCreated: new(uint64), - UploadsTerminated: new(uint64), - } -} - -// ErrorsTotalMap stores the counters for the different HTTP errors. -type ErrorsTotalMap struct { - lock sync.RWMutex - counter map[simpleHTTPError]*uint64 -} - -type simpleHTTPError struct { - Message string - StatusCode int -} - -func simplifyHTTPError(err HTTPError) simpleHTTPError { - return simpleHTTPError{ - Message: err.Error(), - StatusCode: err.StatusCode(), - } -} - -func newErrorsTotalMap() *ErrorsTotalMap { - m := make(map[simpleHTTPError]*uint64, 20) - return &ErrorsTotalMap{ - counter: m, - } -} - -// retrievePointerFor returns (after creating it if necessary) the pointer to -// the counter for the error. -func (e *ErrorsTotalMap) retrievePointerFor(err HTTPError) *uint64 { - serr := simplifyHTTPError(err) - e.lock.RLock() - ptr, ok := e.counter[serr] - e.lock.RUnlock() - if ok { - return ptr - } - - // For pointer creation, a write-lock is required - e.lock.Lock() - // We ensure that the pointer wasn't created in the meantime - if ptr, ok = e.counter[serr]; !ok { - ptr = new(uint64) - e.counter[serr] = ptr - } - e.lock.Unlock() - - return ptr -} - -// Load retrieves the map of the counter pointers atomically -func (e *ErrorsTotalMap) Load() map[HTTPError]*uint64 { - m := make(map[HTTPError]*uint64, len(e.counter)) - e.lock.RLock() - for err, ptr := range e.counter { - httpErr := NewHTTPError(errors.New(err.Message), err.StatusCode) - m[httpErr] = ptr - } - e.lock.RUnlock() - - return m -} diff --git a/vendor/github.com/tus/tusd/pkg/handler/unrouted_handler.go b/vendor/github.com/tus/tusd/pkg/handler/unrouted_handler.go deleted file mode 100644 index 0e0ab17957..0000000000 --- a/vendor/github.com/tus/tusd/pkg/handler/unrouted_handler.go +++ /dev/null @@ -1,1468 +0,0 @@ -package handler - -import ( - "context" - "encoding/base64" - "errors" - "io" - "log" - "math" - "mime" - "net" - "net/http" - "regexp" - "strconv" - "strings" - "time" -) - -const UploadLengthDeferred = "1" -const currentUploadDraftInteropVersion = "3" - -var ( - reExtractFileID = regexp.MustCompile(`([^/]+)\/?$`) - reForwardedHost = regexp.MustCompile(`host="?([^;"]+)`) - reForwardedProto = regexp.MustCompile(`proto=(https?)`) - reMimeType = regexp.MustCompile(`^[a-z]+\/[a-z0-9\-\+\.]+$`) -) - -// HTTPError represents an error with an additional status code attached -// which may be used when this error is sent in a HTTP response. -// See the net/http package for standardized status codes. -type HTTPError interface { - error - StatusCode() int - Body() []byte -} - -type httpError struct { - error - statusCode int -} - -func (err httpError) StatusCode() int { - return err.statusCode -} - -func (err httpError) Body() []byte { - return []byte(err.Error()) -} - -// NewHTTPError adds the given status code to the provided error and returns -// the new error instance. The status code may be used in corresponding HTTP -// responses. See the net/http package for standardized status codes. -func NewHTTPError(err error, statusCode int) HTTPError { - return httpError{err, statusCode} -} - -var ( - ErrUnsupportedVersion = NewHTTPError(errors.New("unsupported version"), http.StatusPreconditionFailed) - ErrMaxSizeExceeded = NewHTTPError(errors.New("maximum size exceeded"), http.StatusRequestEntityTooLarge) - ErrInvalidContentType = NewHTTPError(errors.New("missing or invalid Content-Type header"), http.StatusBadRequest) - ErrInvalidUploadLength = NewHTTPError(errors.New("missing or invalid Upload-Length header"), http.StatusBadRequest) - ErrInvalidOffset = NewHTTPError(errors.New("missing or invalid Upload-Offset header"), http.StatusBadRequest) - ErrNotFound = NewHTTPError(errors.New("upload not found"), http.StatusNotFound) - ErrFileLocked = NewHTTPError(errors.New("file currently locked"), 423) // Locked (WebDAV) (RFC 4918) - ErrMismatchOffset = NewHTTPError(errors.New("mismatched offset"), http.StatusConflict) - ErrSizeExceeded = NewHTTPError(errors.New("resource's size exceeded"), http.StatusRequestEntityTooLarge) - ErrNotImplemented = NewHTTPError(errors.New("feature not implemented"), http.StatusNotImplemented) - ErrUploadNotFinished = NewHTTPError(errors.New("one of the partial uploads is not finished"), http.StatusBadRequest) - ErrInvalidConcat = NewHTTPError(errors.New("invalid Upload-Concat header"), http.StatusBadRequest) - ErrModifyFinal = NewHTTPError(errors.New("modifying a final upload is not allowed"), http.StatusForbidden) - ErrUploadLengthAndUploadDeferLength = NewHTTPError(errors.New("provided both Upload-Length and Upload-Defer-Length"), http.StatusBadRequest) - ErrInvalidUploadDeferLength = NewHTTPError(errors.New("invalid Upload-Defer-Length header"), http.StatusBadRequest) - ErrUploadStoppedByServer = NewHTTPError(errors.New("upload has been stopped by server"), http.StatusBadRequest) - ErrOriginNotAllowed = NewHTTPError(errors.New("request origin is not allowed"), http.StatusForbidden) - - errReadTimeout = errors.New("read tcp: i/o timeout") - errConnectionReset = errors.New("read tcp: connection reset by peer") -) - -// HTTPRequest contains basic details of an incoming HTTP request. -type HTTPRequest struct { - // Method is the HTTP method, e.g. POST or PATCH - Method string - // URI is the full HTTP request URI, e.g. /files/fooo - URI string - // RemoteAddr contains the network address that sent the request - RemoteAddr string - // Header contains all HTTP headers as present in the HTTP request. - Header http.Header -} - -// HookEvent represents an event from tusd which can be handled by the application. -type HookEvent struct { - // Upload contains information about the upload that caused this hook - // to be fired. - Upload FileInfo - // HTTPRequest contains details about the HTTP request that reached - // tusd. - HTTPRequest HTTPRequest -} - -func newHookEvent(info FileInfo, r *http.Request) HookEvent { - // The Host header field is not present in the header map, see https://pkg.go.dev/net/http#Request: - // > For incoming requests, the Host header is promoted to the - // > Request.Host field and removed from the Header map. - // That's why we add it back manually. - r.Header.Set("Host", r.Host) - - return HookEvent{ - Upload: info, - HTTPRequest: HTTPRequest{ - Method: r.Method, - URI: r.RequestURI, - RemoteAddr: r.RemoteAddr, - Header: r.Header, - }, - } -} - -// UnroutedHandler exposes methods to handle requests as part of the tus protocol, -// such as PostFile, HeadFile, PatchFile and DelFile. In addition the GetFile method -// is provided which is, however, not part of the specification. -type UnroutedHandler struct { - config Config - composer *StoreComposer - isBasePathAbs bool - basePath string - logger *log.Logger - extensions string - - // CompleteUploads is used to send notifications whenever an upload is - // completed by a user. The HookEvent will contain information about this - // upload after it is completed. Sending to this channel will only - // happen if the NotifyCompleteUploads field is set to true in the Config - // structure. Notifications will also be sent for completions using the - // Concatenation extension. - CompleteUploads chan HookEvent - // TerminatedUploads is used to send notifications whenever an upload is - // terminated by a user. The HookEvent will contain information about this - // upload gathered before the termination. Sending to this channel will only - // happen if the NotifyTerminatedUploads field is set to true in the Config - // structure. - TerminatedUploads chan HookEvent - // UploadProgress is used to send notifications about the progress of the - // currently running uploads. For each open PATCH request, every second - // a HookEvent instance will be send over this channel with the Offset field - // being set to the number of bytes which have been transfered to the server. - // Please be aware that this number may be higher than the number of bytes - // which have been stored by the data store! Sending to this channel will only - // happen if the NotifyUploadProgress field is set to true in the Config - // structure. - UploadProgress chan HookEvent - // CreatedUploads is used to send notifications about the uploads having been - // created. It triggers post creation and therefore has all the HookEvent incl. - // the ID available already. It facilitates the post-create hook. Sending to - // this channel will only happen if the NotifyCreatedUploads field is set to - // true in the Config structure. - CreatedUploads chan HookEvent - // Metrics provides numbers of the usage for this handler. - Metrics Metrics -} - -// NewUnroutedHandler creates a new handler without routing using the given -// configuration. It exposes the http handlers which need to be combined with -// a router (aka mux) of your choice. If you are looking for preconfigured -// handler see NewHandler. -func NewUnroutedHandler(config Config) (*UnroutedHandler, error) { - if err := config.validate(); err != nil { - return nil, err - } - - // Only promote extesions using the Tus-Extension header which are implemented - extensions := "creation,creation-with-upload" - if config.StoreComposer.UsesTerminater { - extensions += ",termination" - } - if config.StoreComposer.UsesConcater { - extensions += ",concatenation" - } - if config.StoreComposer.UsesLengthDeferrer { - extensions += ",creation-defer-length" - } - - handler := &UnroutedHandler{ - config: config, - composer: config.StoreComposer, - basePath: config.BasePath, - isBasePathAbs: config.isAbs, - CompleteUploads: make(chan HookEvent), - TerminatedUploads: make(chan HookEvent), - UploadProgress: make(chan HookEvent), - CreatedUploads: make(chan HookEvent), - logger: config.Logger, - extensions: extensions, - Metrics: newMetrics(), - } - - return handler, nil -} - -// SupportedExtensions returns a comma-separated list of the supported tus extensions. -// The availability of an extension usually depends on whether the provided data store -// implements some additional interfaces. -func (handler *UnroutedHandler) SupportedExtensions() string { - return handler.extensions -} - -// Middleware checks various aspects of the request and ensures that it -// conforms with the spec. Also handles method overriding for clients which -// cannot make PATCH AND DELETE requests. If you are using the tusd handlers -// directly you will need to wrap at least the POST and PATCH endpoints in -// this middleware. -func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Allow overriding the HTTP method. The reason for this is - // that some libraries/environments do not support PATCH and - // DELETE requests, e.g. Flash in a browser and parts of Java. - if newMethod := r.Header.Get("X-HTTP-Method-Override"); r.Method == "POST" && newMethod != "" { - r.Method = newMethod - } - - handler.log("RequestIncoming", "method", r.Method, "path", r.URL.Path, "requestId", getRequestId(r)) - - handler.Metrics.incRequestsTotal(r.Method) - - header := w.Header() - - cors := handler.config.Cors - if origin := r.Header.Get("Origin"); !cors.Disable && origin != "" { - originIsAllowed := cors.AllowOrigin.MatchString(origin) - if !originIsAllowed { - handler.sendError(w, r, ErrOriginNotAllowed) - return - } - - header.Set("Access-Control-Allow-Origin", origin) - header.Set("Vary", "Origin") - - if cors.AllowCredentials { - header.Add("Access-Control-Allow-Credentials", "true") - } - - if r.Method == "OPTIONS" { - // Preflight request - header.Add("Access-Control-Allow-Methods", cors.AllowMethods) - header.Add("Access-Control-Allow-Headers", cors.AllowHeaders) - header.Set("Access-Control-Max-Age", cors.MaxAge) - } else { - // Actual request - header.Add("Access-Control-Expose-Headers", cors.ExposeHeaders) - } - } - - // Detect requests with tus v1 protocol vs the IETF resumable upload draft - isTusV1 := !handler.isResumableUploadDraftRequest(r) - - if isTusV1 { - // Set current version used by the server - header.Set("Tus-Resumable", "1.0.0") - } - - // Add nosniff to all responses https://golang.org/src/net/http/server.go#L1429 - header.Set("X-Content-Type-Options", "nosniff") - - // Set appropriated headers in case of OPTIONS method allowing protocol - // discovery and end with an 204 No Content - if r.Method == "OPTIONS" { - if handler.config.MaxSize > 0 { - header.Set("Tus-Max-Size", strconv.FormatInt(handler.config.MaxSize, 10)) - } - - header.Set("Tus-Version", "1.0.0") - header.Set("Tus-Extension", handler.extensions) - - // Although the 204 No Content status code is a better fit in this case, - // since we do not have a response body included, we cannot use it here - // as some browsers only accept 200 OK as successful response to a - // preflight request. If we send them the 204 No Content the response - // will be ignored or interpreted as a rejection. - // For example, the Presto engine, which is used in older versions of - // Opera, Opera Mobile and Opera Mini, handles CORS this way. - handler.sendResp(w, r, http.StatusOK) - return - } - - // Test if the version sent by the client is supported - // GET and HEAD methods are not checked since a browser may visit this URL and does - // not include this header. GET requests are not part of the specification. - if r.Method != "GET" && r.Method != "HEAD" && r.Header.Get("Tus-Resumable") != "1.0.0" && isTusV1 { - handler.sendError(w, r, ErrUnsupportedVersion) - return - } - - // Proceed with routing the request - h.ServeHTTP(w, r) - }) -} - -// PostFile creates a new file upload using the datastore after validating the -// length and parsing the metadata. -func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) { - if handler.isResumableUploadDraftRequest(r) { - handler.PostFileV2(w, r) - return - } - - ctx := context.Background() - - // Check for presence of application/offset+octet-stream. If another content - // type is defined, it will be ignored and treated as none was set because - // some HTTP clients may enforce a default value for this header. - containsChunk := r.Header.Get("Content-Type") == "application/offset+octet-stream" - - // Only use the proper Upload-Concat header if the concatenation extension - // is even supported by the data store. - var concatHeader string - if handler.composer.UsesConcater { - concatHeader = r.Header.Get("Upload-Concat") - } - - // Parse Upload-Concat header - isPartial, isFinal, partialUploadIDs, err := parseConcat(concatHeader) - if err != nil { - handler.sendError(w, r, err) - return - } - - // If the upload is a final upload created by concatenation multiple partial - // uploads the size is sum of all sizes of these files (no need for - // Upload-Length header) - var size int64 - var sizeIsDeferred bool - var partialUploads []Upload - if isFinal { - // A final upload must not contain a chunk within the creation request - if containsChunk { - handler.sendError(w, r, ErrModifyFinal) - return - } - - partialUploads, size, err = handler.sizeOfUploads(ctx, partialUploadIDs) - if err != nil { - handler.sendError(w, r, err) - return - } - } else { - uploadLengthHeader := r.Header.Get("Upload-Length") - uploadDeferLengthHeader := r.Header.Get("Upload-Defer-Length") - size, sizeIsDeferred, err = handler.validateNewUploadLengthHeaders(uploadLengthHeader, uploadDeferLengthHeader) - if err != nil { - handler.sendError(w, r, err) - return - } - } - - // Test whether the size is still allowed - if handler.config.MaxSize > 0 && size > handler.config.MaxSize { - handler.sendError(w, r, ErrMaxSizeExceeded) - return - } - - // Parse metadata - meta := ParseMetadataHeader(r.Header.Get("Upload-Metadata")) - - info := FileInfo{ - Size: size, - SizeIsDeferred: sizeIsDeferred, - MetaData: meta, - IsPartial: isPartial, - IsFinal: isFinal, - PartialUploads: partialUploadIDs, - } - - if handler.config.PreUploadCreateCallback != nil { - if err := handler.config.PreUploadCreateCallback(newHookEvent(info, r)); err != nil { - handler.sendError(w, r, err) - return - } - } - - upload, err := handler.composer.Core.NewUpload(ctx, info) - if err != nil { - handler.sendError(w, r, err) - return - } - - info, err = upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - id := info.ID - - // Add the Location header directly after creating the new resource to even - // include it in cases of failure when an error is returned - url := handler.absFileURL(r, id) - w.Header().Set("Location", url) - - handler.Metrics.incUploadsCreated() - handler.log("UploadCreated", "id", id, "size", i64toa(size), "url", url) - - if handler.config.NotifyCreatedUploads { - handler.CreatedUploads <- newHookEvent(info, r) - } - - if isFinal { - concatableUpload := handler.composer.Concater.AsConcatableUpload(upload) - if err := concatableUpload.ConcatUploads(ctx, partialUploads); err != nil { - handler.sendError(w, r, err) - return - } - info.Offset = size - - if handler.config.NotifyCompleteUploads { - handler.CompleteUploads <- newHookEvent(info, r) - } - } - - if containsChunk { - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - if err := handler.writeChunk(ctx, upload, info, w, r); err != nil { - handler.sendError(w, r, err) - return - } - } else if !sizeIsDeferred && size == 0 { - // Directly finish the upload if the upload is empty (i.e. has a size of 0). - // This statement is in an else-if block to avoid causing duplicate calls - // to finishUploadIfComplete if an upload is empty and contains a chunk. - if err := handler.finishUploadIfComplete(ctx, upload, info, r); err != nil { - handler.sendError(w, r, err) - return - } - } - - handler.sendResp(w, r, http.StatusCreated) -} - -// PostFile creates a new file upload using the datastore after validating the -// length and parsing the metadata. -func (handler *UnroutedHandler) PostFileV2(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() - - // Parse headers - contentType := r.Header.Get("Content-Type") - contentDisposition := r.Header.Get("Content-Disposition") - isComplete := r.Header.Get("Upload-Incomplete") == "?0" - - info := FileInfo{ - MetaData: make(MetaData), - } - if isComplete && r.ContentLength != -1 { - // If the client wants to perform the upload in one request with Content-Length, we know the final upload size. - info.Size = r.ContentLength - } else { - // Error out if the storage does not support upload length deferring, but we need it. - if !handler.composer.UsesLengthDeferrer { - handler.sendError(w, r, ErrNotImplemented) - return - } - - info.SizeIsDeferred = true - } - - // Parse Content-Type and Content-Disposition to get file type or file name - if contentType != "" { - fileType, _, err := mime.ParseMediaType(contentType) - if err != nil { - handler.sendError(w, r, err) - return - } - - info.MetaData["filetype"] = fileType - } - - if contentDisposition != "" { - _, values, err := mime.ParseMediaType(contentDisposition) - if err != nil { - handler.sendError(w, r, err) - return - } - - if values["filename"] != "" { - info.MetaData["filename"] = values["filename"] - } - } - - // 1. Create upload resource - if handler.config.PreUploadCreateCallback != nil { - if err := handler.config.PreUploadCreateCallback(newHookEvent(info, r)); err != nil { - handler.sendError(w, r, err) - return - } - } - - upload, err := handler.composer.Core.NewUpload(ctx, info) - if err != nil { - handler.sendError(w, r, err) - return - } - - info, err = upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - id := info.ID - - // Add the Location header directly after creating the new resource to even - // include it in cases of failure when an error is returned - url := handler.absFileURL(r, id) - w.Header().Set("Location", url) - - // Send 104 response - w.Header().Set("Upload-Draft-Interop-Version", currentUploadDraftInteropVersion) - w.WriteHeader(104) - - handler.Metrics.incUploadsCreated() - - handler.log("UploadCreated", "id", id, "size", i64toa(info.Size), "url", url) - - if handler.config.NotifyCreatedUploads { - handler.CreatedUploads <- newHookEvent(info, r) - } - - // 2. Lock upload - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - // 3. Write chunk - if err := handler.writeChunk(ctx, upload, info, w, r); err != nil { - handler.sendError(w, r, err) - return - } - - // 4. Finish upload, if necessary - if isComplete && info.SizeIsDeferred { - info, err = upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - uploadLength := info.Offset - - lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) - if err := lengthDeclarableUpload.DeclareLength(ctx, uploadLength); err != nil { - handler.sendError(w, r, err) - return - } - - info.Size = uploadLength - info.SizeIsDeferred = false - - if err := handler.finishUploadIfComplete(ctx, upload, info, r); err != nil { - handler.sendError(w, r, err) - return - } - - } - - handler.sendResp(w, r, http.StatusCreated) -} - -// HeadFile returns the length and offset for the HEAD request -func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() - - id, err := extractIDFromPath(r.URL.Path) - if err != nil { - handler.sendError(w, r, err) - return - } - - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - upload, err := handler.composer.Core.GetUpload(ctx, id) - if err != nil { - handler.sendError(w, r, err) - return - } - - info, err := upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - w.Header().Set("Cache-Control", "no-store") - w.Header().Set("Upload-Offset", strconv.FormatInt(info.Offset, 10)) - - if !handler.isResumableUploadDraftRequest(r) { - // Add Upload-Concat header if possible - if info.IsPartial { - w.Header().Set("Upload-Concat", "partial") - } - - if info.IsFinal { - v := "final;" - for _, uploadID := range info.PartialUploads { - v += handler.absFileURL(r, uploadID) + " " - } - // Remove trailing space - v = v[:len(v)-1] - - w.Header().Set("Upload-Concat", v) - } - - if len(info.MetaData) != 0 { - w.Header().Set("Upload-Metadata", SerializeMetadataHeader(info.MetaData)) - } - - if info.SizeIsDeferred { - w.Header().Set("Upload-Defer-Length", UploadLengthDeferred) - } else { - w.Header().Set("Upload-Length", strconv.FormatInt(info.Size, 10)) - w.Header().Set("Content-Length", strconv.FormatInt(info.Size, 10)) - } - - // TODO: We send a 200 OK here by default. Can we switch this to 204? - handler.sendResp(w, r, http.StatusOK) - } else { - if !info.SizeIsDeferred && info.Offset == info.Size { - // Upload is complete if we know the size and it matches the offset. - w.Header().Set("Upload-Incomplete", "?0") - } else { - w.Header().Set("Upload-Incomplete", "?1") - } - - w.Header().Set("Upload-Draft-Interop-Version", currentUploadDraftInteropVersion) - - // Draft requires a 204 No Content response - handler.sendResp(w, r, http.StatusNoContent) - } -} - -// PatchFile adds a chunk to an upload. This operation is only allowed -// if enough space in the upload is left. -func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() - - isTusV1 := !handler.isResumableUploadDraftRequest(r) - - // Check for presence of application/offset+octet-stream - if isTusV1 && r.Header.Get("Content-Type") != "application/offset+octet-stream" { - handler.sendError(w, r, ErrInvalidContentType) - return - } - - // Check for presence of a valid Upload-Offset Header - offset, err := strconv.ParseInt(r.Header.Get("Upload-Offset"), 10, 64) - if err != nil || offset < 0 { - handler.sendError(w, r, ErrInvalidOffset) - return - } - - id, err := extractIDFromPath(r.URL.Path) - if err != nil { - handler.sendError(w, r, err) - return - } - - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - upload, err := handler.composer.Core.GetUpload(ctx, id) - if err != nil { - handler.sendError(w, r, err) - return - } - - info, err := upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - // Modifying a final upload is not allowed - if info.IsFinal { - handler.sendError(w, r, ErrModifyFinal) - return - } - - if offset != info.Offset { - handler.sendError(w, r, ErrMismatchOffset) - return - } - - // TODO: If Upload-Incomplete: ?0 and Content-Length is set, we can - // - declare the length already here - // - validate that the length from this request matches info.Size if !info.SizeIsDeferred - - // Do not proxy the call to the data store if the upload is already completed - if !info.SizeIsDeferred && info.Offset == info.Size { - w.Header().Set("Upload-Offset", strconv.FormatInt(offset, 10)) - handler.sendResp(w, r, http.StatusNoContent) - return - } - - if r.Header.Get("Upload-Length") != "" { - if !handler.composer.UsesLengthDeferrer { - handler.sendError(w, r, ErrNotImplemented) - return - } - if !info.SizeIsDeferred { - handler.sendError(w, r, ErrInvalidUploadLength) - return - } - uploadLength, err := strconv.ParseInt(r.Header.Get("Upload-Length"), 10, 64) - if err != nil || uploadLength < 0 || uploadLength < info.Offset || (handler.config.MaxSize > 0 && uploadLength > handler.config.MaxSize) { - handler.sendError(w, r, ErrInvalidUploadLength) - return - } - - lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) - if err := lengthDeclarableUpload.DeclareLength(ctx, uploadLength); err != nil { - handler.sendError(w, r, err) - return - } - - info.Size = uploadLength - info.SizeIsDeferred = false - } - - if err := handler.writeChunk(ctx, upload, info, w, r); err != nil { - handler.sendError(w, r, err) - return - } - - isComplete := r.Header.Get("Upload-Incomplete") == "?0" - if isComplete && info.SizeIsDeferred { - info, err = upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - uploadLength := info.Offset - - lengthDeclarableUpload := handler.composer.LengthDeferrer.AsLengthDeclarableUpload(upload) - if err := lengthDeclarableUpload.DeclareLength(ctx, uploadLength); err != nil { - handler.sendError(w, r, err) - return - } - - info.Size = uploadLength - info.SizeIsDeferred = false - - if err := handler.finishUploadIfComplete(ctx, upload, info, r); err != nil { - handler.sendError(w, r, err) - return - } - - } - - handler.sendResp(w, r, http.StatusNoContent) -} - -// writeChunk reads the body from the requests r and appends it to the upload -// with the corresponding id. Afterwards, it will set the necessary response -// headers but will not send the response. -func (handler *UnroutedHandler) writeChunk(ctx context.Context, upload Upload, info FileInfo, w http.ResponseWriter, r *http.Request) error { - // Get Content-Length if possible - length := r.ContentLength - offset := info.Offset - id := info.ID - - // Test if this upload fits into the file's size - if !info.SizeIsDeferred && offset+length > info.Size { - return ErrSizeExceeded - } - - maxSize := info.Size - offset - // If the upload's length is deferred and the PATCH request does not contain the Content-Length - // header (which is allowed if 'Transfer-Encoding: chunked' is used), we still need to set limits for - // the body size. - if info.SizeIsDeferred { - if handler.config.MaxSize > 0 { - // Ensure that the upload does not exceed the maximum upload size - maxSize = handler.config.MaxSize - offset - } else { - // If no upload limit is given, we allow arbitrary sizes - maxSize = math.MaxInt64 - } - } - if length > 0 { - maxSize = length - } - - handler.log("ChunkWriteStart", "id", id, "maxSize", i64toa(maxSize), "offset", i64toa(offset)) - - var bytesWritten int64 - var err error - // Prevent a nil pointer dereference when accessing the body which may not be - // available in the case of a malicious request. - if r.Body != nil { - // Limit the data read from the request's body to the allowed maximum - reader := newBodyReader(io.LimitReader(r.Body, maxSize)) - - // We use a context object to allow the hook system to cancel an upload - uploadCtx, stopUpload := context.WithCancel(context.Background()) - info.stopUpload = stopUpload - // terminateUpload specifies whether the upload should be deleted after - // the write has finished - terminateUpload := false - // Cancel the context when the function exits to ensure that the goroutine - // is properly cleaned up - defer stopUpload() - - go func() { - // Interrupt the Read() call from the request body - <-uploadCtx.Done() - terminateUpload = true - r.Body.Close() - }() - - if handler.config.NotifyUploadProgress { - stopProgressEvents := handler.sendProgressMessages(newHookEvent(info, r), reader) - defer close(stopProgressEvents) - } - - bytesWritten, err = upload.WriteChunk(ctx, offset, reader) - if terminateUpload && handler.composer.UsesTerminater { - if terminateErr := handler.terminateUpload(ctx, upload, info, r); terminateErr != nil { - // We only log this error and not show it to the user since this - // termination error is not relevant to the uploading client - handler.log("UploadStopTerminateError", "id", id, "error", terminateErr.Error()) - } - } - - // If we encountered an error while reading the body from the HTTP request, log it, but only include - // it in the response, if the store did not also return an error. - if bodyErr := reader.hasError(); bodyErr != nil { - handler.log("BodyReadError", "id", id, "error", bodyErr.Error()) - if err == nil { - err = bodyErr - } - } - - // If the upload was stopped by the server, send an error response indicating this. - // TODO: Include a custom reason for the end user why the upload was stopped. - if terminateUpload { - err = ErrUploadStoppedByServer - } - } - - handler.log("ChunkWriteComplete", "id", id, "bytesWritten", i64toa(bytesWritten)) - - if err != nil { - return err - } - - // Send new offset to client - newOffset := offset + bytesWritten - w.Header().Set("Upload-Offset", strconv.FormatInt(newOffset, 10)) - handler.Metrics.incBytesReceived(uint64(bytesWritten)) - info.Offset = newOffset - - return handler.finishUploadIfComplete(ctx, upload, info, r) -} - -// finishUploadIfComplete checks whether an upload is completed (i.e. upload offset -// matches upload size) and if so, it will call the data store's FinishUpload -// function and send the necessary message on the CompleteUpload channel. -func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, upload Upload, info FileInfo, r *http.Request) error { - // If the upload is completed, ... - if !info.SizeIsDeferred && info.Offset == info.Size { - // ... allow the data storage to finish and cleanup the upload - if err := upload.FinishUpload(ctx); err != nil { - return err - } - - // ... allow the hook callback to run before sending the response - if handler.config.PreFinishResponseCallback != nil { - if err := handler.config.PreFinishResponseCallback(newHookEvent(info, r)); err != nil { - return err - } - } - - handler.Metrics.incUploadsFinished() - - // ... send the info out to the channel - if handler.config.NotifyCompleteUploads { - handler.CompleteUploads <- newHookEvent(info, r) - } - } - - return nil -} - -// GetFile handles requests to download a file using a GET request. This is not -// part of the specification. -func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() - - id, err := extractIDFromPath(r.URL.Path) - if err != nil { - handler.sendError(w, r, err) - return - } - - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - upload, err := handler.composer.Core.GetUpload(ctx, id) - if err != nil { - handler.sendError(w, r, err) - return - } - - info, err := upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - // Set headers before sending responses - w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10)) - - contentType, contentDisposition := filterContentType(info) - w.Header().Set("Content-Type", contentType) - w.Header().Set("Content-Disposition", contentDisposition) - - // If no data has been uploaded yet, respond with an empty "204 No Content" status. - if info.Offset == 0 { - handler.sendResp(w, r, http.StatusNoContent) - return - } - - src, err := upload.GetReader(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - - handler.sendResp(w, r, http.StatusOK) - io.Copy(w, src) - - // Try to close the reader if the io.Closer interface is implemented - if closer, ok := src.(io.Closer); ok { - closer.Close() - } -} - -// mimeInlineBrowserWhitelist is a map containing MIME types which should be -// allowed to be rendered by browser inline, instead of being forced to be -// downloaded. For example, HTML or SVG files are not allowed, since they may -// contain malicious JavaScript. In a similiar fashion PDF is not on this list -// as their parsers commonly contain vulnerabilities which can be exploited. -// The values of this map does not convey any meaning and are therefore just -// empty structs. -var mimeInlineBrowserWhitelist = map[string]struct{}{ - "text/plain": struct{}{}, - - "image/png": struct{}{}, - "image/jpeg": struct{}{}, - "image/gif": struct{}{}, - "image/bmp": struct{}{}, - "image/webp": struct{}{}, - - "audio/wave": struct{}{}, - "audio/wav": struct{}{}, - "audio/x-wav": struct{}{}, - "audio/x-pn-wav": struct{}{}, - "audio/webm": struct{}{}, - "video/webm": struct{}{}, - "audio/ogg": struct{}{}, - "video/ogg": struct{}{}, - "application/ogg": struct{}{}, -} - -// filterContentType returns the values for the Content-Type and -// Content-Disposition headers for a given upload. These values should be used -// in responses for GET requests to ensure that only non-malicious file types -// are shown directly in the browser. It will extract the file name and type -// from the "fileame" and "filetype". -// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition -func filterContentType(info FileInfo) (contentType string, contentDisposition string) { - filetype := info.MetaData["filetype"] - - if reMimeType.MatchString(filetype) { - // If the filetype from metadata is well formed, we forward use this - // for the Content-Type header. However, only whitelisted mime types - // will be allowed to be shown inline in the browser - contentType = filetype - if _, isWhitelisted := mimeInlineBrowserWhitelist[filetype]; isWhitelisted { - contentDisposition = "inline" - } else { - contentDisposition = "attachment" - } - } else { - // If the filetype from the metadata is not well formed, we use a - // default type and force the browser to download the content. - contentType = "application/octet-stream" - contentDisposition = "attachment" - } - - // Add a filename to Content-Disposition if one is available in the metadata - if filename, ok := info.MetaData["filename"]; ok { - contentDisposition += ";filename=" + strconv.Quote(filename) - } - - return contentType, contentDisposition -} - -// DelFile terminates an upload permanently. -func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() - - // Abort the request handling if the required interface is not implemented - if !handler.composer.UsesTerminater { - handler.sendError(w, r, ErrNotImplemented) - return - } - - id, err := extractIDFromPath(r.URL.Path) - if err != nil { - handler.sendError(w, r, err) - return - } - - if handler.composer.UsesLocker { - lock, err := handler.lockUpload(id) - if err != nil { - handler.sendError(w, r, err) - return - } - - defer lock.Unlock() - } - - upload, err := handler.composer.Core.GetUpload(ctx, id) - if err != nil { - handler.sendError(w, r, err) - return - } - - var info FileInfo - if handler.config.NotifyTerminatedUploads { - info, err = upload.GetInfo(ctx) - if err != nil { - handler.sendError(w, r, err) - return - } - } - - err = handler.terminateUpload(ctx, upload, info, r) - if err != nil { - handler.sendError(w, r, err) - return - } - - handler.sendResp(w, r, http.StatusNoContent) -} - -// terminateUpload passes a given upload to the DataStore's Terminater, -// send the corresponding upload info on the TerminatedUploads channnel -// and updates the statistics. -// Note the the info argument is only needed if the terminated uploads -// notifications are enabled. -func (handler *UnroutedHandler) terminateUpload(ctx context.Context, upload Upload, info FileInfo, r *http.Request) error { - terminatableUpload := handler.composer.Terminater.AsTerminatableUpload(upload) - - err := terminatableUpload.Terminate(ctx) - if err != nil { - return err - } - - if handler.config.NotifyTerminatedUploads { - handler.TerminatedUploads <- newHookEvent(info, r) - } - - handler.Metrics.incUploadsTerminated() - - return nil -} - -// Send the error in the response body. The status code will be looked up in -// ErrStatusCodes. If none is found 500 Internal Error will be used. -func (handler *UnroutedHandler) sendError(w http.ResponseWriter, r *http.Request, err error) { - // Errors for read timeouts contain too much information which is not - // necessary for us and makes grouping for the metrics harder. The error - // message looks like: read tcp 127.0.0.1:1080->127.0.0.1:53673: i/o timeout - // Therefore, we use a common error message for all of them. - if netErr, ok := err.(net.Error); ok && netErr.Timeout() { - err = errReadTimeout - } - - // Errors for connnection resets also contain TCP details, we don't need, e.g: - // read tcp 127.0.0.1:1080->127.0.0.1:10023: read: connection reset by peer - // Therefore, we also trim those down. - if strings.HasSuffix(err.Error(), "read: connection reset by peer") { - err = errConnectionReset - } - - // TODO: Decide if we should handle this in here, in body_reader or not at all. - // If the HTTP PATCH request gets interrupted in the middle (e.g. because - // the user wants to pause the upload), Go's net/http returns an io.ErrUnexpectedEOF. - // However, for the handler it's not important whether the stream has ended - // on purpose or accidentally. - //if err == io.ErrUnexpectedEOF { - // err = nil - //} - - // TODO: Decide if we want to ignore connection reset errors all together. - // In some cases, the HTTP connection gets reset by the other peer. This is not - // necessarily the tus client but can also be a proxy in front of tusd, e.g. HAProxy 2 - // is known to reset the connection to tusd, when the tus client closes the connection. - // To avoid erroring out in this case and loosing the uploaded data, we can ignore - // the error here without causing harm. - //if strings.Contains(err.Error(), "read: connection reset by peer") { - // err = nil - //} - - statusErr, ok := err.(HTTPError) - if !ok { - statusErr = NewHTTPError(err, http.StatusInternalServerError) - } - - reason := append(statusErr.Body(), '\n') - if r.Method == "HEAD" { - reason = nil - } - - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("Content-Length", strconv.Itoa(len(reason))) - w.WriteHeader(statusErr.StatusCode()) - w.Write(reason) - - handler.log("ResponseOutgoing", "status", strconv.Itoa(statusErr.StatusCode()), "method", r.Method, "path", r.URL.Path, "error", err.Error(), "requestId", getRequestId(r)) - - handler.Metrics.incErrorsTotal(statusErr) -} - -// sendResp writes the header to w with the specified status code. -func (handler *UnroutedHandler) sendResp(w http.ResponseWriter, r *http.Request, status int) { - w.WriteHeader(status) - - handler.log("ResponseOutgoing", "status", strconv.Itoa(status), "method", r.Method, "path", r.URL.Path, "requestId", getRequestId(r)) -} - -// Make an absolute URLs to the given upload id. If the base path is absolute -// it will be prepended else the host and protocol from the request is used. -func (handler *UnroutedHandler) absFileURL(r *http.Request, id string) string { - if handler.isBasePathAbs { - return handler.basePath + id - } - - // Read origin and protocol from request - host, proto := getHostAndProtocol(r, handler.config.RespectForwardedHeaders) - - url := proto + "://" + host + handler.basePath + id - - return url -} - -// sendProgressMessage will send a notification over the UploadProgress channel -// every second, indicating how much data has been transfered to the server. -// It will stop sending these instances once the returned channel has been -// closed. -func (handler *UnroutedHandler) sendProgressMessages(hook HookEvent, reader *bodyReader) chan<- struct{} { - previousOffset := int64(0) - originalOffset := hook.Upload.Offset - stop := make(chan struct{}, 1) - - go func() { - for { - select { - case <-stop: - hook.Upload.Offset = originalOffset + reader.bytesRead() - if hook.Upload.Offset != previousOffset { - handler.UploadProgress <- hook - previousOffset = hook.Upload.Offset - } - return - case <-time.After(1 * time.Second): - hook.Upload.Offset = originalOffset + reader.bytesRead() - if hook.Upload.Offset != previousOffset { - handler.UploadProgress <- hook - previousOffset = hook.Upload.Offset - } - } - } - }() - - return stop -} - -// getHostAndProtocol extracts the host and used protocol (either HTTP or HTTPS) -// from the given request. If `allowForwarded` is set, the X-Forwarded-Host, -// X-Forwarded-Proto and Forwarded headers will also be checked to -// support proxies. -func getHostAndProtocol(r *http.Request, allowForwarded bool) (host, proto string) { - if r.TLS != nil { - proto = "https" - } else { - proto = "http" - } - - host = r.Host - - if !allowForwarded { - return - } - - if h := r.Header.Get("X-Forwarded-Host"); h != "" { - host = h - } - - if h := r.Header.Get("X-Forwarded-Proto"); h == "http" || h == "https" { - proto = h - } - - if h := r.Header.Get("Forwarded"); h != "" { - if r := reForwardedHost.FindStringSubmatch(h); len(r) == 2 { - host = r[1] - } - - if r := reForwardedProto.FindStringSubmatch(h); len(r) == 2 { - proto = r[1] - } - } - - return -} - -// The get sum of all sizes for a list of upload ids while checking whether -// all of these uploads are finished yet. This is used to calculate the size -// of a final resource. -func (handler *UnroutedHandler) sizeOfUploads(ctx context.Context, ids []string) (partialUploads []Upload, size int64, err error) { - partialUploads = make([]Upload, len(ids)) - - for i, id := range ids { - upload, err := handler.composer.Core.GetUpload(ctx, id) - if err != nil { - return nil, 0, err - } - - info, err := upload.GetInfo(ctx) - if err != nil { - return nil, 0, err - } - - if info.SizeIsDeferred || info.Offset != info.Size { - err = ErrUploadNotFinished - return nil, 0, err - } - - size += info.Size - partialUploads[i] = upload - } - - return -} - -// Verify that the Upload-Length and Upload-Defer-Length headers are acceptable for creating a -// new upload -func (handler *UnroutedHandler) validateNewUploadLengthHeaders(uploadLengthHeader string, uploadDeferLengthHeader string) (uploadLength int64, uploadLengthDeferred bool, err error) { - haveBothLengthHeaders := uploadLengthHeader != "" && uploadDeferLengthHeader != "" - haveInvalidDeferHeader := uploadDeferLengthHeader != "" && uploadDeferLengthHeader != UploadLengthDeferred - lengthIsDeferred := uploadDeferLengthHeader == UploadLengthDeferred - - if lengthIsDeferred && !handler.composer.UsesLengthDeferrer { - err = ErrNotImplemented - } else if haveBothLengthHeaders { - err = ErrUploadLengthAndUploadDeferLength - } else if haveInvalidDeferHeader { - err = ErrInvalidUploadDeferLength - } else if lengthIsDeferred { - uploadLengthDeferred = true - } else { - uploadLength, err = strconv.ParseInt(uploadLengthHeader, 10, 64) - if err != nil || uploadLength < 0 { - err = ErrInvalidUploadLength - } - } - - return -} - -// lockUpload creates a new lock for the given upload ID and attempts to lock it. -// The created lock is returned if it was aquired successfully. -func (handler *UnroutedHandler) lockUpload(id string) (Lock, error) { - lock, err := handler.composer.Locker.NewLock(id) - if err != nil { - return nil, err - } - - if err := lock.Lock(); err != nil { - return nil, err - } - - return lock, nil -} - -// isResumableUploadDraftRequest returns whether a HTTP request includes a sign that it is -// related to resumable upload draft from IETF (instead of tus v1) -func (handler UnroutedHandler) isResumableUploadDraftRequest(r *http.Request) bool { - return handler.config.EnableExperimentalProtocol && r.Header.Get("Upload-Draft-Interop-Version") == currentUploadDraftInteropVersion -} - -// ParseMetadataHeader parses the Upload-Metadata header as defined in the -// File Creation extension. -// e.g. Upload-Metadata: name bHVucmpzLnBuZw==,type aW1hZ2UvcG5n -func ParseMetadataHeader(header string) map[string]string { - meta := make(map[string]string) - - for _, element := range strings.Split(header, ",") { - element := strings.TrimSpace(element) - - parts := strings.Split(element, " ") - - if len(parts) > 2 { - continue - } - - key := parts[0] - if key == "" { - continue - } - - value := "" - if len(parts) == 2 { - // Ignore current element if the value is no valid base64 - dec, err := base64.StdEncoding.DecodeString(parts[1]) - if err != nil { - continue - } - - value = string(dec) - } - - meta[key] = value - } - - return meta -} - -// SerializeMetadataHeader serializes a map of strings into the Upload-Metadata -// header format used in the response for HEAD requests. -// e.g. Upload-Metadata: name bHVucmpzLnBuZw==,type aW1hZ2UvcG5n -func SerializeMetadataHeader(meta map[string]string) string { - header := "" - for key, value := range meta { - valueBase64 := base64.StdEncoding.EncodeToString([]byte(value)) - header += key + " " + valueBase64 + "," - } - - // Remove trailing comma - if len(header) > 0 { - header = header[:len(header)-1] - } - - return header -} - -// Parse the Upload-Concat header, e.g. -// Upload-Concat: partial -// Upload-Concat: final;http://tus.io/files/a /files/b/ -func parseConcat(header string) (isPartial bool, isFinal bool, partialUploads []string, err error) { - if len(header) == 0 { - return - } - - if header == "partial" { - isPartial = true - return - } - - l := len("final;") - if strings.HasPrefix(header, "final;") && len(header) > l { - isFinal = true - - list := strings.Split(header[l:], " ") - for _, value := range list { - value := strings.TrimSpace(value) - if value == "" { - continue - } - - id, extractErr := extractIDFromPath(value) - if extractErr != nil { - err = extractErr - return - } - - partialUploads = append(partialUploads, id) - } - } - - // If no valid partial upload ids are extracted this is not a final upload. - if len(partialUploads) == 0 { - isFinal = false - err = ErrInvalidConcat - } - - return -} - -// extractIDFromPath pulls the last segment from the url provided -func extractIDFromPath(url string) (string, error) { - result := reExtractFileID.FindStringSubmatch(url) - if len(result) != 2 { - return "", ErrNotFound - } - return result[1], nil -} - -func i64toa(num int64) string { - return strconv.FormatInt(num, 10) -} - -// getRequestId returns the value of the X-Request-ID header, if available, -// and also takes care of truncating the input. -func getRequestId(r *http.Request) string { - reqId := r.Header.Get("X-Request-ID") - if reqId == "" { - return "" - } - - // Limit the length of the request ID to 36 characters, which is enough - // to fit a UUID. - if len(reqId) > 36 { - reqId = reqId[:36] - } - - return reqId -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 8992dc2f0a..5dc5e38640 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -261,9 +261,6 @@ github.com/blevesearch/zapx/v16 # github.com/bluele/gcache v0.0.2 ## explicit; go 1.15 github.com/bluele/gcache -# github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f -## explicit -github.com/bmizerany/pat # github.com/bombsimon/logrusr/v3 v3.1.0 ## explicit; go 1.17 github.com/bombsimon/logrusr/v3 @@ -1100,6 +1097,8 @@ github.com/golang/snappy # github.com/gomodule/redigo v1.8.9 ## explicit; go 1.16 github.com/gomodule/redigo/redis +# github.com/google/flatbuffers v2.0.8+incompatible +## explicit # github.com/google/go-cmp v0.6.0 ## explicit; go 1.13 github.com/google/go-cmp/cmp @@ -1882,9 +1881,6 @@ github.com/trustelem/zxcvbn/internal/mathutils github.com/trustelem/zxcvbn/match github.com/trustelem/zxcvbn/matching github.com/trustelem/zxcvbn/scoring -# github.com/tus/tusd v1.13.0 -## explicit; go 1.16 -github.com/tus/tusd/pkg/handler # github.com/tus/tusd/v2 v2.4.0 ## explicit; go 1.20 github.com/tus/tusd/v2/pkg/handler