From 3fcd69f1f81c1213f24c8b26b90d2d6dd807ce77 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 24 Jan 2023 11:00:54 +0100 Subject: [PATCH] drain body when put failed Signed-off-by: jkoberg --- changelog/unreleased/drain-body-on-put.md | 5 ++ pkg/rhttp/datatx/manager/spaces/spaces.go | 67 +++++++++++++---------- 2 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 changelog/unreleased/drain-body-on-put.md diff --git a/changelog/unreleased/drain-body-on-put.md b/changelog/unreleased/drain-body-on-put.md new file mode 100644 index 00000000000..20474569960 --- /dev/null +++ b/changelog/unreleased/drain-body-on-put.md @@ -0,0 +1,5 @@ +Bugfix: Drain body on failed put + +When a put request fails the server would not drain the body. This will lead to `connection closed` errors on clients when using http 1 + +https://github.com/cs3org/reva/pull/3618 diff --git a/pkg/rhttp/datatx/manager/spaces/spaces.go b/pkg/rhttp/datatx/manager/spaces/spaces.go index b4ec4bddeff..20ae61c7401 100644 --- a/pkg/rhttp/datatx/manager/spaces/spaces.go +++ b/pkg/rhttp/datatx/manager/spaces/spaces.go @@ -19,6 +19,8 @@ package spaces import ( + "io" + "io/ioutil" "net/http" "path" "strings" @@ -113,38 +115,45 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { sublog.Error().Err(err).Msg("failed to publish FileUploaded event") } }) - switch v := err.(type) { - case nil: - // set etag, mtime and file id - w.Header().Set(net.HeaderETag, info.Etag) - w.Header().Set(net.HeaderOCETag, info.Etag) - if info.Id != nil { - w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) + if err != nil { + if r.ProtoMajor == 1 { + // drain body to avoid `connection closed` errors + _, _ = io.Copy(ioutil.Discard, r.Body) } - if info.Mtime != nil { - t := utils.TSToTime(info.Mtime).UTC() - lastModifiedString := t.Format(time.RFC1123Z) - w.Header().Set(net.HeaderLastModified, lastModifiedString) + + switch v := err.(type) { + case errtypes.PartialContent: + w.WriteHeader(http.StatusPartialContent) + case errtypes.ChecksumMismatch: + w.WriteHeader(errtypes.StatusChecksumMismatch) + case errtypes.NotFound: + w.WriteHeader(http.StatusNotFound) + case errtypes.PermissionDenied: + w.WriteHeader(http.StatusForbidden) + case errtypes.InvalidCredentials: + w.WriteHeader(http.StatusUnauthorized) + case errtypes.InsufficientStorage: + w.WriteHeader(http.StatusInsufficientStorage) + case errtypes.PreconditionFailed, errtypes.Aborted: + w.WriteHeader(http.StatusPreconditionFailed) + default: + sublog.Error().Err(v).Msg("error uploading file") + w.WriteHeader(http.StatusInternalServerError) } - w.WriteHeader(http.StatusOK) - case errtypes.PartialContent: - w.WriteHeader(http.StatusPartialContent) - case errtypes.ChecksumMismatch: - w.WriteHeader(errtypes.StatusChecksumMismatch) - case errtypes.NotFound: - w.WriteHeader(http.StatusNotFound) - case errtypes.PermissionDenied: - w.WriteHeader(http.StatusForbidden) - case errtypes.InvalidCredentials: - w.WriteHeader(http.StatusUnauthorized) - case errtypes.InsufficientStorage: - w.WriteHeader(http.StatusInsufficientStorage) - case errtypes.PreconditionFailed, errtypes.Aborted: - w.WriteHeader(http.StatusPreconditionFailed) - default: - sublog.Error().Err(v).Msg("error uploading file") - w.WriteHeader(http.StatusInternalServerError) + return + } + // set etag, mtime and file id + w.Header().Set(net.HeaderETag, info.Etag) + w.Header().Set(net.HeaderOCETag, info.Etag) + if info.Id != nil { + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) + } + if info.Mtime != nil { + t := utils.TSToTime(info.Mtime).UTC() + lastModifiedString := t.Format(time.RFC1123Z) + w.Header().Set(net.HeaderLastModified, lastModifiedString) } + w.WriteHeader(http.StatusOK) return default: w.WriteHeader(http.StatusNotImplemented)