summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2023-11-13 19:48:51 +0100
committerLibravatar GitHub <noreply@github.com>2023-11-13 19:48:51 +0100
commit8d0c017cf205bcf57630c91b53079001deed4d36 (patch)
treecf2240e3dff137df2871c9b93548a885833e9a52 /internal/api
parent[chore] update otel -> v1.20.0 (#2358) (diff)
downloadgotosocial-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')
-rw-r--r--internal/api/activitypub.go4
-rw-r--r--internal/api/auth.go2
-rw-r--r--internal/api/client.go2
-rw-r--r--internal/api/fileserver.go2
-rw-r--r--internal/api/nodeinfo.go2
-rw-r--r--internal/api/util/errorhandling.go46
-rw-r--r--internal/api/wellknown.go2
7 files changed, 41 insertions, 19 deletions
diff --git a/internal/api/activitypub.go b/internal/api/activitypub.go
index 02ae0767c..0c0222d1c 100644
--- a/internal/api/activitypub.go
+++ b/internal/api/activitypub.go
@@ -35,7 +35,7 @@ type ActivityPub struct {
signatureCheckMiddleware gin.HandlerFunc
}
-func (a *ActivityPub) Route(r router.Router, m ...gin.HandlerFunc) {
+func (a *ActivityPub) Route(r *router.Router, m ...gin.HandlerFunc) {
// create groupings for the 'emoji' and 'users' prefixes
emojiGroup := r.AttachGroup("emoji")
usersGroup := r.AttachGroup("users")
@@ -54,7 +54,7 @@ func (a *ActivityPub) Route(r router.Router, m ...gin.HandlerFunc) {
}
// Public key endpoint requires different middleware + cache policies from other AP endpoints.
-func (a *ActivityPub) RoutePublicKey(r router.Router, m ...gin.HandlerFunc) {
+func (a *ActivityPub) RoutePublicKey(r *router.Router, m ...gin.HandlerFunc) {
// Create grouping for the 'users/[username]/main-key' prefix.
publicKeyGroup := r.AttachGroup(publickey.PublicKeyPath)
diff --git a/internal/api/auth.go b/internal/api/auth.go
index 961caa981..8d7808a3a 100644
--- a/internal/api/auth.go
+++ b/internal/api/auth.go
@@ -36,7 +36,7 @@ type Auth struct {
}
// Route attaches 'auth' and 'oauth' groups to the given router.
-func (a *Auth) Route(r router.Router, m ...gin.HandlerFunc) {
+func (a *Auth) Route(r *router.Router, m ...gin.HandlerFunc) {
// create groupings for the 'auth' and 'oauth' prefixes
authGroup := r.AttachGroup("auth")
oauthGroup := r.AttachGroup("oauth")
diff --git a/internal/api/client.go b/internal/api/client.go
index ec8fa6034..1112efa31 100644
--- a/internal/api/client.go
+++ b/internal/api/client.go
@@ -79,7 +79,7 @@ type Client struct {
user *user.Module // api/v1/user
}
-func (c *Client) Route(r router.Router, m ...gin.HandlerFunc) {
+func (c *Client) Route(r *router.Router, m ...gin.HandlerFunc) {
// create a new group on the top level client 'api' prefix
apiGroup := r.AttachGroup("api")
diff --git a/internal/api/fileserver.go b/internal/api/fileserver.go
index 8f1e60b82..59f38c362 100644
--- a/internal/api/fileserver.go
+++ b/internal/api/fileserver.go
@@ -30,7 +30,7 @@ type Fileserver struct {
fileserver *fileserver.Module
}
-func (f *Fileserver) Route(r router.Router, m ...gin.HandlerFunc) {
+func (f *Fileserver) Route(r *router.Router, m ...gin.HandlerFunc) {
fileserverGroup := r.AttachGroup("fileserver")
// Attach middlewares appropriate for this group.
diff --git a/internal/api/nodeinfo.go b/internal/api/nodeinfo.go
index 22d314033..fb7918edc 100644
--- a/internal/api/nodeinfo.go
+++ b/internal/api/nodeinfo.go
@@ -29,7 +29,7 @@ type NodeInfo struct {
nodeInfo *nodeinfo.Module
}
-func (w *NodeInfo) Route(r router.Router, m ...gin.HandlerFunc) {
+func (w *NodeInfo) Route(r *router.Router, m ...gin.HandlerFunc) {
// group nodeinfo endpoints together
nodeInfoGroup := r.AttachGroup("nodeinfo")
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
}
diff --git a/internal/api/wellknown.go b/internal/api/wellknown.go
index 63ca48ef7..90e18d637 100644
--- a/internal/api/wellknown.go
+++ b/internal/api/wellknown.go
@@ -33,7 +33,7 @@ type WellKnown struct {
hostMeta *hostmeta.Module
}
-func (w *WellKnown) Route(r router.Router, m ...gin.HandlerFunc) {
+func (w *WellKnown) Route(r *router.Router, m ...gin.HandlerFunc) {
// group .well-known endpoints together
wellKnownGroup := r.AttachGroup(".well-known")