diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 067841f..5808311 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -35,7 +35,9 @@ func NewHandler(config Config) (*Handler, error) { mux := pat.New() - routedHandler.Handler = handler.Middleware(mux) + disconnectedHandler := handler.DisconnectMiddleware(mux) + + routedHandler.Handler = handler.Middleware(disconnectedHandler) mux.Post("", http.HandlerFunc(handler.PostFile)) mux.Head(":id", http.HandlerFunc(handler.HeadFile)) diff --git a/pkg/handler/unrouted_handler.go b/pkg/handler/unrouted_handler.go index c8db15e..020fa96 100644 --- a/pkg/handler/unrouted_handler.go +++ b/pkg/handler/unrouted_handler.go @@ -271,10 +271,21 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler { }) } +// DisconnectMiddleware does a deep clone of the request with an empty context so tusd +// can continue to finish the file upload, even if the request aborts +func (handler *UnroutedHandler) DisconnectMiddleware(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // disconnect the existing context to ignore cancels + r.Clone(context.Background()) + // 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) { - ctx := context.Background() + ctx := r.Context() // 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 @@ -414,7 +425,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) // HeadFile returns the length and offset for the HEAD request func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() + ctx := r.Context() id, err := extractIDFromPath(r.URL.Path) if err != nil { @@ -478,7 +489,7 @@ func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) // 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() + ctx := r.Context() // Check for presence of application/offset+octet-stream if r.Header.Get("Content-Type") != "application/offset+octet-stream" { @@ -693,7 +704,7 @@ func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, uplo // 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() + ctx := r.Context() id, err := extractIDFromPath(r.URL.Path) if err != nil { @@ -814,7 +825,7 @@ func filterContentType(info FileInfo) (contentType string, contentDisposition st // DelFile terminates an upload permanently. func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request) { - ctx := context.Background() + ctx := r.Context() // Abort the request handling if the required interface is not implemented if !handler.composer.UsesTerminater {