diff options
author | 2023-11-13 19:48:51 +0100 | |
---|---|---|
committer | 2023-11-13 19:48:51 +0100 | |
commit | 8d0c017cf205bcf57630c91b53079001deed4d36 (patch) | |
tree | cf2240e3dff137df2871c9b93548a885833e9a52 /internal/api/util/errorhandling.go | |
parent | [chore] update otel -> v1.20.0 (#2358) (diff) | |
download | gotosocial-8d0c017cf205bcf57630c91b53079001deed4d36.tar.xz |
[feature/performance] Wrap incoming HTTP requests in timeout handler (#2353)
* deinterface router, start messing about with deadlines
* weeeee
* thanks linter (thinter)
* write Connection: close when timing out requests
* update wording
* don't replace req
* don't bother with fancy Cause functions (I'll use them one day...)
Diffstat (limited to 'internal/api/util/errorhandling.go')
-rw-r--r-- | internal/api/util/errorhandling.go | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/internal/api/util/errorhandling.go b/internal/api/util/errorhandling.go index 33f501474..4fa544ffd 100644 --- a/internal/api/util/errorhandling.go +++ b/internal/api/util/errorhandling.go @@ -19,6 +19,7 @@ package util import ( "context" + "errors" "net/http" "codeberg.org/gruf/go-kv" @@ -90,19 +91,40 @@ func genericErrorHandler(c *gin.Context, instanceGet func(ctx context.Context) ( // try to serve an appropriate application/json content-type error. // To override the default response type, specify `offers`. // -// If the requester already hung up on the request, ErrorHandler -// will overwrite the given errWithCode with a 499 error to indicate -// that the failure wasn't due to something we did, and will avoid -// trying to write extensive bytes to the caller by just aborting. +// If the requester already hung up on the request, or the server +// timed out a very slow request, ErrorHandler will overwrite the +// given errWithCode with a 408 or 499 error to indicate that the +// failure wasn't due to something we did, and will avoid trying +// to write extensive bytes to the caller by just aborting. // -// See: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#nginx. -func ErrorHandler(c *gin.Context, errWithCode gtserror.WithCode, instanceGet func(ctx context.Context) (*apimodel.InstanceV1, gtserror.WithCode), offers ...MIME) { - if c.Request.Context().Err() != nil { - // Context error means requester probably left already. - // Wrap original error with a less alarming one. Then - // we can return early, because it doesn't matter what - // we send to the client at this point; they're gone. - errWithCode = gtserror.NewErrorClientClosedRequest(errWithCode.Unwrap()) +// For 499, see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#nginx. +func ErrorHandler( + c *gin.Context, + errWithCode gtserror.WithCode, + instanceGet func(ctx context.Context) (*apimodel.InstanceV1, gtserror.WithCode), + offers ...MIME, +) { + if ctxErr := c.Request.Context().Err(); ctxErr != nil { + // Context error means either client has left already, + // or server has timed out a very slow request. + // + // Rewrap the error with something less scary, + // and just abort the request gracelessly. + err := errWithCode.Unwrap() + + if errors.Is(ctxErr, context.DeadlineExceeded) { + // We timed out the request. + errWithCode = gtserror.NewErrorRequestTimeout(err) + + // Be correct and write "close". + // See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#close + // and: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408 + c.Header("Connection", "close") + } else { + // Client timed out the request. + errWithCode = gtserror.NewErrorClientClosedRequest(err) + } + c.AbortWithStatus(errWithCode.Code()) return } |