mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] More consistent API error handling (#637)
* update templates * start reworking api error handling * update template * return AP status at web endpoint if negotiated * start making api error handling much more consistent * update account endpoints to new error handling * use new api error handling in admin endpoints * go fmt ./... * use api error logic in app * use generic error handling in auth * don't export generic error handler * don't defer clearing session * user nicer error handling on oidc callback handler * tidy up the sign in handler * tidy up the token handler * use nicer error handling in blocksget * auth emojis endpoint * fix up remaining api endpoints * fix whoopsie during login flow * regenerate swagger docs * change http error logging to debug
This commit is contained in:
@@ -23,8 +23,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// NodeInfoGETHandler swagger:operation GET /nodeinfo/2.0 nodeInfoGet
|
||||
@@ -45,27 +45,22 @@ import (
|
||||
// schema:
|
||||
// "$ref": "#/definitions/nodeinfo"
|
||||
func (m *Module) NodeInfoGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "NodeInfoGETHandler",
|
||||
"user-agent": c.Request.UserAgent(),
|
||||
})
|
||||
|
||||
if _, err := api.NegotiateAccept(c, api.JSONAcceptHeaders...); err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
ni, err := m.processor.GetNodeInfo(c.Request.Context(), c.Request)
|
||||
ni, errWithCode := m.processor.GetNodeInfo(c.Request.Context(), c.Request)
|
||||
if errWithCode != nil {
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := json.Marshal(ni)
|
||||
if err != nil {
|
||||
l.Debugf("error with get node info request: %s", err)
|
||||
c.JSON(err.Code(), err.Safe())
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, jsonErr := json.Marshal(ni)
|
||||
if jsonErr != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": jsonErr.Error()})
|
||||
}
|
||||
|
||||
c.Data(http.StatusOK, `application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"`, b)
|
||||
}
|
||||
|
@@ -22,8 +22,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// NodeInfoWellKnownGETHandler swagger:operation GET /.well-known/nodeinfo nodeInfoWellKnownGet
|
||||
@@ -45,19 +45,14 @@ import (
|
||||
// schema:
|
||||
// "$ref": "#/definitions/wellKnownResponse"
|
||||
func (m *Module) NodeInfoWellKnownGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "NodeInfoWellKnownGETHandler",
|
||||
})
|
||||
|
||||
if _, err := api.NegotiateAccept(c, api.JSONAcceptHeaders...); err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
niRel, err := m.processor.GetNodeInfoRel(c.Request.Context(), c.Request)
|
||||
if err != nil {
|
||||
l.Debugf("error with get node info rel request: %s", err)
|
||||
c.JSON(err.Code(), err.Safe())
|
||||
niRel, errWithCode := m.processor.GetNodeInfoRel(c.Request.Context(), c.Request)
|
||||
if errWithCode != nil {
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,48 +20,45 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// FollowersGETHandler returns a collection of URIs for followers of the target user, formatted so that other AP servers can understand it.
|
||||
func (m *Module) FollowersGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "FollowersGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the user's profile
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
|
||||
}
|
||||
|
||||
followers, errWithCode := m.processor.GetFediFollowers(ctx, requestedUsername, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediFollowers(transferContext(c), requestedUsername, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(followers)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,48 +20,45 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// FollowingGETHandler returns a collection of URIs for accounts that the target user follows, formatted so that other AP servers can understand it.
|
||||
func (m *Module) FollowingGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "FollowingGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the user's profile
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
|
||||
}
|
||||
|
||||
following, errWithCode := m.processor.GetFediFollowing(ctx, requestedUsername, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediFollowing(transferContext(c), requestedUsername, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(following)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -19,43 +19,33 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror" //nolint:typecheck
|
||||
)
|
||||
|
||||
// InboxPOSTHandler deals with incoming POST requests to an actor's inbox.
|
||||
// Eg., POST to https://example.org/users/whatever/inbox.
|
||||
func (m *Module) InboxPOSTHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "InboxPOSTHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := transferContext(c)
|
||||
|
||||
posted, err := m.processor.InboxPost(ctx, c.Writer, c.Request)
|
||||
if err != nil {
|
||||
if posted, err := m.processor.InboxPost(transferContext(c), c.Writer, c.Request); err != nil {
|
||||
if withCode, ok := err.(gtserror.WithCode); ok {
|
||||
l.Debugf("InboxPOSTHandler: %s", withCode.Error())
|
||||
c.JSON(withCode.Code(), withCode.Safe())
|
||||
return
|
||||
api.ErrorHandler(c, withCode, m.processor.InstanceGet)
|
||||
} else {
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
}
|
||||
l.Debugf("InboxPOSTHandler: error processing request: %s", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unable to process request"})
|
||||
return
|
||||
}
|
||||
|
||||
if !posted {
|
||||
l.Debugf("InboxPOSTHandler: request could not be handled as an AP request; headers were: %+v", c.Request.Header)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unable to process request"})
|
||||
} else if !posted {
|
||||
err := errors.New("unable to process request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
}
|
||||
}
|
||||
|
@@ -20,13 +20,15 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// OutboxGETHandler swagger:operation GET /users/{username}/outbox s2sOutboxGet
|
||||
@@ -80,23 +82,31 @@ import (
|
||||
// '404':
|
||||
// description: not found
|
||||
func (m *Module) OutboxGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "OutboxGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the user's profile
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
|
||||
}
|
||||
|
||||
var page bool
|
||||
if pageString := c.Query(PageKey); pageString != "" {
|
||||
i, err := strconv.ParseBool(pageString)
|
||||
if err != nil {
|
||||
l.Debugf("error parsing page string: %s", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse page query param"})
|
||||
err := fmt.Errorf("error parsing %s: %s", PageKey, err)
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
page = i
|
||||
@@ -114,27 +124,15 @@ func (m *Module) OutboxGETHandler(c *gin.Context) {
|
||||
maxID = maxIDString
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
|
||||
outbox, errWithCode := m.processor.GetFediOutbox(ctx, requestedUsername, page, maxID, minID, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediOutbox(transferContext(c), requestedUsername, page, maxID, minID, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(outbox)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,12 +20,13 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// PublicKeyGETHandler should be served at eg https://example.org/users/:username/main-key.
|
||||
@@ -34,38 +35,34 @@ import (
|
||||
// in the form of a vocab.ActivityStreamsPerson. The account will only contain the id,
|
||||
// public key, username, and type of the account.
|
||||
func (m *Module) PublicKeyGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "PublicKeyGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the user's profile
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
|
||||
}
|
||||
|
||||
user, errWithCode := m.processor.GetFediUser(ctx, requestedUsername, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediUser(transferContext(c), requestedUsername, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(user)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,13 +20,15 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// StatusRepliesGETHandler swagger:operation GET /users/{username}/statuses/{status}/replies s2sRepliesGet
|
||||
@@ -86,29 +88,39 @@ import (
|
||||
// '404':
|
||||
// description: not found
|
||||
func (m *Module) StatusRepliesGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "StatusRepliesGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
requestedStatusID := c.Param(StatusIDKey)
|
||||
// status IDs on our instance are always uppercase
|
||||
requestedStatusID := strings.ToUpper(c.Param(StatusIDKey))
|
||||
if requestedStatusID == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no status id specified in request"})
|
||||
err := errors.New("no status id specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the status
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID)
|
||||
}
|
||||
|
||||
var page bool
|
||||
if pageString := c.Query(PageKey); pageString != "" {
|
||||
i, err := strconv.ParseBool(pageString)
|
||||
if err != nil {
|
||||
l.Debugf("error parsing page string: %s", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse page query param"})
|
||||
err := fmt.Errorf("error parsing %s: %s", PageKey, err)
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
page = i
|
||||
@@ -119,8 +131,8 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) {
|
||||
if onlyOtherAccountsString != "" {
|
||||
i, err := strconv.ParseBool(onlyOtherAccountsString)
|
||||
if err != nil {
|
||||
l.Debugf("error parsing only_other_accounts string: %s", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse only_other_accounts query param"})
|
||||
err := fmt.Errorf("error parsing %s: %s", OnlyOtherAccountsKey, err)
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
onlyOtherAccounts = i
|
||||
@@ -132,27 +144,15 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) {
|
||||
minID = minIDString
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
|
||||
replies, errWithCode := m.processor.GetFediStatusReplies(ctx, requestedUsername, requestedStatusID, page, onlyOtherAccounts, minID, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediStatusReplies(transferContext(c), requestedUsername, requestedStatusID, page, onlyOtherAccounts, minID, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(replies)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,57 +20,53 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// StatusGETHandler serves the target status as an activitystreams NOTE so that other AP servers can parse it.
|
||||
func (m *Module) StatusGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "StatusGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
// status IDs on our instance are always uppercase
|
||||
requestedStatusID := strings.ToUpper(c.Param(StatusIDKey))
|
||||
if requestedStatusID == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no status id specified in request"})
|
||||
err := errors.New("no status id specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the status
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID)
|
||||
}
|
||||
|
||||
status, errWithCode := m.processor.GetFediStatus(ctx, requestedUsername, requestedStatusID, c.Request.URL)
|
||||
resp, errWithCode := m.processor.GetFediStatus(transferContext(c), requestedUsername, requestedStatusID, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(status)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -20,12 +20,13 @@ package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// UsersGETHandler should be served at https://example.org/users/:username.
|
||||
@@ -38,38 +39,34 @@ import (
|
||||
// And of course, the request should be refused if the account or server making the
|
||||
// request is blocked.
|
||||
func (m *Module) UsersGETHandler(c *gin.Context) {
|
||||
l := logrus.WithFields(logrus.Fields{
|
||||
"func": "UsersGETHandler",
|
||||
"url": c.Request.RequestURI,
|
||||
})
|
||||
|
||||
requestedUsername := c.Param(UsernameKey)
|
||||
// usernames on our instance are always lowercase
|
||||
requestedUsername := strings.ToLower(c.Param(UsernameKey))
|
||||
if requestedUsername == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"})
|
||||
err := errors.New("no username specified in request")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
format, err := api.NegotiateAccept(c, api.ActivityPubAcceptHeaders...)
|
||||
format, err := api.NegotiateAccept(c, api.HTMLOrActivityPubHeaders...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{"error": err.Error()})
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
l.Tracef("negotiated format: %s", format)
|
||||
|
||||
ctx := transferContext(c)
|
||||
if format == string(api.TextHTML) {
|
||||
// redirect to the user's profile
|
||||
c.Redirect(http.StatusSeeOther, "/@"+requestedUsername)
|
||||
}
|
||||
|
||||
user, errWithCode := m.processor.GetFediUser(ctx, requestedUsername, c.Request.URL) // GetFediUser handles auth as well
|
||||
resp, errWithCode := m.processor.GetFediUser(transferContext(c), requestedUsername, c.Request.URL)
|
||||
if errWithCode != nil {
|
||||
l.Info(errWithCode.Error())
|
||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
b, mErr := json.Marshal(user)
|
||||
if mErr != nil {
|
||||
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||
l.Error(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
b, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
)
|
||||
|
||||
@@ -105,10 +106,9 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) {
|
||||
ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeyVerifier, verifier)
|
||||
}
|
||||
|
||||
resp, err := m.processor.GetWebfingerAccount(ctx, username)
|
||||
if err != nil {
|
||||
l.Debugf("aborting request with an error: %s", err.Error())
|
||||
c.JSON(err.Code(), gin.H{"error": err.Safe()})
|
||||
resp, errWithCode := m.processor.GetWebfingerAccount(ctx, username)
|
||||
if errWithCode != nil {
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user