diff --git a/.gitignore b/.gitignore index 8294f8c1..c6b2ccdd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ tusd_*_* __pycache__/ examples/hooks/plugin/hook_handler .idea/ +.vscode/ \ No newline at end of file diff --git a/cmd/tusd/cli/flags.go b/cmd/tusd/cli/flags.go index 33e00db5..f77638d4 100644 --- a/cmd/tusd/cli/flags.go +++ b/cmd/tusd/cli/flags.go @@ -15,6 +15,7 @@ var Flags struct { HttpHost string HttpPort string HttpSock string + EnableH2C bool MaxSize int64 UploadDir string Basepath string @@ -87,6 +88,7 @@ func ParseFlags() { f.StringVar(&Flags.HttpSock, "unix-sock", "", "If set, will listen to a UNIX socket at this location instead of a TCP socket") f.StringVar(&Flags.Basepath, "base-path", "/files/", "Basepath of the HTTP server") f.BoolVar(&Flags.BehindProxy, "behind-proxy", false, "Respect X-Forwarded-* and similar headers which may be set by proxies") + f.BoolVar(&Flags.EnableH2C, "enable-h2c", false, "Allow for HTTP/2 cleartext (h2c) connections (non-encrypted)") }) fs.AddGroup("TLS options", func(f *flag.FlagSet) { diff --git a/cmd/tusd/cli/serve.go b/cmd/tusd/cli/serve.go index 0ea987e1..a647888d 100644 --- a/cmd/tusd/cli/serve.go +++ b/cmd/tusd/cli/serve.go @@ -15,6 +15,9 @@ import ( tushandler "github.com/tus/tusd/v2/pkg/handler" "github.com/tus/tusd/v2/pkg/hooks" "github.com/tus/tusd/v2/pkg/hooks/plugin" + + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" ) const ( @@ -160,6 +163,13 @@ func Serve() { if protocol == "http" { // Non-TLS mode + if Flags.EnableH2C { + // Wrap in h2c for optional HTTP/2 support in clear text mode (without TLS) + // See https://pkg.go.dev/golang.org/x/net/http2/h2c#NewHandler + h2s := &http2.Server{} + newHandler := h2c.NewHandler(mux, h2s) + server.Handler = newHandler + } err = server.Serve(listener) } else { // TLS mode diff --git a/docs/_getting-started/configuration.md b/docs/_getting-started/configuration.md index f1b8033e..bb76150f 100644 --- a/docs/_getting-started/configuration.md +++ b/docs/_getting-started/configuration.md @@ -22,7 +22,7 @@ By default, tusd listens on port 8080 and all available interfaces. This can be $ tusd -host 127.0.0.1 -port 1337 ``` -Once running, tusd accepts HTTP/1.1 requests on the configured port. If [HTTPS/TLS](#httpstls) is configured, tusd will also accept HTTP/2 connection, thanks to [Go's transparent support](https://pkg.go.dev/net/http#hdr-HTTP_2). HTTP/3 and QUIC is currently not supported by tusd directly and requires the use of a reverse proxy. +Once running, tusd accepts HTTP requests on the configured port. ### UNIX socket @@ -126,6 +126,14 @@ Alternatively, you can completely disable any CORS-related logic in tusd and han $ tusd -disable-cors ``` +## HTTP/2 + +By default, tusd only accepts HTTP/1.1 requests on the configured port. + +If [HTTPS/TLS](#httpstls) is configured, tusd will also accept an encrypted HTTP/2 connection without any additional configuration, thanks to [Go's transparent support](https://pkg.go.dev/net/http#hdr-HTTP_2). + +Alternatively, if HTTPS/TLS is not enabled, support for HTTP/2 cleartext mode (h2c) can be activated using the `-enable-h2c` flag, where tusd also accepts unencrypted HTTP/2 requests. This is useful if a reverse proxy should connect to tusd over HTTP/2 (e.g. in GCP Cloud Run). Be aware that the first request on an upgraded connection (without prior knowledge) is [read fully into memory](https://pkg.go.dev/golang.org/x/net/http2/h2c#NewHandler). To avoid excessive memory usage from PATCH requests, it's recommended to only connect with prior knowledge about tusd's HTTP/2 support. + ## HTTPS/TLS If you want tusd to be accessible via HTTPS, there are two options: diff --git a/go.mod b/go.mod index e79bf401..0a6a8597 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/tus/lockfile v1.2.0 github.com/vimeo/go-util v1.4.1 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df + golang.org/x/net v0.26.0 google.golang.org/api v0.195.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2