summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2023-11-27 14:00:57 +0000
committerLibravatar GitHub <noreply@github.com>2023-11-27 14:00:57 +0000
commit74700cc8034980334e7df466f313287a41d2b8a6 (patch)
tree63ab8912c813eefba8a492e0d0489f4e5fe59446
parent[chore]: Bump codeberg.org/gruf/go-mutexes from 1.3.0 to 1.3.1 (#2387) (diff)
downloadgotosocial-74700cc8034980334e7df466f313287a41d2b8a6.tar.xz
[performance] http response encoding / writing improvements (#2374)
-rw-r--r--internal/api/activitypub/emoji/emojiget.go18
-rw-r--r--internal/api/activitypub/publickey/publickeyget.go20
-rw-r--r--internal/api/activitypub/users/featured.go13
-rw-r--r--internal/api/activitypub/users/followers.go13
-rw-r--r--internal/api/activitypub/users/following.go13
-rw-r--r--internal/api/activitypub/users/inboxpost.go3
-rw-r--r--internal/api/activitypub/users/outboxget.go13
-rw-r--r--internal/api/activitypub/users/outboxget_test.go2
-rw-r--r--internal/api/activitypub/users/repliesget.go14
-rw-r--r--internal/api/activitypub/users/repliesget_test.go9
-rw-r--r--internal/api/activitypub/users/statusget.go13
-rw-r--r--internal/api/activitypub/users/userget.go13
-rw-r--r--internal/api/auth/token.go8
-rw-r--r--internal/api/client/accounts/accountcreate.go2
-rw-r--r--internal/api/client/accounts/accountdelete.go4
-rw-r--r--internal/api/client/accounts/accountget.go2
-rw-r--r--internal/api/client/accounts/accountupdate.go2
-rw-r--r--internal/api/client/accounts/accountverify.go2
-rw-r--r--internal/api/client/accounts/block.go2
-rw-r--r--internal/api/client/accounts/follow.go2
-rw-r--r--internal/api/client/accounts/followers.go2
-rw-r--r--internal/api/client/accounts/following.go2
-rw-r--r--internal/api/client/accounts/lists.go2
-rw-r--r--internal/api/client/accounts/lookup.go2
-rw-r--r--internal/api/client/accounts/note.go2
-rw-r--r--internal/api/client/accounts/relationships.go2
-rw-r--r--internal/api/client/accounts/search.go2
-rw-r--r--internal/api/client/accounts/statuses.go3
-rw-r--r--internal/api/client/accounts/unblock.go3
-rw-r--r--internal/api/client/accounts/unfollow.go2
-rw-r--r--internal/api/client/admin/accountaction.go4
-rw-r--r--internal/api/client/admin/domainkeysexpire.go4
-rw-r--r--internal/api/client/admin/domainpermission.go10
-rw-r--r--internal/api/client/admin/emailtest.go4
-rw-r--r--internal/api/client/admin/emojicategoriesget.go2
-rw-r--r--internal/api/client/admin/emojicreate.go2
-rw-r--r--internal/api/client/admin/emojidelete.go2
-rw-r--r--internal/api/client/admin/emojiget.go2
-rw-r--r--internal/api/client/admin/emojisget.go3
-rw-r--r--internal/api/client/admin/emojiupdate.go2
-rw-r--r--internal/api/client/admin/mediacleanup.go2
-rw-r--r--internal/api/client/admin/mediarefetch.go2
-rw-r--r--internal/api/client/admin/reportget.go2
-rw-r--r--internal/api/client/admin/reportresolve.go2
-rw-r--r--internal/api/client/admin/reportsget.go3
-rw-r--r--internal/api/client/admin/rulecreate.go2
-rw-r--r--internal/api/client/admin/ruledelete.go2
-rw-r--r--internal/api/client/admin/ruleget.go2
-rw-r--r--internal/api/client/admin/rulesget.go2
-rw-r--r--internal/api/client/admin/ruleupdate.go2
-rw-r--r--internal/api/client/apps/appcreate.go2
-rw-r--r--internal/api/client/blocks/blocksget.go2
-rw-r--r--internal/api/client/bookmarks/bookmarksget.go3
-rw-r--r--internal/api/client/customemojis/customemojisget.go2
-rw-r--r--internal/api/client/favourites/favouritesget.go3
-rw-r--r--internal/api/client/featuredtags/get.go2
-rw-r--r--internal/api/client/filters/filtersget.go2
-rw-r--r--internal/api/client/followrequests/authorize.go2
-rw-r--r--internal/api/client/followrequests/get.go2
-rw-r--r--internal/api/client/followrequests/reject.go2
-rw-r--r--internal/api/client/instance/instanceget.go4
-rw-r--r--internal/api/client/instance/instancepatch.go2
-rw-r--r--internal/api/client/instance/instancepatch_test.go24
-rw-r--r--internal/api/client/instance/instancepeersget.go2
-rw-r--r--internal/api/client/instance/instancerulesget.go2
-rw-r--r--internal/api/client/lists/listaccounts.go3
-rw-r--r--internal/api/client/lists/listaccountsadd.go2
-rw-r--r--internal/api/client/lists/listaccountsremove.go2
-rw-r--r--internal/api/client/lists/listcreate.go2
-rw-r--r--internal/api/client/lists/listdelete.go2
-rw-r--r--internal/api/client/lists/listget.go2
-rw-r--r--internal/api/client/lists/listsget.go2
-rw-r--r--internal/api/client/lists/listupdate.go2
-rw-r--r--internal/api/client/markers/markersget.go2
-rw-r--r--internal/api/client/markers/markerspost.go2
-rw-r--r--internal/api/client/media/mediacreate.go2
-rw-r--r--internal/api/client/media/mediaget.go2
-rw-r--r--internal/api/client/media/mediaupdate.go2
-rw-r--r--internal/api/client/notifications/notificationget.go2
-rw-r--r--internal/api/client/notifications/notificationsclear.go2
-rw-r--r--internal/api/client/notifications/notificationsget.go3
-rw-r--r--internal/api/client/polls/polls_get.go2
-rw-r--r--internal/api/client/polls/polls_vote.go2
-rw-r--r--internal/api/client/preferences/preferencesget.go3
-rw-r--r--internal/api/client/reports/reportcreate.go2
-rw-r--r--internal/api/client/reports/reportget.go2
-rw-r--r--internal/api/client/reports/reportsget.go3
-rw-r--r--internal/api/client/search/searchget.go2
-rw-r--r--internal/api/client/timelines/home.go3
-rw-r--r--internal/api/client/timelines/list.go3
-rw-r--r--internal/api/client/timelines/public.go3
-rw-r--r--internal/api/client/timelines/tag.go3
-rw-r--r--internal/api/client/user/passwordchange.go2
-rw-r--r--internal/api/fileserver/servefile.go13
-rw-r--r--internal/api/nodeinfo/nodeinfoget.go16
-rw-r--r--internal/api/util/errorhandling.go12
-rw-r--r--internal/api/util/mime.go28
-rw-r--r--internal/api/util/negotiate.go18
-rw-r--r--internal/api/util/negotiate_test.go2
-rw-r--r--internal/api/util/response.go282
-rw-r--r--internal/api/wellknown/hostmeta/hostmetaget.go27
-rw-r--r--internal/api/wellknown/nodeinfo/nodeinfoget.go9
-rw-r--r--internal/api/wellknown/webfinger/webfingerget.go18
-rw-r--r--internal/web/tag.go2
104 files changed, 526 insertions, 267 deletions
diff --git a/internal/api/activitypub/emoji/emojiget.go b/internal/api/activitypub/emoji/emojiget.go
index c291a500a..5a9f0db72 100644
--- a/internal/api/activitypub/emoji/emojiget.go
+++ b/internal/api/activitypub/emoji/emojiget.go
@@ -18,7 +18,6 @@
package emoji
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -36,7 +35,7 @@ func (m *Module) EmojiGetHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
@@ -48,11 +47,12 @@ func (m *Module) EmojiGetHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ // Encode JSON HTTP response.
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ contentType,
+ resp,
+ )
}
diff --git a/internal/api/activitypub/publickey/publickeyget.go b/internal/api/activitypub/publickey/publickeyget.go
index a7de4efad..083a31961 100644
--- a/internal/api/activitypub/publickey/publickeyget.go
+++ b/internal/api/activitypub/publickey/publickeyget.go
@@ -18,7 +18,6 @@
package publickey
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -42,13 +41,13 @@ func (m *Module) PublicKeyGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// redirect to the user's profile
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
return
@@ -60,11 +59,12 @@ func (m *Module) PublicKeyGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ // Encode JSON HTTP response.
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ contentType,
+ resp,
+ )
}
diff --git a/internal/api/activitypub/users/featured.go b/internal/api/activitypub/users/featured.go
index 7a2b73a6f..f256c1e75 100644
--- a/internal/api/activitypub/users/featured.go
+++ b/internal/api/activitypub/users/featured.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -67,13 +66,13 @@ func (m *Module) FeaturedCollectionGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// This isn't an ActivityPub request;
// redirect to the user's profile.
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
@@ -86,11 +85,5 @@ func (m *Module) FeaturedCollectionGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/followers.go b/internal/api/activitypub/users/followers.go
index e93ef8d4d..956cdc71e 100644
--- a/internal/api/activitypub/users/followers.go
+++ b/internal/api/activitypub/users/followers.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -39,13 +38,13 @@ func (m *Module) FollowersGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// This isn't an ActivityPub request;
// redirect to the user's profile.
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
@@ -68,11 +67,5 @@ func (m *Module) FollowersGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/following.go b/internal/api/activitypub/users/following.go
index 54fb3b676..d01b55b57 100644
--- a/internal/api/activitypub/users/following.go
+++ b/internal/api/activitypub/users/following.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -39,13 +38,13 @@ func (m *Module) FollowingGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// This isn't an ActivityPub request;
// redirect to the user's profile.
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
@@ -68,11 +67,5 @@ func (m *Module) FollowingGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/inboxpost.go b/internal/api/activitypub/users/inboxpost.go
index c2d3d79c4..03ba5c5a6 100644
--- a/internal/api/activitypub/users/inboxpost.go
+++ b/internal/api/activitypub/users/inboxpost.go
@@ -47,6 +47,5 @@ func (m *Module) InboxPOSTHandler(c *gin.Context) {
return
}
- // Inbox POST body was Accepted for processing.
- c.JSON(http.StatusAccepted, gin.H{"status": http.StatusText(http.StatusAccepted)})
+ apiutil.Data(c, http.StatusAccepted, apiutil.AppJSON, apiutil.StatusAcceptedJSON)
}
diff --git a/internal/api/activitypub/users/outboxget.go b/internal/api/activitypub/users/outboxget.go
index e4617ba90..7dcc354ac 100644
--- a/internal/api/activitypub/users/outboxget.go
+++ b/internal/api/activitypub/users/outboxget.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"fmt"
"net/http"
@@ -93,13 +92,13 @@ func (m *Module) OutboxGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// This isn't an ActivityPub request;
// redirect to the user's profile.
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
@@ -135,11 +134,5 @@ func (m *Module) OutboxGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/outboxget_test.go b/internal/api/activitypub/users/outboxget_test.go
index 4829a8946..31b7e8e9b 100644
--- a/internal/api/activitypub/users/outboxget_test.go
+++ b/internal/api/activitypub/users/outboxget_test.go
@@ -209,7 +209,7 @@ func (suite *OutboxGetTestSuite) TestGetOutboxNextPage() {
suite.NoError(err)
suite.Equal(`{
"@context": "https://www.w3.org/ns/activitystreams",
- "id": "http://localhost:8080/users/the_mighty_zork/outbox?page=true\u0026maxID=01F8MHAMCHF6Y650WCRSCP4WMY",
+ "id": "http://localhost:8080/users/the_mighty_zork/outbox?page=true&maxID=01F8MHAMCHF6Y650WCRSCP4WMY",
"orderedItems": [],
"partOf": "http://localhost:8080/users/the_mighty_zork/outbox",
"type": "OrderedCollectionPage"
diff --git a/internal/api/activitypub/users/repliesget.go b/internal/api/activitypub/users/repliesget.go
index 3ac4ccbbb..2d3472f35 100644
--- a/internal/api/activitypub/users/repliesget.go
+++ b/internal/api/activitypub/users/repliesget.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -107,13 +106,13 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// redirect to the status
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID)
return
@@ -161,12 +160,5 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- errWithCode := gtserror.NewErrorInternalError(err)
- apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/repliesget_test.go b/internal/api/activitypub/users/repliesget_test.go
index ac25f3617..d20d8c6c0 100644
--- a/internal/api/activitypub/users/repliesget_test.go
+++ b/internal/api/activitypub/users/repliesget_test.go
@@ -266,11 +266,16 @@ func toJSON(a any) string {
}
a = m
}
- b, err := json.MarshalIndent(a, "", " ")
+ var dst bytes.Buffer
+ enc := json.NewEncoder(&dst)
+ enc.SetIndent("", " ")
+ enc.SetEscapeHTML(false)
+ err := enc.Encode(a)
if err != nil {
panic(err)
}
- return string(b)
+ dst.Truncate(dst.Len() - 1) // drop new-line
+ return dst.String()
}
// indentJSON will return indented JSON from raw provided JSON.
diff --git a/internal/api/activitypub/users/statusget.go b/internal/api/activitypub/users/statusget.go
index f7b5ccfd1..27af9c6b4 100644
--- a/internal/api/activitypub/users/statusget.go
+++ b/internal/api/activitypub/users/statusget.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -46,13 +45,13 @@ func (m *Module) StatusGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// redirect to the status
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID)
return
@@ -64,11 +63,5 @@ func (m *Module) StatusGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/activitypub/users/userget.go b/internal/api/activitypub/users/userget.go
index 61be69836..2deca0fa4 100644
--- a/internal/api/activitypub/users/userget.go
+++ b/internal/api/activitypub/users/userget.go
@@ -18,7 +18,6 @@
package users
import (
- "encoding/json"
"errors"
"net/http"
"strings"
@@ -46,13 +45,13 @@ func (m *Module) UsersGETHandler(c *gin.Context) {
return
}
- format, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubOrHTMLHeaders...)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
- if format == string(apiutil.TextHTML) {
+ if contentType == string(apiutil.TextHTML) {
// redirect to the user's profile
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
return
@@ -64,11 +63,5 @@ func (m *Module) UsersGETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, format, b)
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
}
diff --git a/internal/api/auth/token.go b/internal/api/auth/token.go
index 9787e9efc..cab9352fa 100644
--- a/internal/api/auth/token.go
+++ b/internal/api/auth/token.go
@@ -110,5 +110,11 @@ func (m *Module) TokenPOSTHandler(c *gin.Context) {
c.Header("Cache-Control", "no-store")
c.Header("Pragma", "no-cache")
- c.JSON(http.StatusOK, token)
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ apiutil.AppJSON,
+ token,
+ )
}
diff --git a/internal/api/client/accounts/accountcreate.go b/internal/api/client/accounts/accountcreate.go
index 473000f6d..061c66b57 100644
--- a/internal/api/client/accounts/accountcreate.go
+++ b/internal/api/client/accounts/accountcreate.go
@@ -107,7 +107,7 @@ func (m *Module) AccountCreatePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, ti)
+ apiutil.JSON(c, http.StatusOK, ti)
}
// validateNormalizeCreateAccount checks through all the necessary prerequisites for creating a new account,
diff --git a/internal/api/client/accounts/accountdelete.go b/internal/api/client/accounts/accountdelete.go
index 242902cab..947634f70 100644
--- a/internal/api/client/accounts/accountdelete.go
+++ b/internal/api/client/accounts/accountdelete.go
@@ -96,5 +96,7 @@ func (m *Module) AccountDeletePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusAccepted, gin.H{"message": "accepted"})
+ apiutil.JSON(c, http.StatusAccepted, map[string]string{
+ "message": "accepted",
+ })
}
diff --git a/internal/api/client/accounts/accountget.go b/internal/api/client/accounts/accountget.go
index 300efe46e..4c1b66a20 100644
--- a/internal/api/client/accounts/accountget.go
+++ b/internal/api/client/accounts/accountget.go
@@ -90,5 +90,5 @@ func (m *Module) AccountGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, acctInfo)
+ apiutil.JSON(c, http.StatusOK, acctInfo)
}
diff --git a/internal/api/client/accounts/accountupdate.go b/internal/api/client/accounts/accountupdate.go
index 9c51f5924..ab731bd7e 100644
--- a/internal/api/client/accounts/accountupdate.go
+++ b/internal/api/client/accounts/accountupdate.go
@@ -170,7 +170,7 @@ func (m *Module) AccountUpdateCredentialsPATCHHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, acctSensitive)
+ apiutil.JSON(c, http.StatusOK, acctSensitive)
}
// fieldsAttributesFormBinding satisfies gin's binding.Binding interface.
diff --git a/internal/api/client/accounts/accountverify.go b/internal/api/client/accounts/accountverify.go
index 97a21e0d8..1799089ab 100644
--- a/internal/api/client/accounts/accountverify.go
+++ b/internal/api/client/accounts/accountverify.go
@@ -73,5 +73,5 @@ func (m *Module) AccountVerifyGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, acctSensitive)
+ apiutil.JSON(c, http.StatusOK, acctSensitive)
}
diff --git a/internal/api/client/accounts/block.go b/internal/api/client/accounts/block.go
index ccf781849..24ff099a7 100644
--- a/internal/api/client/accounts/block.go
+++ b/internal/api/client/accounts/block.go
@@ -90,5 +90,5 @@ func (m *Module) AccountBlockPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/accounts/follow.go b/internal/api/client/accounts/follow.go
index 260f647cc..2e6e79964 100644
--- a/internal/api/client/accounts/follow.go
+++ b/internal/api/client/accounts/follow.go
@@ -122,5 +122,5 @@ func (m *Module) AccountFollowPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/accounts/followers.go b/internal/api/client/accounts/followers.go
index 2448bc50a..bedbcef24 100644
--- a/internal/api/client/accounts/followers.go
+++ b/internal/api/client/accounts/followers.go
@@ -151,5 +151,5 @@ func (m *Module) AccountFollowersGETHandler(c *gin.Context) {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/accounts/following.go b/internal/api/client/accounts/following.go
index d106d6ea6..9a8e488b2 100644
--- a/internal/api/client/accounts/following.go
+++ b/internal/api/client/accounts/following.go
@@ -151,5 +151,5 @@ func (m *Module) AccountFollowingGETHandler(c *gin.Context) {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/accounts/lists.go b/internal/api/client/accounts/lists.go
index 4ce1bf729..d42fdd3f9 100644
--- a/internal/api/client/accounts/lists.go
+++ b/internal/api/client/accounts/lists.go
@@ -93,5 +93,5 @@ func (m *Module) AccountListsGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, lists)
+ apiutil.JSON(c, http.StatusOK, lists)
}
diff --git a/internal/api/client/accounts/lookup.go b/internal/api/client/accounts/lookup.go
index 4b31ea6cc..f6bd97657 100644
--- a/internal/api/client/accounts/lookup.go
+++ b/internal/api/client/accounts/lookup.go
@@ -89,5 +89,5 @@ func (m *Module) AccountLookupGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, account)
+ apiutil.JSON(c, http.StatusOK, account)
}
diff --git a/internal/api/client/accounts/note.go b/internal/api/client/accounts/note.go
index 9a0667875..29ea01c9a 100644
--- a/internal/api/client/accounts/note.go
+++ b/internal/api/client/accounts/note.go
@@ -104,5 +104,5 @@ func (m *Module) AccountNotePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/accounts/relationships.go b/internal/api/client/accounts/relationships.go
index 591ae7684..dfe8c1721 100644
--- a/internal/api/client/accounts/relationships.go
+++ b/internal/api/client/accounts/relationships.go
@@ -106,5 +106,5 @@ func (m *Module) AccountRelationshipsGETHandler(c *gin.Context) {
relationships = append(relationships, *r)
}
- c.JSON(http.StatusOK, relationships)
+ apiutil.JSON(c, http.StatusOK, relationships)
}
diff --git a/internal/api/client/accounts/search.go b/internal/api/client/accounts/search.go
index c10fb2960..183fc1347 100644
--- a/internal/api/client/accounts/search.go
+++ b/internal/api/client/accounts/search.go
@@ -162,5 +162,5 @@ func (m *Module) AccountSearchGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, results)
+ apiutil.JSON(c, http.StatusOK, results)
}
diff --git a/internal/api/client/accounts/statuses.go b/internal/api/client/accounts/statuses.go
index 867788501..870a96891 100644
--- a/internal/api/client/accounts/statuses.go
+++ b/internal/api/client/accounts/statuses.go
@@ -241,5 +241,6 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/accounts/unblock.go b/internal/api/client/accounts/unblock.go
index 882a3b2f1..e8144711e 100644
--- a/internal/api/client/accounts/unblock.go
+++ b/internal/api/client/accounts/unblock.go
@@ -91,5 +91,6 @@ func (m *Module) AccountUnblockPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
+
}
diff --git a/internal/api/client/accounts/unfollow.go b/internal/api/client/accounts/unfollow.go
index 4edc9ccea..9eb66aed3 100644
--- a/internal/api/client/accounts/unfollow.go
+++ b/internal/api/client/accounts/unfollow.go
@@ -91,5 +91,5 @@ func (m *Module) AccountUnfollowPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/admin/accountaction.go b/internal/api/client/admin/accountaction.go
index 91186ae73..89bcf644e 100644
--- a/internal/api/client/admin/accountaction.go
+++ b/internal/api/client/admin/accountaction.go
@@ -124,5 +124,7 @@ func (m *Module) AccountActionPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, gin.H{"message": "OK"})
+ apiutil.JSON(c, http.StatusOK, map[string]string{
+ "message": "OK",
+ })
}
diff --git a/internal/api/client/admin/domainkeysexpire.go b/internal/api/client/admin/domainkeysexpire.go
index 73a811dd4..10a7597a4 100644
--- a/internal/api/client/admin/domainkeysexpire.go
+++ b/internal/api/client/admin/domainkeysexpire.go
@@ -132,7 +132,9 @@ func (m *Module) DomainKeysExpirePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusAccepted, &apimodel.AdminActionResponse{ActionID: actionID})
+ apiutil.JSON(c, http.StatusOK, &apimodel.AdminActionResponse{
+ ActionID: actionID,
+ })
}
func validateDomainKeysExpire(form *apimodel.DomainKeysExpireRequest) error {
diff --git a/internal/api/client/admin/domainpermission.go b/internal/api/client/admin/domainpermission.go
index 203eddc8b..05319086f 100644
--- a/internal/api/client/admin/domainpermission.go
+++ b/internal/api/client/admin/domainpermission.go
@@ -122,7 +122,7 @@ func (m *Module) createDomainPermissions(
return
}
- c.JSON(http.StatusOK, domainBlock)
+ apiutil.JSON(c, http.StatusOK, domainBlock)
return
}
@@ -158,7 +158,7 @@ func (m *Module) createDomainPermissions(
domainPerms = append(domainPerms, entry.Resource)
}
- c.JSON(http.StatusOK, domainPerms)
+ apiutil.JSON(c, http.StatusOK, domainPerms)
}
// deleteDomainPermission deletes a single domain permission (block or allow).
@@ -200,7 +200,7 @@ func (m *Module) deleteDomainPermission(
return
}
- c.JSON(http.StatusOK, domainPerm)
+ apiutil.JSON(c, http.StatusOK, domainPerm)
}
// getDomainPermission gets a single domain permission (block or allow).
@@ -248,7 +248,7 @@ func (m *Module) getDomainPermission(
return
}
- c.JSON(http.StatusOK, domainPerm)
+ apiutil.JSON(c, http.StatusOK, domainPerm)
}
// getDomainPermissions gets all domain permissions of the given type (block, allow).
@@ -290,5 +290,5 @@ func (m *Module) getDomainPermissions(
return
}
- c.JSON(http.StatusOK, domainPerm)
+ apiutil.JSON(c, http.StatusOK, domainPerm)
}
diff --git a/internal/api/client/admin/emailtest.go b/internal/api/client/admin/emailtest.go
index 5c5330679..8f274e226 100644
--- a/internal/api/client/admin/emailtest.go
+++ b/internal/api/client/admin/emailtest.go
@@ -116,5 +116,7 @@ func (m *Module) EmailTestPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusAccepted, gin.H{"status": "test email sent"})
+ apiutil.JSON(c, http.StatusAccepted, map[string]string{
+ "status": "test email sent",
+ })
}
diff --git a/internal/api/client/admin/emojicategoriesget.go b/internal/api/client/admin/emojicategoriesget.go
index 9597f789c..2c097c6df 100644
--- a/internal/api/client/admin/emojicategoriesget.go
+++ b/internal/api/client/admin/emojicategoriesget.go
@@ -89,5 +89,5 @@ func (m *Module) EmojiCategoriesGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, categories)
+ apiutil.JSON(c, http.StatusOK, categories)
}
diff --git a/internal/api/client/admin/emojicreate.go b/internal/api/client/admin/emojicreate.go
index e98ef754e..d916a76c1 100644
--- a/internal/api/client/admin/emojicreate.go
+++ b/internal/api/client/admin/emojicreate.go
@@ -131,7 +131,7 @@ func (m *Module) EmojiCreatePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiEmoji)
+ apiutil.JSON(c, http.StatusOK, apiEmoji)
}
func validateCreateEmoji(form *apimodel.EmojiCreateRequest) error {
diff --git a/internal/api/client/admin/emojidelete.go b/internal/api/client/admin/emojidelete.go
index 8d388a409..b5cf72daf 100644
--- a/internal/api/client/admin/emojidelete.go
+++ b/internal/api/client/admin/emojidelete.go
@@ -105,5 +105,5 @@ func (m *Module) EmojiDELETEHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, emoji)
+ apiutil.JSON(c, http.StatusOK, emoji)
}
diff --git a/internal/api/client/admin/emojiget.go b/internal/api/client/admin/emojiget.go
index 349747b6b..710094551 100644
--- a/internal/api/client/admin/emojiget.go
+++ b/internal/api/client/admin/emojiget.go
@@ -95,5 +95,5 @@ func (m *Module) EmojiGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, emoji)
+ apiutil.JSON(c, http.StatusOK, emoji)
}
diff --git a/internal/api/client/admin/emojisget.go b/internal/api/client/admin/emojisget.go
index c0ae90004..212401117 100644
--- a/internal/api/client/admin/emojisget.go
+++ b/internal/api/client/admin/emojisget.go
@@ -206,5 +206,6 @@ func (m *Module) EmojisGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/admin/emojiupdate.go b/internal/api/client/admin/emojiupdate.go
index 49f8c3414..f531f36f9 100644
--- a/internal/api/client/admin/emojiupdate.go
+++ b/internal/api/client/admin/emojiupdate.go
@@ -161,7 +161,7 @@ func (m *Module) EmojiPATCHHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, emoji)
+ apiutil.JSON(c, http.StatusOK, emoji)
}
// do a first pass on the form here
diff --git a/internal/api/client/admin/mediacleanup.go b/internal/api/client/admin/mediacleanup.go
index 3ef3c1441..7a0ee4bd6 100644
--- a/internal/api/client/admin/mediacleanup.go
+++ b/internal/api/client/admin/mediacleanup.go
@@ -102,5 +102,5 @@ func (m *Module) MediaCleanupPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, remoteCacheDays)
+ apiutil.JSON(c, http.StatusOK, remoteCacheDays)
}
diff --git a/internal/api/client/admin/mediarefetch.go b/internal/api/client/admin/mediarefetch.go
index 2c57d3b95..1c0da6dea 100644
--- a/internal/api/client/admin/mediarefetch.go
+++ b/internal/api/client/admin/mediarefetch.go
@@ -88,5 +88,5 @@ func (m *Module) MediaRefetchPOSTHandler(c *gin.Context) {
return
}
- c.Status(http.StatusAccepted)
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.StatusAcceptedJSON)
}
diff --git a/internal/api/client/admin/reportget.go b/internal/api/client/admin/reportget.go
index 55425f53a..f70ae8b54 100644
--- a/internal/api/client/admin/reportget.go
+++ b/internal/api/client/admin/reportget.go
@@ -98,5 +98,5 @@ func (m *Module) ReportGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, report)
+ apiutil.JSON(c, http.StatusOK, report)
}
diff --git a/internal/api/client/admin/reportresolve.go b/internal/api/client/admin/reportresolve.go
index fdd4f8449..9c1c32afe 100644
--- a/internal/api/client/admin/reportresolve.go
+++ b/internal/api/client/admin/reportresolve.go
@@ -120,5 +120,5 @@ func (m *Module) ReportResolvePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, report)
+ apiutil.JSON(c, http.StatusOK, report)
}
diff --git a/internal/api/client/admin/reportsget.go b/internal/api/client/admin/reportsget.go
index cffa578f4..394962f6b 100644
--- a/internal/api/client/admin/reportsget.go
+++ b/internal/api/client/admin/reportsget.go
@@ -176,5 +176,6 @@ func (m *Module) ReportsGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/admin/rulecreate.go b/internal/api/client/admin/rulecreate.go
index 7792233f6..e838bff1e 100644
--- a/internal/api/client/admin/rulecreate.go
+++ b/internal/api/client/admin/rulecreate.go
@@ -108,7 +108,7 @@ func (m *Module) RulePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiRule)
+ apiutil.JSON(c, http.StatusOK, apiRule)
}
func validateCreateRule(form *apimodel.InstanceRuleCreateRequest) error {
diff --git a/internal/api/client/admin/ruledelete.go b/internal/api/client/admin/ruledelete.go
index 7281ed62e..dfa84615f 100644
--- a/internal/api/client/admin/ruledelete.go
+++ b/internal/api/client/admin/ruledelete.go
@@ -103,5 +103,5 @@ func (m *Module) RuleDELETEHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiRule)
+ apiutil.JSON(c, http.StatusOK, apiRule)
}
diff --git a/internal/api/client/admin/ruleget.go b/internal/api/client/admin/ruleget.go
index 444820a3f..8281092fb 100644
--- a/internal/api/client/admin/ruleget.go
+++ b/internal/api/client/admin/ruleget.go
@@ -98,5 +98,5 @@ func (m *Module) RuleGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, rule)
+ apiutil.JSON(c, http.StatusOK, rule)
}
diff --git a/internal/api/client/admin/rulesget.go b/internal/api/client/admin/rulesget.go
index 56f83866f..2cc9e0158 100644
--- a/internal/api/client/admin/rulesget.go
+++ b/internal/api/client/admin/rulesget.go
@@ -87,5 +87,5 @@ func (m *Module) RulesGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, resp)
+ apiutil.JSON(c, http.StatusOK, resp)
}
diff --git a/internal/api/client/admin/ruleupdate.go b/internal/api/client/admin/ruleupdate.go
index 82ed41190..eafa3af34 100644
--- a/internal/api/client/admin/ruleupdate.go
+++ b/internal/api/client/admin/ruleupdate.go
@@ -123,5 +123,5 @@ func (m *Module) RulePATCHHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiRule)
+ apiutil.JSON(c, http.StatusOK, apiRule)
}
diff --git a/internal/api/client/apps/appcreate.go b/internal/api/client/apps/appcreate.go
index ebbc462cd..8aa87c3b3 100644
--- a/internal/api/client/apps/appcreate.go
+++ b/internal/api/client/apps/appcreate.go
@@ -121,5 +121,5 @@ func (m *Module) AppsPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiApp)
+ apiutil.JSON(c, http.StatusOK, apiApp)
}
diff --git a/internal/api/client/blocks/blocksget.go b/internal/api/client/blocks/blocksget.go
index 0761160bc..fe5104c61 100644
--- a/internal/api/client/blocks/blocksget.go
+++ b/internal/api/client/blocks/blocksget.go
@@ -142,5 +142,5 @@ func (m *Module) BlocksGETHandler(c *gin.Context) {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/bookmarks/bookmarksget.go b/internal/api/client/bookmarks/bookmarksget.go
index 06aaaf578..17808642c 100644
--- a/internal/api/client/bookmarks/bookmarksget.go
+++ b/internal/api/client/bookmarks/bookmarksget.go
@@ -120,5 +120,6 @@ func (m *Module) BookmarksGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/customemojis/customemojisget.go b/internal/api/client/customemojis/customemojisget.go
index f9a529114..be595afd7 100644
--- a/internal/api/client/customemojis/customemojisget.go
+++ b/internal/api/client/customemojis/customemojisget.go
@@ -71,5 +71,5 @@ func (m *Module) CustomEmojisGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, emojis)
+ apiutil.JSON(c, http.StatusOK, emojis)
}
diff --git a/internal/api/client/favourites/favouritesget.go b/internal/api/client/favourites/favouritesget.go
index 112bbd856..3ba2f9fcf 100644
--- a/internal/api/client/favourites/favouritesget.go
+++ b/internal/api/client/favourites/favouritesget.go
@@ -137,5 +137,6 @@ func (m *Module) FavouritesGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/featuredtags/get.go b/internal/api/client/featuredtags/get.go
index f4ba00a39..c1ee7ca2c 100644
--- a/internal/api/client/featuredtags/get.go
+++ b/internal/api/client/featuredtags/get.go
@@ -71,5 +71,5 @@ func (m *Module) FeaturedTagsGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, []interface{}{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONArray)
}
diff --git a/internal/api/client/filters/filtersget.go b/internal/api/client/filters/filtersget.go
index 58ae23c32..38dd330a7 100644
--- a/internal/api/client/filters/filtersget.go
+++ b/internal/api/client/filters/filtersget.go
@@ -38,5 +38,5 @@ func (m *Module) FiltersGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, []string{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONArray)
}
diff --git a/internal/api/client/followrequests/authorize.go b/internal/api/client/followrequests/authorize.go
index 707d3db26..406b54179 100644
--- a/internal/api/client/followrequests/authorize.go
+++ b/internal/api/client/followrequests/authorize.go
@@ -93,5 +93,5 @@ func (m *Module) FollowRequestAuthorizePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/followrequests/get.go b/internal/api/client/followrequests/get.go
index af2f3741c..40cdceaea 100644
--- a/internal/api/client/followrequests/get.go
+++ b/internal/api/client/followrequests/get.go
@@ -139,5 +139,5 @@ func (m *Module) FollowRequestGETHandler(c *gin.Context) {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/followrequests/reject.go b/internal/api/client/followrequests/reject.go
index 6514a615e..a8189b78a 100644
--- a/internal/api/client/followrequests/reject.go
+++ b/internal/api/client/followrequests/reject.go
@@ -91,5 +91,5 @@ func (m *Module) FollowRequestRejectPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, relationship)
+ apiutil.JSON(c, http.StatusOK, relationship)
}
diff --git a/internal/api/client/instance/instanceget.go b/internal/api/client/instance/instanceget.go
index 57d47b902..6690e7e98 100644
--- a/internal/api/client/instance/instanceget.go
+++ b/internal/api/client/instance/instanceget.go
@@ -58,7 +58,7 @@ func (m *Module) InstanceInformationGETHandlerV1(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, instance)
+ apiutil.JSON(c, http.StatusOK, instance)
}
// InstanceInformationGETHandlerV2 swagger:operation GET /api/v2/instance instanceGetV2
@@ -93,5 +93,5 @@ func (m *Module) InstanceInformationGETHandlerV2(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, instance)
+ apiutil.JSON(c, http.StatusOK, instance)
}
diff --git a/internal/api/client/instance/instancepatch.go b/internal/api/client/instance/instancepatch.go
index 885ad19c8..484579cf2 100644
--- a/internal/api/client/instance/instancepatch.go
+++ b/internal/api/client/instance/instancepatch.go
@@ -161,7 +161,7 @@ func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, i)
+ apiutil.JSON(c, http.StatusOK, i)
}
func validateInstanceUpdate(form *apimodel.InstanceSettingsUpdateRequest) error {
diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go
index 1f8b691be..0c270de21 100644
--- a/internal/api/client/instance/instancepatch_test.go
+++ b/internal/api/client/instance/instancepatch_test.go
@@ -78,8 +78,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "Example Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
"email": "someone@example.org",
"version": "0.0.0-testrig",
"languages": [
@@ -195,8 +195,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "Geoff's Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
"email": "admin@example.org",
"version": "0.0.0-testrig",
"languages": [
@@ -312,8 +312,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "GoToSocial Testrig Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is some html, which is \u003cem\u003eallowed\u003c/em\u003e in short descriptions.\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is some html, which is <em>allowed</em> in short descriptions.</p>",
"email": "admin@example.org",
"version": "0.0.0-testrig",
"languages": [
@@ -480,8 +480,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "GoToSocial Testrig Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
"email": "",
"version": "0.0.0-testrig",
"languages": [
@@ -619,8 +619,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "GoToSocial Testrig Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
"email": "admin@example.org",
"version": "0.0.0-testrig",
"languages": [
@@ -773,8 +773,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
"uri": "http://localhost:8080",
"account_domain": "localhost:8080",
"title": "GoToSocial Testrig Instance",
- "description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
- "short_description": "\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e",
+ "description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
+ "short_description": "<p>This is the GoToSocial testrig. It doesn't federate or anything.</p><p>When the testrig is shut down, all data on it will be deleted.</p><p>Don't use this in production!</p>",
"email": "admin@example.org",
"version": "0.0.0-testrig",
"languages": [
diff --git a/internal/api/client/instance/instancepeersget.go b/internal/api/client/instance/instancepeersget.go
index 05085bc0f..c278c0674 100644
--- a/internal/api/client/instance/instancepeersget.go
+++ b/internal/api/client/instance/instancepeersget.go
@@ -156,5 +156,5 @@ func (m *Module) InstancePeersGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, data)
+ apiutil.JSON(c, http.StatusOK, data)
}
diff --git a/internal/api/client/instance/instancerulesget.go b/internal/api/client/instance/instancerulesget.go
index 5cc99ba41..9df1b8fbe 100644
--- a/internal/api/client/instance/instancerulesget.go
+++ b/internal/api/client/instance/instancerulesget.go
@@ -67,5 +67,5 @@ func (m *Module) InstanceRulesGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, resp)
+ apiutil.JSON(c, http.StatusOK, resp)
}
diff --git a/internal/api/client/lists/listaccounts.go b/internal/api/client/lists/listaccounts.go
index 6feffb1e8..e1d340ebb 100644
--- a/internal/api/client/lists/listaccounts.go
+++ b/internal/api/client/lists/listaccounts.go
@@ -174,5 +174,6 @@ func (m *Module) ListAccountsGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/lists/listaccountsadd.go b/internal/api/client/lists/listaccountsadd.go
index a2a74e475..6fb5eab3c 100644
--- a/internal/api/client/lists/listaccountsadd.go
+++ b/internal/api/client/lists/listaccountsadd.go
@@ -116,5 +116,5 @@ func (m *Module) ListAccountsPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, gin.H{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONObject)
}
diff --git a/internal/api/client/lists/listaccountsremove.go b/internal/api/client/lists/listaccountsremove.go
index 2a89cb960..50e53a3a3 100644
--- a/internal/api/client/lists/listaccountsremove.go
+++ b/internal/api/client/lists/listaccountsremove.go
@@ -126,5 +126,5 @@ func (m *Module) ListAccountsDELETEHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, gin.H{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONObject)
}
diff --git a/internal/api/client/lists/listcreate.go b/internal/api/client/lists/listcreate.go
index 1405aedd2..4228e5fff 100644
--- a/internal/api/client/lists/listcreate.go
+++ b/internal/api/client/lists/listcreate.go
@@ -102,5 +102,5 @@ func (m *Module) ListCreatePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiList)
+ apiutil.JSON(c, http.StatusOK, apiList)
}
diff --git a/internal/api/client/lists/listdelete.go b/internal/api/client/lists/listdelete.go
index e0139b574..b03f21e5a 100644
--- a/internal/api/client/lists/listdelete.go
+++ b/internal/api/client/lists/listdelete.go
@@ -87,5 +87,5 @@ func (m *Module) ListDELETEHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, gin.H{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONObject)
}
diff --git a/internal/api/client/lists/listget.go b/internal/api/client/lists/listget.go
index f8dc54eb1..34b21d28b 100644
--- a/internal/api/client/lists/listget.go
+++ b/internal/api/client/lists/listget.go
@@ -91,5 +91,5 @@ func (m *Module) ListGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, resp)
+ apiutil.JSON(c, http.StatusOK, resp)
}
diff --git a/internal/api/client/lists/listsget.go b/internal/api/client/lists/listsget.go
index f16152a9d..6bfc3c883 100644
--- a/internal/api/client/lists/listsget.go
+++ b/internal/api/client/lists/listsget.go
@@ -77,5 +77,5 @@ func (m *Module) ListsGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, lists)
+ apiutil.JSON(c, http.StatusOK, lists)
}
diff --git a/internal/api/client/lists/listupdate.go b/internal/api/client/lists/listupdate.go
index 97c0cc636..58a4cf1c4 100644
--- a/internal/api/client/lists/listupdate.go
+++ b/internal/api/client/lists/listupdate.go
@@ -148,5 +148,5 @@ func (m *Module) ListUpdatePUTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiList)
+ apiutil.JSON(c, http.StatusOK, apiList)
}
diff --git a/internal/api/client/markers/markersget.go b/internal/api/client/markers/markersget.go
index eb403dcc6..9f4fc4270 100644
--- a/internal/api/client/markers/markersget.go
+++ b/internal/api/client/markers/markersget.go
@@ -84,7 +84,7 @@ func (m *Module) MarkersGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, marker)
+ apiutil.JSON(c, http.StatusOK, marker)
}
// parseMarkerNames turns a list of strings into a set of valid marker timeline names, or returns an error.
diff --git a/internal/api/client/markers/markerspost.go b/internal/api/client/markers/markerspost.go
index 3167becac..8fe40c798 100644
--- a/internal/api/client/markers/markerspost.go
+++ b/internal/api/client/markers/markerspost.go
@@ -106,5 +106,5 @@ func (m *Module) MarkersPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, marker)
+ apiutil.JSON(c, http.StatusOK, marker)
}
diff --git a/internal/api/client/media/mediacreate.go b/internal/api/client/media/mediacreate.go
index d2264bb0d..daa2e5bb7 100644
--- a/internal/api/client/media/mediacreate.go
+++ b/internal/api/client/media/mediacreate.go
@@ -139,7 +139,7 @@ func (m *Module) MediaCreatePOSTHandler(c *gin.Context) {
apiAttachment.URL = nil
}
- c.JSON(http.StatusOK, apiAttachment)
+ apiutil.JSON(c, http.StatusOK, apiAttachment)
}
func validateCreateMedia(form *apimodel.AttachmentRequest) error {
diff --git a/internal/api/client/media/mediaget.go b/internal/api/client/media/mediaget.go
index 431f73d65..8456f85d8 100644
--- a/internal/api/client/media/mediaget.go
+++ b/internal/api/client/media/mediaget.go
@@ -98,5 +98,5 @@ func (m *Module) MediaGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, attachment)
+ apiutil.JSON(c, http.StatusOK, attachment)
}
diff --git a/internal/api/client/media/mediaupdate.go b/internal/api/client/media/mediaupdate.go
index 032cfd705..8378502e8 100644
--- a/internal/api/client/media/mediaupdate.go
+++ b/internal/api/client/media/mediaupdate.go
@@ -141,7 +141,7 @@ func (m *Module) MediaPUTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, attachment)
+ apiutil.JSON(c, http.StatusOK, attachment)
}
func validateUpdateMedia(form *apimodel.AttachmentUpdateRequest) error {
diff --git a/internal/api/client/notifications/notificationget.go b/internal/api/client/notifications/notificationget.go
index 98e32498b..551eeca39 100644
--- a/internal/api/client/notifications/notificationget.go
+++ b/internal/api/client/notifications/notificationget.go
@@ -83,5 +83,5 @@ func (m *Module) NotificationGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, resp)
+ apiutil.JSON(c, http.StatusOK, resp)
}
diff --git a/internal/api/client/notifications/notificationsclear.go b/internal/api/client/notifications/notificationsclear.go
index 4b63db283..2d7da3c6b 100644
--- a/internal/api/client/notifications/notificationsclear.go
+++ b/internal/api/client/notifications/notificationsclear.go
@@ -75,5 +75,5 @@ func (m *Module) NotificationsClearPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, struct{}{})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.EmptyJSONObject)
}
diff --git a/internal/api/client/notifications/notificationsget.go b/internal/api/client/notifications/notificationsget.go
index fd175a115..da43cffec 100644
--- a/internal/api/client/notifications/notificationsget.go
+++ b/internal/api/client/notifications/notificationsget.go
@@ -155,5 +155,6 @@ func (m *Module) NotificationsGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/polls/polls_get.go b/internal/api/client/polls/polls_get.go
index 0b15c0ed1..fc89255e9 100644
--- a/internal/api/client/polls/polls_get.go
+++ b/internal/api/client/polls/polls_get.go
@@ -96,5 +96,5 @@ func (m *Module) PollGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, poll)
+ apiutil.JSON(c, http.StatusOK, poll)
}
diff --git a/internal/api/client/polls/polls_vote.go b/internal/api/client/polls/polls_vote.go
index e5281b3fc..0ab5ac20c 100644
--- a/internal/api/client/polls/polls_vote.go
+++ b/internal/api/client/polls/polls_vote.go
@@ -117,7 +117,7 @@ func (m *Module) PollVotePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, poll)
+ apiutil.JSON(c, http.StatusOK, poll)
}
func bindChoices(c *gin.Context) ([]int, error) {
diff --git a/internal/api/client/preferences/preferencesget.go b/internal/api/client/preferences/preferencesget.go
index 2834134de..4a6cb4b55 100644
--- a/internal/api/client/preferences/preferencesget.go
+++ b/internal/api/client/preferences/preferencesget.go
@@ -87,5 +87,6 @@ func (m *Module) PreferencesGETHandler(c *gin.Context) {
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
return
}
- c.JSON(http.StatusOK, resp)
+
+ apiutil.JSON(c, http.StatusOK, resp)
}
diff --git a/internal/api/client/reports/reportcreate.go b/internal/api/client/reports/reportcreate.go
index a4fa01148..a34b8d52e 100644
--- a/internal/api/client/reports/reportcreate.go
+++ b/internal/api/client/reports/reportcreate.go
@@ -107,5 +107,5 @@ func (m *Module) ReportPOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, apiReport)
+ apiutil.JSON(c, http.StatusOK, apiReport)
}
diff --git a/internal/api/client/reports/reportget.go b/internal/api/client/reports/reportget.go
index 0d5d16da2..4a9b06664 100644
--- a/internal/api/client/reports/reportget.go
+++ b/internal/api/client/reports/reportget.go
@@ -90,5 +90,5 @@ func (m *Module) ReportGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, report)
+ apiutil.JSON(c, http.StatusOK, report)
}
diff --git a/internal/api/client/reports/reportsget.go b/internal/api/client/reports/reportsget.go
index e290608eb..ba47f1b8b 100644
--- a/internal/api/client/reports/reportsget.go
+++ b/internal/api/client/reports/reportsget.go
@@ -168,5 +168,6 @@ func (m *Module) ReportsGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/search/searchget.go b/internal/api/client/search/searchget.go
index 2759feb5b..909c14f24 100644
--- a/internal/api/client/search/searchget.go
+++ b/internal/api/client/search/searchget.go
@@ -235,5 +235,5 @@ func (m *Module) SearchGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, results)
+ apiutil.JSON(c, http.StatusOK, results)
}
diff --git a/internal/api/client/timelines/home.go b/internal/api/client/timelines/home.go
index 963096f59..a7e7717da 100644
--- a/internal/api/client/timelines/home.go
+++ b/internal/api/client/timelines/home.go
@@ -147,5 +147,6 @@ func (m *Module) HomeTimelineGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/timelines/list.go b/internal/api/client/timelines/list.go
index 2e13e32cd..dc5f21424 100644
--- a/internal/api/client/timelines/list.go
+++ b/internal/api/client/timelines/list.go
@@ -145,5 +145,6 @@ func (m *Module) ListTimelineGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/timelines/public.go b/internal/api/client/timelines/public.go
index 7b8acf1ca..8eb34edc7 100644
--- a/internal/api/client/timelines/public.go
+++ b/internal/api/client/timelines/public.go
@@ -158,5 +158,6 @@ func (m *Module) PublicTimelineGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/timelines/tag.go b/internal/api/client/timelines/tag.go
index 58754705b..0d95a6c58 100644
--- a/internal/api/client/timelines/tag.go
+++ b/internal/api/client/timelines/tag.go
@@ -142,5 +142,6 @@ func (m *Module) TagTimelineGETHandler(c *gin.Context) {
if resp.LinkHeader != "" {
c.Header("Link", resp.LinkHeader)
}
- c.JSON(http.StatusOK, resp.Items)
+
+ apiutil.JSON(c, http.StatusOK, resp.Items)
}
diff --git a/internal/api/client/user/passwordchange.go b/internal/api/client/user/passwordchange.go
index 8a1487ac0..c2928e9e5 100644
--- a/internal/api/client/user/passwordchange.go
+++ b/internal/api/client/user/passwordchange.go
@@ -99,5 +99,5 @@ func (m *Module) PasswordChangePOSTHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, gin.H{"status": "OK"})
+ apiutil.Data(c, http.StatusOK, apiutil.AppJSON, apiutil.StatusOKJSON)
}
diff --git a/internal/api/fileserver/servefile.go b/internal/api/fileserver/servefile.go
index 12d24ca76..5fe79f1d7 100644
--- a/internal/api/fileserver/servefile.go
+++ b/internal/api/fileserver/servefile.go
@@ -91,9 +91,8 @@ func (m *Module) ServeFile(c *gin.Context) {
}
if content.URL != nil {
- // This is a non-local, non-proxied S3 file we're redirecting to.
- // Derive the max-age value from how long the link has left until
- // it expires.
+ // This is a non-local, non-proxied S3 file we're redirecting to. Derive
+ // the max-age value from how long the link has left until it expires.
maxAge := int(time.Until(content.URL.Expiry).Seconds())
c.Header("Cache-Control", "private, max-age="+strconv.Itoa(maxAge)+", immutable")
c.Redirect(http.StatusFound, content.URL.String())
@@ -110,7 +109,7 @@ func (m *Module) ServeFile(c *gin.Context) {
// TODO: if the requester only accepts text/html we should try to serve them *something*.
// This is mostly needed because when sharing a link to a gts-hosted file on something like mastodon, the masto servers will
// attempt to look up the content to provide a preview of the link, and they ask for text/html.
- format, err := apiutil.NegotiateAccept(c, apiutil.MIME(content.ContentType))
+ contentType, err := apiutil.NegotiateAccept(c, content.ContentType)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
@@ -118,7 +117,7 @@ func (m *Module) ServeFile(c *gin.Context) {
// if this is a head request, just return info + throw the reader away
if c.Request.Method == http.MethodHead {
- c.Header("Content-Type", format)
+ c.Header("Content-Type", contentType)
c.Header("Content-Length", strconv.FormatInt(content.ContentLength, 10))
c.Status(http.StatusOK)
return
@@ -128,12 +127,12 @@ func (m *Module) ServeFile(c *gin.Context) {
rng := c.GetHeader("Range")
if rng == "" {
// This is a simple query for the whole file, so do a read from whole reader.
- c.DataFromReader(http.StatusOK, content.ContentLength, format, content.Content, nil)
+ c.DataFromReader(http.StatusOK, content.ContentLength, contentType, content.Content, nil)
return
}
// Set known content-type and serve range.
- c.Header("Content-Type", format)
+ c.Header("Content-Type", contentType)
serveFileRange(
c.Writer,
c.Request,
diff --git a/internal/api/nodeinfo/nodeinfoget.go b/internal/api/nodeinfo/nodeinfoget.go
index 3158eeb9a..368a5503d 100644
--- a/internal/api/nodeinfo/nodeinfoget.go
+++ b/internal/api/nodeinfo/nodeinfoget.go
@@ -18,7 +18,6 @@
package nodeinfo
import (
- "encoding/json"
"net/http"
"github.com/gin-gonic/gin"
@@ -55,11 +54,12 @@ func (m *Module) NodeInfo2GETHandler(c *gin.Context) {
return
}
- b, err := json.Marshal(nodeInfo)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, NodeInfo2ContentType, b)
+ // Encode JSON HTTP response.
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ NodeInfo2ContentType,
+ nodeInfo,
+ )
}
diff --git a/internal/api/util/errorhandling.go b/internal/api/util/errorhandling.go
index 4fa544ffd..8bb251040 100644
--- a/internal/api/util/errorhandling.go
+++ b/internal/api/util/errorhandling.go
@@ -55,7 +55,9 @@ func NotFoundHandler(c *gin.Context, instanceGet func(ctx context.Context) (*api
"requestID": gtscontext.RequestID(ctx),
})
default:
- c.JSON(http.StatusNotFound, gin.H{"error": errWithCode.Safe()})
+ JSON(c, http.StatusNotFound, map[string]string{
+ "error": errWithCode.Safe(),
+ })
}
}
@@ -78,7 +80,9 @@ func genericErrorHandler(c *gin.Context, instanceGet func(ctx context.Context) (
"requestID": gtscontext.RequestID(ctx),
})
default:
- c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
+ JSON(c, errWithCode.Code(), map[string]string{
+ "error": errWithCode.Safe(),
+ })
}
}
@@ -102,7 +106,7 @@ func ErrorHandler(
c *gin.Context,
errWithCode gtserror.WithCode,
instanceGet func(ctx context.Context) (*apimodel.InstanceV1, gtserror.WithCode),
- offers ...MIME,
+ offers ...string,
) {
if ctxErr := c.Request.Context().Err(); ctxErr != nil {
// Context error means either client has left already,
@@ -175,7 +179,7 @@ func OAuthErrorHandler(c *gin.Context, errWithCode gtserror.WithCode) {
l.Debug("handling OAuth error")
}
- c.JSON(statusCode, gin.H{
+ JSON(c, statusCode, map[string]string{
"error": errWithCode.Error(),
"error_description": errWithCode.Safe(),
})
diff --git a/internal/api/util/mime.go b/internal/api/util/mime.go
index edd0dcecf..ad1b405cd 100644
--- a/internal/api/util/mime.go
+++ b/internal/api/util/mime.go
@@ -17,20 +17,18 @@
package util
-// MIME represents a mime-type.
-type MIME string
-
const (
- AppJSON MIME = `application/json`
- AppXML MIME = `application/xml`
- AppXMLXRD MIME = `application/xrd+xml`
- AppRSSXML MIME = `application/rss+xml`
- AppActivityJSON MIME = `application/activity+json`
- AppActivityLDJSON MIME = `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`
- AppJRDJSON MIME = `application/jrd+json` // https://www.rfc-editor.org/rfc/rfc7033#section-10.2
- AppForm MIME = `application/x-www-form-urlencoded`
- MultipartForm MIME = `multipart/form-data`
- TextXML MIME = `text/xml`
- TextHTML MIME = `text/html`
- TextCSS MIME = `text/css`
+ // Possible GoToSocial mimetypes.
+ AppJSON = `application/json`
+ AppXML = `application/xml`
+ AppXMLXRD = `application/xrd+xml`
+ AppRSSXML = `application/rss+xml`
+ AppActivityJSON = `application/activity+json`
+ AppActivityLDJSON = `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`
+ AppJRDJSON = `application/jrd+json` // https://www.rfc-editor.org/rfc/rfc7033#section-10.2
+ AppForm = `application/x-www-form-urlencoded`
+ MultipartForm = `multipart/form-data`
+ TextXML = `text/xml`
+ TextHTML = `text/html`
+ TextCSS = `text/css`
)
diff --git a/internal/api/util/negotiate.go b/internal/api/util/negotiate.go
index f4268511b..5b4f54bc6 100644
--- a/internal/api/util/negotiate.go
+++ b/internal/api/util/negotiate.go
@@ -26,7 +26,7 @@ import (
)
// JSONAcceptHeaders is a slice of offers that just contains application/json types.
-var JSONAcceptHeaders = []MIME{
+var JSONAcceptHeaders = []string{
AppJSON,
}
@@ -34,7 +34,7 @@ var JSONAcceptHeaders = []MIME{
// jrd+json content type, but will be chill and fall back to app/json.
// This is to be used specifically for webfinger responses.
// See https://www.rfc-editor.org/rfc/rfc7033#section-10.2
-var WebfingerJSONAcceptHeaders = []MIME{
+var WebfingerJSONAcceptHeaders = []string{
AppJRDJSON,
AppJSON,
}
@@ -42,13 +42,13 @@ var WebfingerJSONAcceptHeaders = []MIME{
// JSONOrHTMLAcceptHeaders is a slice of offers that prefers AppJSON and will
// fall back to HTML if necessary. This is useful for error handling, since it can
// be used to serve a nice HTML page if the caller accepts that, or just JSON if not.
-var JSONOrHTMLAcceptHeaders = []MIME{
+var JSONOrHTMLAcceptHeaders = []string{
AppJSON,
TextHTML,
}
// HTMLAcceptHeaders is a slice of offers that just contains text/html types.
-var HTMLAcceptHeaders = []MIME{
+var HTMLAcceptHeaders = []string{
TextHTML,
}
@@ -57,7 +57,7 @@ var HTMLAcceptHeaders = []MIME{
// but which should also be able to serve ActivityPub as a fallback.
//
// https://www.w3.org/TR/activitypub/#retrieving-objects
-var HTMLOrActivityPubHeaders = []MIME{
+var HTMLOrActivityPubHeaders = []string{
TextHTML,
AppActivityLDJSON,
AppActivityJSON,
@@ -68,7 +68,7 @@ var HTMLOrActivityPubHeaders = []MIME{
// which a user might also go to in their browser sometimes.
//
// https://www.w3.org/TR/activitypub/#retrieving-objects
-var ActivityPubOrHTMLHeaders = []MIME{
+var ActivityPubOrHTMLHeaders = []string{
AppActivityLDJSON,
AppActivityJSON,
TextHTML,
@@ -78,12 +78,12 @@ var ActivityPubOrHTMLHeaders = []MIME{
// This is useful for URLs should only serve ActivityPub.
//
// https://www.w3.org/TR/activitypub/#retrieving-objects
-var ActivityPubHeaders = []MIME{
+var ActivityPubHeaders = []string{
AppActivityLDJSON,
AppActivityJSON,
}
-var HostMetaHeaders = []MIME{
+var HostMetaHeaders = []string{
AppXMLXRD,
AppXML,
}
@@ -109,7 +109,7 @@ var HostMetaHeaders = []MIME{
// often-used Accept types.
//
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation#server-driven_content_negotiation
-func NegotiateAccept(c *gin.Context, offers ...MIME) (string, error) {
+func NegotiateAccept(c *gin.Context, offers ...string) (string, error) {
if len(offers) == 0 {
return "", errors.New("no format offered")
}
diff --git a/internal/api/util/negotiate_test.go b/internal/api/util/negotiate_test.go
index a8b28b55f..d1b08695f 100644
--- a/internal/api/util/negotiate_test.go
+++ b/internal/api/util/negotiate_test.go
@@ -9,7 +9,7 @@ import (
"github.com/gin-gonic/gin"
)
-type testMIMES []MIME
+type testMIMES []string
func (tm testMIMES) String(t *testing.T) string {
t.Helper()
diff --git a/internal/api/util/response.go b/internal/api/util/response.go
new file mode 100644
index 000000000..e22bac545
--- /dev/null
+++ b/internal/api/util/response.go
@@ -0,0 +1,282 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package util
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "io"
+ "net/http"
+ "strconv"
+ "sync"
+
+ "codeberg.org/gruf/go-byteutil"
+ "codeberg.org/gruf/go-fastcopy"
+ "github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/log"
+)
+
+var (
+ // Pre-preared response body data.
+ StatusOKJSON = mustJSON(map[string]string{
+ "status": http.StatusText(http.StatusOK),
+ })
+ StatusAcceptedJSON = mustJSON(map[string]string{
+ "status": http.StatusText(http.StatusAccepted),
+ })
+ StatusInternalServerErrorJSON = mustJSON(map[string]string{
+ "status": http.StatusText(http.StatusInternalServerError),
+ })
+ EmptyJSONObject = mustJSON("{}")
+ EmptyJSONArray = mustJSON("[]")
+
+ // write buffer pool.
+ bufPool sync.Pool
+)
+
+// JSON calls EncodeJSONResponse() using gin.Context{}, with content-type = AppJSON,
+// This function handles the case of JSON unmarshal errors and pools read buffers.
+func JSON(c *gin.Context, code int, data any) {
+ EncodeJSONResponse(c.Writer, c.Request, code, AppJSON, data)
+}
+
+// JSON calls EncodeJSONResponse() using gin.Context{}, with given content-type.
+// This function handles the case of JSON unmarshal errors and pools read buffers.
+func JSONType(c *gin.Context, code int, contentType string, data any) {
+ EncodeJSONResponse(c.Writer, c.Request, code, contentType, data)
+}
+
+// Data calls WriteResponseBytes() using gin.Context{}, with given content-type.
+func Data(c *gin.Context, code int, contentType string, data []byte) {
+ WriteResponseBytes(c.Writer, c.Request, code, contentType, data)
+}
+
+// WriteResponse buffered streams 'data' as HTTP response
+// to ResponseWriter with given status code content-type.
+func WriteResponse(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ contentType string,
+ data io.Reader,
+ length int64,
+) {
+ if length < 0 {
+ // The worst-case scenario, length is not known so we need to
+ // read the entire thing into memory to know length & respond.
+ writeResponseUnknownLength(rw, r, statusCode, contentType, data)
+ return
+ }
+
+ // The best-case scenario, stream content of known length.
+ rw.Header().Set("Content-Type", contentType)
+ rw.Header().Set("Content-Length", strconv.FormatInt(length, 10))
+ rw.WriteHeader(statusCode)
+ if _, err := fastcopy.Copy(rw, data); err != nil {
+ log.Errorf(r.Context(), "error streaming: %v", err)
+ }
+}
+
+// WriteResponseBytes is functionally similar to
+// WriteResponse except that it takes prepared bytes.
+func WriteResponseBytes(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ contentType string,
+ data []byte,
+) {
+ rw.Header().Set("Content-Type", contentType)
+ rw.Header().Set("Content-Length", strconv.Itoa(len(data)))
+ rw.WriteHeader(statusCode)
+ if _, err := rw.Write(data); err != nil && err != io.EOF {
+ log.Errorf(r.Context(), "error writing: %v", err)
+ }
+}
+
+// EncodeJSONResponse encodes 'data' as JSON HTTP response
+// to ResponseWriter with given status code, content-type.
+func EncodeJSONResponse(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ contentType string,
+ data any,
+) {
+ // Acquire buffer.
+ buf := getBuf()
+
+ // Wrap buffer in JSON encoder.
+ enc := json.NewEncoder(buf)
+ enc.SetEscapeHTML(false)
+
+ // Encode JSON data into byte buffer.
+ if err := enc.Encode(data); err == nil {
+
+ // Drop new-line added by encoder.
+ if buf.B[len(buf.B)-1] == '\n' {
+ buf.B = buf.B[:len(buf.B)-1]
+ }
+
+ // Respond with the now-known
+ // size byte slice within buf.
+ WriteResponseBytes(rw, r,
+ statusCode,
+ contentType,
+ buf.B,
+ )
+ } else {
+ // This will always be a JSON error, we
+ // can't really add any more useful context.
+ log.Error(r.Context(), err)
+
+ // Any error returned here is unrecoverable,
+ // set Internal Server Error JSON response.
+ WriteResponseBytes(rw, r,
+ http.StatusInternalServerError,
+ AppJSON,
+ StatusInternalServerErrorJSON,
+ )
+ }
+
+ // Release.
+ putBuf(buf)
+}
+
+// EncodeJSONResponse encodes 'data' as XML HTTP response
+// to ResponseWriter with given status code, content-type.
+func EncodeXMLResponse(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ contentType string,
+ data any,
+) {
+ // Acquire buffer.
+ buf := getBuf()
+
+ // Write XML header string to buf.
+ buf.B = append(buf.B, xml.Header...)
+
+ // Wrap buffer in XML encoder.
+ enc := xml.NewEncoder(buf)
+
+ // Encode JSON data into byte buffer.
+ if err := enc.Encode(data); err == nil {
+
+ // Respond with the now-known
+ // size byte slice within buf.
+ WriteResponseBytes(rw, r,
+ statusCode,
+ contentType,
+ buf.B,
+ )
+ } else {
+ // This will always be an XML error, we
+ // can't really add any more useful context.
+ log.Error(r.Context(), err)
+
+ // Any error returned here is unrecoverable,
+ // set Internal Server Error JSON response.
+ WriteResponseBytes(rw, r,
+ http.StatusInternalServerError,
+ AppJSON,
+ StatusInternalServerErrorJSON,
+ )
+ }
+
+ // Release.
+ putBuf(buf)
+}
+
+// writeResponseUnknownLength handles reading data of unknown legnth
+// efficiently into memory, and passing on to WriteResponseBytes().
+func writeResponseUnknownLength(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ contentType string,
+ data io.Reader,
+) {
+ // Acquire buffer.
+ buf := getBuf()
+
+ // Read content into buffer.
+ _, err := buf.ReadFrom(data)
+
+ if err == nil {
+
+ // Respond with the now-known
+ // size byte slice within buf.
+ WriteResponseBytes(rw, r,
+ statusCode,
+ contentType,
+ buf.B,
+ )
+ } else {
+ // This will always be a reader error (non EOF),
+ // but that doesn't mean the writer is closed yet!
+ log.Errorf(r.Context(), "error reading: %v", err)
+
+ // Any error returned here is unrecoverable,
+ // set Internal Server Error JSON response.
+ WriteResponseBytes(rw, r,
+ http.StatusInternalServerError,
+ AppJSON,
+ StatusInternalServerErrorJSON,
+ )
+ }
+
+ // Release.
+ putBuf(buf)
+}
+
+func getBuf() *byteutil.Buffer {
+ // acquire buffer from pool.
+ buf, _ := bufPool.Get().(*byteutil.Buffer)
+
+ if buf == nil {
+ // alloc new buf if needed.
+ buf = new(byteutil.Buffer)
+ buf.B = make([]byte, 0, 4096)
+ }
+
+ return buf
+}
+
+func putBuf(buf *byteutil.Buffer) {
+ if cap(buf.B) >= int(^uint16(0)) {
+ // drop buffers of large size.
+ return
+ }
+
+ // ensure empty.
+ buf.Reset()
+
+ // release to pool.
+ bufPool.Put(buf)
+}
+
+// mustJSON converts data to JSON, else panicking.
+func mustJSON(data any) []byte {
+ b, err := json.Marshal(data)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
diff --git a/internal/api/wellknown/hostmeta/hostmetaget.go b/internal/api/wellknown/hostmeta/hostmetaget.go
index c74a2e246..131e2ac58 100644
--- a/internal/api/wellknown/hostmeta/hostmetaget.go
+++ b/internal/api/wellknown/hostmeta/hostmetaget.go
@@ -18,8 +18,6 @@
package hostmeta
import (
- "bytes"
- "encoding/xml"
"net/http"
"github.com/gin-gonic/gin"
@@ -52,21 +50,12 @@ func (m *Module) HostMetaGETHandler(c *gin.Context) {
hostMeta := m.processor.Fedi().HostMetaGet()
- // this setup with a separate buffer we encode into is used because
- // xml.Marshal does not emit xml.Header by itself
- var buf bytes.Buffer
-
- // Preallocate buffer of reasonable length.
- buf.Grow(len(xml.Header) + 64)
-
- // No need to check for error on write to buffer.
- _, _ = buf.WriteString(xml.Header)
-
- // Encode host-meta as XML to in-memory buffer.
- if err := xml.NewEncoder(&buf).Encode(hostMeta); err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- c.Data(http.StatusOK, HostMetaContentType, buf.Bytes())
+ // Encode XML HTTP response.
+ apiutil.EncodeXMLResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ HostMetaContentType,
+ hostMeta,
+ )
}
diff --git a/internal/api/wellknown/nodeinfo/nodeinfoget.go b/internal/api/wellknown/nodeinfo/nodeinfoget.go
index 3cbb29650..c458f131e 100644
--- a/internal/api/wellknown/nodeinfo/nodeinfoget.go
+++ b/internal/api/wellknown/nodeinfo/nodeinfoget.go
@@ -55,5 +55,12 @@ func (m *Module) NodeInfoWellKnownGETHandler(c *gin.Context) {
return
}
- c.JSON(http.StatusOK, resp)
+ // Encode JSON HTTP response.
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ apiutil.AppJSON,
+ resp,
+ )
}
diff --git a/internal/api/wellknown/webfinger/webfingerget.go b/internal/api/wellknown/webfinger/webfingerget.go
index 02f366ea6..74cb8fefe 100644
--- a/internal/api/wellknown/webfinger/webfingerget.go
+++ b/internal/api/wellknown/webfinger/webfingerget.go
@@ -18,7 +18,6 @@
package webfinger
import (
- "encoding/json"
"errors"
"fmt"
"net/http"
@@ -87,13 +86,12 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) {
return
}
- b, err := json.Marshal(resp)
- if err != nil {
- apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
- return
- }
-
- // Always return "application/jrd+json" regardless of negotiated
- // format. See https://www.rfc-editor.org/rfc/rfc7033#section-10.2
- c.Data(http.StatusOK, string(apiutil.AppJRDJSON), b)
+ // Encode JSON HTTP response.
+ apiutil.EncodeJSONResponse(
+ c.Writer,
+ c.Request,
+ http.StatusOK,
+ apiutil.AppJRDJSON,
+ resp,
+ )
}
diff --git a/internal/web/tag.go b/internal/web/tag.go
index d52de81d8..69591f114 100644
--- a/internal/web/tag.go
+++ b/internal/web/tag.go
@@ -45,7 +45,7 @@ func (m *Module) tagGETHandler(c *gin.Context) {
}
// We only serve text/html at this endpoint.
- if _, err := apiutil.NegotiateAccept(c, []apiutil.MIME{apiutil.TextHTML}...); err != nil {
+ if _, err := apiutil.NegotiateAccept(c, apiutil.TextHTML); err != nil {
apiutil.WebErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), instanceGet)
return
}