More tweaks

This commit is contained in:
Neil Alexander 2022-08-08 11:22:33 +01:00
parent 2d7402ed7d
commit 0801e93dfa
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
2 changed files with 170 additions and 305 deletions

View file

@ -1,6 +1,7 @@
package inthttp package inthttp
import ( import (
"context"
"encoding/json" "encoding/json"
"net/http" "net/http"
@ -13,333 +14,189 @@ import (
// AddRoutes adds the FederationInternalAPI handlers to the http.ServeMux. // AddRoutes adds the FederationInternalAPI handlers to the http.ServeMux.
// nolint:gocyclo // nolint:gocyclo
func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router) { func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router) {
httputil.NewInternalAPIServer( internalAPIMux.Handle(
"QueryJoinedHostServerNamesInRoom",
FederationAPIQueryJoinedHostServerNamesInRoomPath, FederationAPIQueryJoinedHostServerNamesInRoomPath,
intAPI.QueryJoinedHostServerNamesInRoom, httputil.MakeInternalRPCAPI("QueryJoinedHostServerNamesInRoom", intAPI.QueryJoinedHostServerNamesInRoom),
).Serve(internalAPIMux) )
httputil.NewInternalAPIServer( internalAPIMux.Handle(
"PerformInvite",
FederationAPIPerformInviteRequestPath, FederationAPIPerformInviteRequestPath,
intAPI.PerformInvite, httputil.MakeInternalRPCAPI("PerformInvite", intAPI.PerformInvite),
).Serve(internalAPIMux) )
httputil.NewInternalAPIServer( internalAPIMux.Handle(
"PerformLeave",
FederationAPIPerformLeaveRequestPath, FederationAPIPerformLeaveRequestPath,
intAPI.PerformLeave, httputil.MakeInternalRPCAPI("PerformLeave", intAPI.PerformLeave),
).Serve(internalAPIMux) )
httputil.NewInternalAPIServer( internalAPIMux.Handle(
"PerformDirectoryLookupRequest",
FederationAPIPerformDirectoryLookupRequestPath, FederationAPIPerformDirectoryLookupRequestPath,
intAPI.PerformDirectoryLookup, httputil.MakeInternalRPCAPI("PerformDirectoryLookupRequest", intAPI.PerformDirectoryLookup),
).Serve(internalAPIMux) )
httputil.NewInternalAPIServer( internalAPIMux.Handle(
"PerformBroadcastEDU",
FederationAPIPerformBroadcastEDUPath, FederationAPIPerformBroadcastEDUPath,
intAPI.PerformBroadcastEDU, httputil.MakeInternalRPCAPI("PerformJoinRequest", intAPI.PerformBroadcastEDU),
).Serve(internalAPIMux) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIPerformJoinRequestPath, FederationAPIPerformJoinRequestPath,
httputil.MakeInternalAPI("PerformJoinRequest", func(req *http.Request) util.JSONResponse { httputil.MakeInternalRPCAPI(
var request api.PerformJoinRequest "PerformJoinRequest",
var response api.PerformJoinResponse func(ctx context.Context, req *api.PerformJoinRequest, res *api.PerformJoinResponse) error {
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { intAPI.PerformJoin(ctx, req, res)
return util.MessageResponse(http.StatusBadRequest, err.Error()) return nil
} },
intAPI.PerformJoin(req.Context(), &request, &response) ),
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIGetUserDevicesPath, FederationAPIPerformJoinRequestPath,
httputil.MakeInternalAPI("GetUserDevices", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request getUserDevices "GetUserDevices",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *getUserDevices) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.GetUserDevices(ctx, req.S, req.UserID)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.GetUserDevices(req.Context(), request.S, request.UserID) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIClaimKeysPath, FederationAPIClaimKeysPath,
httputil.MakeInternalAPI("ClaimKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request claimKeys "ClaimKeys",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *claimKeys) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.ClaimKeys(ctx, req.S, req.OneTimeKeys)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.ClaimKeys(req.Context(), request.S, request.OneTimeKeys) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIQueryKeysPath, FederationAPIQueryKeysPath,
httputil.MakeInternalAPI("QueryKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request queryKeys "QueryKeys",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *queryKeys) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.QueryKeys(ctx, req.S, req.Keys)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.QueryKeys(req.Context(), request.S, request.Keys) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIBackfillPath, FederationAPIBackfillPath,
httputil.MakeInternalAPI("Backfill", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request backfill "Backfill",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *backfill) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.Backfill(ctx, req.S, req.RoomID, req.Limit, req.EventIDs)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.Backfill(req.Context(), request.S, request.RoomID, request.Limit, request.EventIDs) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPILookupStatePath, FederationAPILookupStatePath,
httputil.MakeInternalAPI("LookupState", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request lookupState "LookupState",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *lookupState) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.LookupState(ctx, req.S, req.RoomID, req.EventID, req.RoomVersion)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.LookupState(req.Context(), request.S, request.RoomID, request.EventID, request.RoomVersion) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPILookupStateIDsPath, FederationAPILookupStateIDsPath,
httputil.MakeInternalAPI("LookupStateIDs", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request lookupStateIDs "LookupStateIDs",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *lookupState) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.LookupState(ctx, req.S, req.RoomID, req.EventID, req.RoomVersion)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.LookupStateIDs(req.Context(), request.S, request.RoomID, request.EventID) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPILookupMissingEventsPath, FederationAPILookupMissingEventsPath,
httputil.MakeInternalAPI("LookupMissingEvents", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request lookupMissingEvents "LookupMissingEvents",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *lookupMissingEvents) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.LookupMissingEvents(ctx, req.S, req.RoomID, req.Missing, req.RoomVersion)
} for _, event := range res.Events {
res, err := intAPI.LookupMissingEvents(req.Context(), request.S, request.RoomID, request.Missing, request.RoomVersion) var js []byte
if err != nil { js, err = json.Marshal(event)
ferr, ok := err.(*api.FederationClientError) if err != nil {
if ok { req.Err = federationClientError(err)
request.Err = ferr return
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
} }
req.Res.Events = append(req.Res.Events, js)
} }
} req.Err = federationClientError(err)
for _, event := range res.Events { },
js, err := json.Marshal(event) ),
if err != nil {
return util.MessageResponse(http.StatusInternalServerError, err.Error())
}
request.Res.Events = append(request.Res.Events, js)
}
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIGetEventPath, FederationAPIGetEventPath,
httputil.MakeInternalAPI("GetEvent", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request getEvent "GetEvent",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *getEvent) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.GetEvent(ctx, req.S, req.EventID)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.GetEvent(req.Context(), request.S, request.EventID) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIGetEventAuthPath, FederationAPIGetEventAuthPath,
httputil.MakeInternalAPI("GetEventAuth", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request getEventAuth "GetEventAuth",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *getEventAuth) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.GetEventAuth(ctx, req.S, req.RoomVersion, req.RoomID, req.EventID)
} req.Res, req.Err = &res, federationClientError(err)
res, err := intAPI.GetEventAuth(req.Context(), request.S, request.RoomVersion, request.RoomID, request.EventID) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = &res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIQueryServerKeysPath, FederationAPIQueryServerKeysPath,
httputil.MakeInternalAPI("QueryServerKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalRPCAPI("QueryServerKeys", intAPI.QueryServerKeys),
var request api.QueryServerKeysRequest
var response api.QueryServerKeysResponse
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
if err := intAPI.QueryServerKeys(req.Context(), &request, &response); err != nil {
return util.ErrorResponse(err)
}
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPILookupServerKeysPath, FederationAPILookupServerKeysPath,
httputil.MakeInternalAPI("LookupServerKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request lookupServerKeys "LookupServerKeys",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *lookupServerKeys) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.LookupServerKeys(ctx, req.S, req.KeyRequests)
} req.ServerKeys, req.Err = res, federationClientError(err)
res, err := intAPI.LookupServerKeys(req.Context(), request.S, request.KeyRequests) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.ServerKeys = res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPIEventRelationshipsPath, FederationAPIEventRelationshipsPath,
httputil.MakeInternalAPI("MSC2836EventRelationships", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request eventRelationships "MSC2836EventRelationships",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *eventRelationships) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.MSC2836EventRelationships(ctx, req.S, req.Req, req.RoomVer)
} req.Res, req.Err = res, federationClientError(err)
res, err := intAPI.MSC2836EventRelationships(req.Context(), request.S, request.Req, request.RoomVer) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
internalAPIMux.Handle( internalAPIMux.Handle(
FederationAPISpacesSummaryPath, FederationAPISpacesSummaryPath,
httputil.MakeInternalAPI("MSC2946SpacesSummary", func(req *http.Request) util.JSONResponse { httputil.MakeInternalProxyAPI(
var request spacesReq "MSC2946SpacesSummary",
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { func(ctx context.Context, req *spacesReq) {
return util.MessageResponse(http.StatusBadRequest, err.Error()) res, err := intAPI.MSC2946Spaces(ctx, req.S, req.RoomID, req.SuggestedOnly)
} req.Res, req.Err = res, federationClientError(err)
res, err := intAPI.MSC2946Spaces(req.Context(), request.S, request.RoomID, request.SuggestedOnly) },
if err != nil { ),
ferr, ok := err.(*api.FederationClientError)
if ok {
request.Err = ferr
} else {
request.Err = &api.FederationClientError{
Err: err.Error(),
}
}
}
request.Res = res
return util.JSONResponse{Code: http.StatusOK, JSON: request}
}),
) )
// TODO: Look at this shape
internalAPIMux.Handle(FederationAPIQueryPublicKeyPath, internalAPIMux.Handle(FederationAPIQueryPublicKeyPath,
httputil.MakeInternalAPI("queryPublicKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalAPI("queryPublicKeys", func(req *http.Request) util.JSONResponse {
request := api.QueryPublicKeysRequest{} request := api.QueryPublicKeysRequest{}
@ -355,6 +212,8 @@ func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router) {
return util.JSONResponse{Code: http.StatusOK, JSON: &response} return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}), }),
) )
// TODO: Look at this shape
internalAPIMux.Handle(FederationAPIInputPublicKeyPath, internalAPIMux.Handle(FederationAPIInputPublicKeyPath,
httputil.MakeInternalAPI("inputPublicKeys", func(req *http.Request) util.JSONResponse { httputil.MakeInternalAPI("inputPublicKeys", func(req *http.Request) util.JSONResponse {
request := api.InputPublicKeysRequest{} request := api.InputPublicKeysRequest{}
@ -369,3 +228,16 @@ func AddRoutes(intAPI api.FederationInternalAPI, internalAPIMux *mux.Router) {
}), }),
) )
} }
func federationClientError(err error) *api.FederationClientError {
if err == nil {
return nil
}
if ferr, ok := err.(*api.FederationClientError); ok {
return ferr
} else {
return &api.FederationClientError{
Err: err.Error(),
}
}
}

View file

@ -19,11 +19,35 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/gorilla/mux"
"github.com/matrix-org/util" "github.com/matrix-org/util"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
) )
func MakeInternalRPCAPI[reqtype, restype any](metricsName string, f func(context.Context, *reqtype, *restype) error) http.Handler {
return MakeInternalAPI(metricsName, func(req *http.Request) util.JSONResponse {
var request reqtype
var response restype
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
if err := f(req.Context(), &request, &response); err != nil {
return util.ErrorResponse(err)
}
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
})
}
func MakeInternalProxyAPI[reqtype any](metricsName string, f func(context.Context, *reqtype)) http.Handler {
return MakeInternalAPI(metricsName, func(req *http.Request) util.JSONResponse {
var request reqtype
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.MessageResponse(http.StatusBadRequest, err.Error())
}
f(req.Context(), &request)
return util.JSONResponse{Code: http.StatusOK, JSON: &request}
})
}
type InternalAPIClient[req, res any] struct { type InternalAPIClient[req, res any] struct {
name string name string
url string url string
@ -44,34 +68,3 @@ func (h *InternalAPIClient[req, res]) Call(ctx context.Context, request *req, re
return PostJSON(ctx, span, h.client, h.url, request, response) return PostJSON(ctx, span, h.client, h.url, request, response)
} }
type InternalAPIServer[req, res any] struct {
name string
url string
f func(context.Context, *req, *res) error
}
func NewInternalAPIServer[req, res any](name, url string, f func(context.Context, *req, *res) error) *InternalAPIServer[req, res] {
return &InternalAPIServer[req, res]{
name: name,
url: url,
f: f,
}
}
func (h *InternalAPIServer[req, res]) Serve(mux *mux.Router) {
mux.Handle(
h.url,
MakeInternalAPI(h.name, func(httpReq *http.Request) util.JSONResponse {
var request req
var response res
if err := json.NewDecoder(httpReq.Body).Decode(&request); err != nil {
return util.ErrorResponse(err)
}
if err := h.f(httpReq.Context(), &request, &response); err != nil {
return util.ErrorResponse(err)
}
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
}),
)
}