From 6782c2473dda9560436304a2c605fd4916f6ca3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 06:12:32 +0000 Subject: [PATCH] chore(deps): bump github.com/tus/tusd/v2 from 2.5.0 to 2.6.0 Bumps [github.com/tus/tusd/v2](https://github.com/tus/tusd) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/tus/tusd/releases) - [Commits](https://github.com/tus/tusd/compare/v2.5.0...v2.6.0) --- updated-dependencies: - dependency-name: github.com/tus/tusd/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 5 +- go.sum | 10 +- .../hashicorp/go-plugin/CHANGELOG.md | 12 +- .../github.com/hashicorp/go-plugin/client.go | 2 +- .../hashicorp/go-plugin/grpc_broker.go | 9 +- .../internal/cmdrunner/cmd_reattach.go | 1 - .../github.com/hashicorp/go-plugin/testing.go | 12 +- .../go-testing-interface/.travis.yml | 12 -- .../mitchellh/go-testing-interface/LICENSE | 21 ---- .../mitchellh/go-testing-interface/README.md | 60 ---------- .../mitchellh/go-testing-interface/testing.go | 112 ------------------ .../tus/tusd/v2/pkg/handler/body_reader.go | 25 +++- .../tusd/v2/pkg/handler/unrouted_handler.go | 111 +++++++++++++++-- vendor/modules.txt | 9 +- 14 files changed, 154 insertions(+), 247 deletions(-) delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/.travis.yml delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/LICENSE delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/README.md delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/testing.go diff --git a/go.mod b/go.mod index f488db8eee..2dbe9b77c1 100644 --- a/go.mod +++ b/go.mod @@ -84,7 +84,7 @@ require ( github.com/test-go/testify v1.1.4 github.com/thejerf/suture/v4 v4.0.5 github.com/tidwall/gjson v1.18.0 - github.com/tus/tusd/v2 v2.5.0 + github.com/tus/tusd/v2 v2.6.0 github.com/unrolled/secure v1.16.0 github.com/urfave/cli/v2 v2.27.5 github.com/xhit/go-simple-mail/v2 v2.16.0 @@ -232,7 +232,7 @@ require ( github.com/gorilla/schema v1.4.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect - github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect @@ -263,7 +263,6 @@ require ( github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/minio-go/v7 v7.0.78 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index 8064765ee7..f036ec2a71 100644 --- a/go.sum +++ b/go.sum @@ -607,8 +607,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -805,8 +805,6 @@ github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HK github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -1107,8 +1105,8 @@ 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/v2 v2.5.0 h1:72/2Ws3kF0upYqENcbb0yr4aca0HByDNkIjOs5yh0es= -github.com/tus/tusd/v2 v2.5.0/go.mod h1:dUDNT4TvTMSqsTZvdAokc8e5xsZ+SsxvOCOPoyEeOJQ= +github.com/tus/tusd/v2 v2.6.0 h1:Je243QDKnFTvm/WkLH2bd1oQ+7trolrflRWyuI0PdWI= +github.com/tus/tusd/v2 v2.6.0/go.mod h1:1Eb1lBoSRBfYJ/mQfFVjyw8ZdNMdBqW17vgQKl3Ah9g= 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= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= diff --git a/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md b/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md index 722ad4f2aa..ca16273c1f 100644 --- a/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md +++ b/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.6.2 + +ENHANCEMENTS: + +* Added support for gRPC dial options to the `Dial` API [[GH-257](https://github.com/hashicorp/go-plugin/pull/257)] + +BUGS: + +* Fixed a bug where reattaching to a plugin that exits could kill an unrelated process [[GH-320](https://github.com/hashicorp/go-plugin/pull/320)] + ## v1.6.1 BUGS: @@ -13,7 +23,7 @@ ENHANCEMENTS: CHANGES: * plugin: Plugins written in other languages can optionally start to advertise whether they support gRPC broker multiplexing. - If the environment variable `PLUGIN_MULTIPLEX_GRPC` is set, it is safe to include a seventh field containing a boolean + If the environment variable `PLUGIN_MULTIPLEX_GRPC` is set, it is safe to include a seventh field containing a boolean value in the `|`-separated protocol negotiation line. ENHANCEMENTS: diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go index b813ba8cd3..df2fd22c82 100644 --- a/vendor/github.com/hashicorp/go-plugin/client.go +++ b/vendor/github.com/hashicorp/go-plugin/client.go @@ -82,7 +82,7 @@ const defaultPluginLogBufferSize = 64 * 1024 // // Plugin hosts should use one Client for each plugin executable. To // dispense a plugin type, use the `Client.Client` function, and then -// cal `Dispense`. This awkward API is mostly historical but is used to split +// call `Dispense`. This awkward API is mostly historical but is used to split // the client that deals with subprocess management and the client that // does RPC management. // diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go index 5b17e37fef..4bac0a5f7d 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go @@ -523,9 +523,12 @@ func (b *GRPCBroker) muxDial(id uint32) func(string, time.Duration) (net.Conn, e } // Dial opens a connection by ID. -func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { +func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { return b.DialWithOptions(id) } + +// Dial opens a connection by ID with options. +func (b *GRPCBroker) DialWithOptions(id uint32, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) { if b.muxer.Enabled() { - return dialGRPCConn(b.tls, b.muxDial(id)) + return dialGRPCConn(b.tls, b.muxDial(id), opts...) } var c *plugin.ConnInfo @@ -560,7 +563,7 @@ func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { return nil, err } - return dialGRPCConn(b.tls, netAddrDialer(addr)) + return dialGRPCConn(b.tls, netAddrDialer(addr), opts...) } // NextId returns a unique ID to use next. diff --git a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go index dce1a86a88..984c875db9 100644 --- a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go +++ b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go @@ -28,7 +28,6 @@ func ReattachFunc(pid int, addr net.Addr) runner.ReattachFunc { // doesn't actually return an error if it can't find the process. conn, err := net.Dial(addr.Network(), addr.String()) if err != nil { - p.Kill() return nil, ErrProcessNotFound } conn.Close() diff --git a/vendor/github.com/hashicorp/go-plugin/testing.go b/vendor/github.com/hashicorp/go-plugin/testing.go index a8735dfc8c..1abd402a35 100644 --- a/vendor/github.com/hashicorp/go-plugin/testing.go +++ b/vendor/github.com/hashicorp/go-plugin/testing.go @@ -9,10 +9,10 @@ import ( "io" "net" "net/rpc" + "testing" hclog "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-plugin/internal/grpcmux" - "github.com/mitchellh/go-testing-interface" "google.golang.org/grpc" ) @@ -33,7 +33,7 @@ type TestOptions struct { // TestConn is a helper function for returning a client and server // net.Conn connected to each other. -func TestConn(t testing.T) (net.Conn, net.Conn) { +func TestConn(t testing.TB) (net.Conn, net.Conn) { // Listen to any local port. This listener will be closed // after a single connection is established. l, err := net.Listen("tcp", "127.0.0.1:0") @@ -67,7 +67,7 @@ func TestConn(t testing.T) (net.Conn, net.Conn) { } // TestRPCConn returns a rpc client and server connected to each other. -func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) { +func TestRPCConn(t testing.TB) (*rpc.Client, *rpc.Server) { clientConn, serverConn := TestConn(t) server := rpc.NewServer() @@ -79,7 +79,7 @@ func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) { // TestPluginRPCConn returns a plugin RPC client and server that are connected // together and configured. -func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) { +func TestPluginRPCConn(t testing.TB, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) { // Create two net.Conns we can use to shuttle our control connection clientConn, serverConn := TestConn(t) @@ -107,7 +107,7 @@ func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*R // TestGRPCConn returns a gRPC client conn and grpc server that are connected // together and configured. The register function is used to register services // prior to the Serve call. This is used to test gRPC connections. -func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) { +func TestGRPCConn(t testing.TB, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) { // Create a listener l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { @@ -135,7 +135,7 @@ func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, * // TestPluginGRPCConn returns a plugin gRPC client and server that are connected // together and configured. This is used to test gRPC connections. -func TestPluginGRPCConn(t testing.T, multiplex bool, ps map[string]Plugin) (*GRPCClient, *GRPCServer) { +func TestPluginGRPCConn(t testing.TB, multiplex bool, ps map[string]Plugin) (*GRPCClient, *GRPCServer) { // Create a listener ln, err := serverListener(UnixSocketConfig{}) if err != nil { diff --git a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml b/vendor/github.com/mitchellh/go-testing-interface/.travis.yml deleted file mode 100644 index cca949103a..0000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go - -go: - - 1.x - - tip - -script: - - go test - -matrix: - allow_failures: - - go: tip diff --git a/vendor/github.com/mitchellh/go-testing-interface/LICENSE b/vendor/github.com/mitchellh/go-testing-interface/LICENSE deleted file mode 100644 index a3866a291f..0000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Mitchell Hashimoto - -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/mitchellh/go-testing-interface/README.md b/vendor/github.com/mitchellh/go-testing-interface/README.md deleted file mode 100644 index ee435adc54..0000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# go-testing-interface - -go-testing-interface is a Go library that exports an interface that -`*testing.T` implements as well as a runtime version you can use in its -place. - -The purpose of this library is so that you can export test helpers as a -public API without depending on the "testing" package, since you can't -create a `*testing.T` struct manually. This lets you, for example, use the -public testing APIs to generate mock data at runtime, rather than just at -test time. - -## Usage & Example - -For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/go-testing-interface). - -Given a test helper written using `go-testing-interface` like this: - - import "github.com/mitchellh/go-testing-interface" - - func TestHelper(t testing.T) { - t.Fatal("I failed") - } - -You can call the test helper in a real test easily: - - import "testing" - - func TestThing(t *testing.T) { - TestHelper(t) - } - -You can also call the test helper at runtime if needed: - - import "github.com/mitchellh/go-testing-interface" - - func main() { - TestHelper(&testing.RuntimeT{}) - } - -## Versioning - -The tagged version matches the version of Go that the interface is -compatible with. For example, the version "1.14.0" is for Go 1.14 and -introduced the `Cleanup` function. The patch version (the ".0" in the -prior example) is used to fix any bugs found in this library and has no -correlation to the supported Go version. - -## Why?! - -**Why would I call a test helper that takes a *testing.T at runtime?** - -You probably shouldn't. The only use case I've seen (and I've had) for this -is to implement a "dev mode" for a service where the test helpers are used -to populate mock data, create a mock DB, perhaps run service dependencies -in-memory, etc. - -Outside of a "dev mode", I've never seen a use case for this and I think -there shouldn't be one since the point of the `testing.T` interface is that -you can fail immediately. diff --git a/vendor/github.com/mitchellh/go-testing-interface/testing.go b/vendor/github.com/mitchellh/go-testing-interface/testing.go deleted file mode 100644 index 86510322ab..0000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/testing.go +++ /dev/null @@ -1,112 +0,0 @@ -package testing - -import ( - "fmt" - "log" -) - -// T is the interface that mimics the standard library *testing.T. -// -// In unit tests you can just pass a *testing.T struct. At runtime, outside -// of tests, you can pass in a RuntimeT struct from this package. -type T interface { - Cleanup(func()) - Error(args ...interface{}) - Errorf(format string, args ...interface{}) - Fail() - FailNow() - Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) - Helper() - Log(args ...interface{}) - Logf(format string, args ...interface{}) - Name() string - Parallel() - Skip(args ...interface{}) - SkipNow() - Skipf(format string, args ...interface{}) - Skipped() bool -} - -// RuntimeT implements T and can be instantiated and run at runtime to -// mimic *testing.T behavior. Unlike *testing.T, this will simply panic -// for calls to Fatal. For calls to Error, you'll have to check the errors -// list to determine whether to exit yourself. -// -// Cleanup does NOT work, so if you're using a helper that uses Cleanup, -// there may be dangling resources. -// -// Parallel does not do anything. -type RuntimeT struct { - skipped bool - failed bool -} - -func (t *RuntimeT) Error(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) - t.Fail() -} - -func (t *RuntimeT) Errorf(format string, args ...interface{}) { - log.Printf(format, args...) - t.Fail() -} - -func (t *RuntimeT) Fail() { - t.failed = true -} - -func (t *RuntimeT) FailNow() { - panic("testing.T failed, see logs for output (if any)") -} - -func (t *RuntimeT) Failed() bool { - return t.failed -} - -func (t *RuntimeT) Fatal(args ...interface{}) { - log.Print(args...) - t.FailNow() -} - -func (t *RuntimeT) Fatalf(format string, args ...interface{}) { - log.Printf(format, args...) - t.FailNow() -} - -func (t *RuntimeT) Log(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) -} - -func (t *RuntimeT) Logf(format string, args ...interface{}) { - log.Println(fmt.Sprintf(format, args...)) -} - -func (t *RuntimeT) Name() string { - return "" -} - -func (t *RuntimeT) Parallel() {} - -func (t *RuntimeT) Skip(args ...interface{}) { - log.Print(args...) - t.SkipNow() -} - -func (t *RuntimeT) SkipNow() { - t.skipped = true -} - -func (t *RuntimeT) Skipf(format string, args ...interface{}) { - log.Printf(format, args...) - t.SkipNow() -} - -func (t *RuntimeT) Skipped() bool { - return t.skipped -} - -func (t *RuntimeT) Helper() {} - -func (t *RuntimeT) Cleanup(func()) {} 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 index ab9c8d3cd9..ed3a5f639d 100644 --- a/vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/body_reader.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "strings" + "sync" "sync/atomic" "time" ) @@ -28,8 +29,11 @@ type bodyReader struct { bytesCounter int64 ctx *httpContext reader io.ReadCloser - err error onReadDone func() + + // lock protects concurrent access to err. + lock sync.RWMutex + err error } func newBodyReader(c *httpContext, maxSize int64) *bodyReader { @@ -41,7 +45,10 @@ func newBodyReader(c *httpContext, maxSize int64) *bodyReader { } func (r *bodyReader) Read(b []byte) (int, error) { - if r.err != nil { + r.lock.RLock() + hasErrored := r.err != nil + r.lock.RUnlock() + if hasErrored { return 0, io.EOF } @@ -99,20 +106,26 @@ func (r *bodyReader) Read(b []byte) (int, error) { // 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. + r.lock.Lock() if r.err == nil { r.err = err } + r.lock.Unlock() } return n, nil } -func (r bodyReader) hasError() error { - if r.err == io.EOF { +func (r *bodyReader) hasError() error { + r.lock.RLock() + err := r.err + r.lock.RUnlock() + + if err == io.EOF { return nil } - return r.err + return err } func (r *bodyReader) bytesRead() int64 { @@ -120,7 +133,9 @@ func (r *bodyReader) bytesRead() int64 { } func (r *bodyReader) closeWithError(err error) { + r.lock.Lock() r.err = err + r.lock.Unlock() // SetReadDeadline with the current time causes concurrent reads to the body to time out, // so the body will be closed sooner with less delay. 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 index 44cd7c2ca3..be46735472 100644 --- a/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go +++ b/vendor/github.com/tus/tusd/v2/pkg/handler/unrouted_handler.go @@ -28,6 +28,7 @@ const ( interopVersion3 draftVersion = "3" // From draft version -01 interopVersion4 draftVersion = "4" // From draft version -02 interopVersion5 draftVersion = "5" // From draft version -03 + interopVersion6 draftVersion = "6" // From draft version -04 and -05 ) var ( @@ -235,8 +236,16 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler { // Set appropriated headers in case of OPTIONS method allowing protocol // discovery and end with an 204 No Content if r.Method == "OPTIONS" { + ietfDraftLimits := "min-size=0" + if handler.config.MaxSize > 0 { - header.Set("Tus-Max-Size", strconv.FormatInt(handler.config.MaxSize, 10)) + maxSizeStr := strconv.FormatInt(handler.config.MaxSize, 10) + header.Set("Tus-Max-Size", maxSizeStr) + ietfDraftLimits += ",max-size=" + maxSizeStr + } + + if handler.usesIETFDraft(r) { + header.Set("Upload-Limit", ietfDraftLimits) } header.Set("Tus-Version", "1.0.0") @@ -462,9 +471,15 @@ func (handler *UnroutedHandler) PostFileV2(w http.ResponseWriter, r *http.Reques 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 + + size, sizeIsDeferred, err := getIETFDraftUploadLength(r) + if err != nil { + handler.sendError(c, err) + return + } + + if !sizeIsDeferred { + info.Size = size } else { // Error out if the storage does not support upload length deferring, but we need it. if !handler.composer.UsesLengthDeferrer { @@ -545,11 +560,14 @@ func (handler *UnroutedHandler) PostFileV2(w http.ResponseWriter, r *http.Reques id := info.ID url := handler.absFileURL(r, id) + limits := handler.getIETFDraftUploadLimits(info) resp.Header["Location"] = url + resp.Header["Upload-Limit"] = limits // Send 104 response w.Header().Set("Location", url) w.Header().Set("Upload-Draft-Interop-Version", string(currentUploadDraftInteropVersion)) + w.Header().Set("Upload-Limit", limits) w.WriteHeader(104) handler.Metrics.incUploadsCreated() @@ -673,6 +691,8 @@ func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) resp.Header["Upload-Defer-Length"] = UploadLengthDeferred } else { resp.Header["Upload-Length"] = strconv.FormatInt(info.Size, 10) + // TODO: Shouldn't this rather be offset? Basically, whatever GET would return. + // But this then also depends on the storage backend if that's even supported. resp.Header["Content-Length"] = strconv.FormatInt(info.Size, 10) } @@ -682,6 +702,12 @@ func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) setIETFDraftUploadComplete(r, resp, isUploadCompleteNow) resp.Header["Upload-Draft-Interop-Version"] = string(getIETFDraftInteropVersion(r)) + if !info.SizeIsDeferred { + resp.Header["Upload-Length"] = strconv.FormatInt(info.Size, 10) + } + + resp.Header["Upload-Limit"] = handler.getIETFDraftUploadLimits(info) + // 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 @@ -697,12 +723,20 @@ func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request isTusV1 := !handler.usesIETFDraft(r) - // Check for presence of application/offset+octet-stream + // Check for presence of application/offset+octet-stream (tus v1) or application/partial-upload (IETF draft since -04) if isTusV1 && r.Header.Get("Content-Type") != "application/offset+octet-stream" { handler.sendError(c, ErrInvalidContentType) return } + if !isTusV1 { + currentInteropVersion := getIETFDraftInteropVersion(r) + if currentInteropVersion != interopVersion3 && currentInteropVersion != interopVersion4 && currentInteropVersion != interopVersion5 && r.Header.Get("Content-Type") != "application/partial-upload" { + 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 { @@ -1185,8 +1219,9 @@ func (handler *UnroutedHandler) terminateUpload(c *httpContext, upload Upload, i func (handler *UnroutedHandler) sendError(c *httpContext, err error) { r := c.req - detailedErr, ok := err.(Error) - if !ok { + var detailedErr Error + + if !errors.As(err, &detailedErr) { c.log.Error("InternalServerError", "message", err.Error()) detailedErr = NewError("ERR_INTERNAL_SERVER_ERROR", err.Error(), http.StatusInternalServerError) } @@ -1376,11 +1411,24 @@ func (handler UnroutedHandler) usesIETFDraft(r *http.Request) bool { return handler.config.EnableExperimentalProtocol && interopVersionHeader != "" } +// getIETFDraftUploadLimits returns the Upload-Limit header for a given upload +// according to the set resumable upload draft version from IETF. +func (handler UnroutedHandler) getIETFDraftUploadLimits(info FileInfo) string { + limits := "min-size=0" + if handler.config.MaxSize > 0 { + limits += ",max-size=" + strconv.FormatInt(handler.config.MaxSize, 10) + } else if !info.SizeIsDeferred { + limits += ",max-size=" + strconv.FormatInt(info.Size, 10) + } + + return limits +} + // 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: + case interopVersion3, interopVersion4, interopVersion5, interopVersion6: return version default: return "" @@ -1392,7 +1440,7 @@ func getIETFDraftInteropVersion(r *http.Request) draftVersion { func isIETFDraftUploadComplete(r *http.Request) bool { currentUploadDraftInteropVersion := getIETFDraftInteropVersion(r) switch currentUploadDraftInteropVersion { - case interopVersion4, interopVersion5: + case interopVersion4, interopVersion5, interopVersion6: return r.Header.Get("Upload-Complete") == "?1" case interopVersion3: return r.Header.Get("Upload-Incomplete") == "?0" @@ -1413,7 +1461,7 @@ func setIETFDraftUploadComplete(r *http.Request, resp HTTPResponse, isComplete b } else { resp.Header["Upload-Incomplete"] = "?1" } - case interopVersion4, interopVersion5: + case interopVersion4, interopVersion5, interopVersion6: if isComplete { resp.Header["Upload-Complete"] = "?1" } else { @@ -1422,6 +1470,49 @@ func setIETFDraftUploadComplete(r *http.Request, resp HTTPResponse, isComplete b } } +// getIETFDraftUploadLength returns the length of an upload as defined in the +// resumable upload draft from IETF. This can either be in the Upload-Length +// header or in the Content-Length header. +func getIETFDraftUploadLength(r *http.Request) (length int64, lengthIsDeferred bool, err error) { + var lengthFromUploadLength int64 + hasLengthFromUploadLength := false + var lengthFromContentLength int64 + hasLengthFromContentLength := false + + willCompleteUpload := isIETFDraftUploadComplete(r) + if willCompleteUpload && r.ContentLength != -1 { + lengthFromContentLength = r.ContentLength + hasLengthFromContentLength = true + } + + uploadLengthStr := r.Header.Get("Upload-Length") + if uploadLengthStr != "" { + var err error + lengthFromUploadLength, err = strconv.ParseInt(uploadLengthStr, 10, 64) + if err != nil { + return 0, false, ErrInvalidUploadLength + } + + hasLengthFromUploadLength = true + } + + // If both lengths are set, they must match + if hasLengthFromContentLength && hasLengthFromUploadLength && lengthFromUploadLength != lengthFromContentLength { + return 0, false, ErrInvalidUploadLength + } + + // Return whichever length is set + if hasLengthFromUploadLength { + return lengthFromUploadLength, false, nil + } + if hasLengthFromContentLength { + return lengthFromContentLength, false, nil + } + + // No length set, so it's deferred + return 0, true, nil +} + // ParseMetadataHeader parses the Upload-Metadata header as defined in the // File Creation extension. // e.g. Upload-Metadata: name bHVucmpzLnBuZw==,type aW1hZ2UvcG5n diff --git a/vendor/modules.txt b/vendor/modules.txt index 05b1c5aa01..14322a7d42 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1168,7 +1168,7 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities # github.com/hashicorp/go-hclog v1.6.3 ## explicit; go 1.13 github.com/hashicorp/go-hclog -# github.com/hashicorp/go-plugin v1.6.1 +# github.com/hashicorp/go-plugin v1.6.2 ## explicit; go 1.17 github.com/hashicorp/go-plugin github.com/hashicorp/go-plugin/internal/cmdrunner @@ -1355,9 +1355,6 @@ github.com/minio/minio-go/v7/pkg/tags # github.com/mitchellh/copystructure v1.2.0 ## explicit; go 1.15 github.com/mitchellh/copystructure -# github.com/mitchellh/go-testing-interface v1.14.1 -## explicit; go 1.14 -github.com/mitchellh/go-testing-interface # github.com/mitchellh/mapstructure v1.5.0 ## explicit; go 1.14 github.com/mitchellh/mapstructure @@ -1849,8 +1846,8 @@ 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/v2 v2.5.0 -## explicit; go 1.20 +# github.com/tus/tusd/v2 v2.6.0 +## explicit; go 1.21.0 github.com/tus/tusd/v2/pkg/handler # github.com/unrolled/secure v1.16.0 => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c ## explicit; go 1.13