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] <support@github.com>
This commit is contained in:
dependabot[bot]
2024-11-29 06:12:32 +00:00
committed by Ralf Haferkamp
parent 293aff1b53
commit 6782c2473d
14 changed files with 154 additions and 247 deletions

5
go.mod
View File

@@ -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

10
go.sum
View File

@@ -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=

View File

@@ -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:

View File

@@ -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.
//

View File

@@ -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.

View File

@@ -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()

View File

@@ -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 {

View File

@@ -1,12 +0,0 @@
language: go
go:
- 1.x
- tip
script:
- go test
matrix:
allow_failures:
- go: tip

View File

@@ -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.

View File

@@ -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.

View File

@@ -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()) {}

View File

@@ -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.

View File

@@ -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

9
vendor/modules.txt vendored
View File

@@ -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