From f536dacd4db60a37917fcbadf9a4b4ca67065e97 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Thu, 10 Oct 2024 10:22:25 +0200 Subject: [PATCH] fix(webdav): Set Retry-After header for 429 responses We're now setting a 'Retry-After' in the webdav response when the thunbnailer is rate limiting the requests. For now the timeout is just a random number between 1 and 15 seconds. --- changelog/unreleased/fix-thumbnail-ratelimit.md | 3 +++ services/webdav/pkg/service/v0/service.go | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/changelog/unreleased/fix-thumbnail-ratelimit.md b/changelog/unreleased/fix-thumbnail-ratelimit.md index 8468223612..0fb94e3392 100644 --- a/changelog/unreleased/fix-thumbnail-ratelimit.md +++ b/changelog/unreleased/fix-thumbnail-ratelimit.md @@ -3,5 +3,8 @@ Bugfix: Thumbnail request limit The `THUMBNAILS_MAX_CONCURRENT_REQUESTS` setting was not working correctly. Previously it was just limiting the number of concurrent thumbnail downloads. Now the limit is applied to the number thumbnail generations requests. +Additionally the webdav service is now returning a "Retry-After" header when +it is hitting the ratelimit of the thumbnail service. +https://github.com/owncloud/ocis/pull/10280 https://github.com/owncloud/ocis/pull/10225 diff --git a/services/webdav/pkg/service/v0/service.go b/services/webdav/pkg/service/v0/service.go index 8089a11057..216e9a37ce 100644 --- a/services/webdav/pkg/service/v0/service.go +++ b/services/webdav/pkg/service/v0/service.go @@ -4,10 +4,12 @@ import ( "context" "encoding/xml" "io" + "math/rand/v2" "net/http" "net/url" "path" "path/filepath" + "strconv" "strings" gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" @@ -259,6 +261,7 @@ func (g Webdav) SpacesThumbnail(w http.ResponseWriter, r *http.Request) { renderError(w, r, errTooEarly(e.Detail)) return case http.StatusTooManyRequests: + addRetryAfterHeader(w) renderError(w, r, errTooManyRequests(e.Detail)) case http.StatusBadRequest: renderError(w, r, errBadRequest(e.Detail)) @@ -356,6 +359,7 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) { renderError(w, r, errTooEarly(e.Detail)) return case http.StatusTooManyRequests: + addRetryAfterHeader(w) renderError(w, r, errTooManyRequests(e.Detail)) case http.StatusBadRequest: renderError(w, r, errBadRequest(e.Detail)) @@ -404,6 +408,7 @@ func (g Webdav) PublicThumbnail(w http.ResponseWriter, r *http.Request) { case http.StatusBadRequest: renderError(w, r, errBadRequest(e.Detail)) case http.StatusTooManyRequests: + addRetryAfterHeader(w) renderError(w, r, errTooManyRequests(e.Detail)) default: renderError(w, r, errInternalError(err.Error())) @@ -448,6 +453,7 @@ func (g Webdav) PublicThumbnailHead(w http.ResponseWriter, r *http.Request) { case http.StatusBadRequest: renderError(w, r, errBadRequest(e.Detail)) case http.StatusTooManyRequests: + addRetryAfterHeader(w) renderError(w, r, errTooManyRequests(e.Detail)) default: renderError(w, r, errInternalError(err.Error())) @@ -566,3 +572,8 @@ func renderError(w http.ResponseWriter, r *http.Request, err *errResponse) { func notFoundMsg(name string) string { return "File with name " + name + " could not be located" } + +func addRetryAfterHeader(w http.ResponseWriter) { + after := rand.IntN(14) + 1 + w.Header().Set("Retry-After", strconv.Itoa(after)) +}