Introduce "Router" struct

This commit is contained in:
Till Faelligen 2023-03-16 12:26:38 +01:00
parent d0a764a083
commit a5aa69add5
No known key found for this signature in database
GPG key ID: ACCDC9606D472758
22 changed files with 152 additions and 139 deletions

View file

@ -213,12 +213,12 @@ func startup() {
monolith.AddAllPublicRoutes(base, caches) monolith.AddAllPublicRoutes(base, caches)
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.Routers.Client)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.Routers.Media)
p2pRouter := pSessions.Protocol("matrix").HTTP().Mux() p2pRouter := pSessions.Protocol("matrix").HTTP().Mux()
p2pRouter.Handle(httputil.PublicFederationPathPrefix, base.PublicFederationAPIMux) p2pRouter.Handle(httputil.PublicFederationPathPrefix, base.Routers.Federation)
p2pRouter.Handle(httputil.PublicMediaPathPrefix, base.PublicMediaAPIMux) p2pRouter.Handle(httputil.PublicMediaPathPrefix, base.Routers.Media)
// Expose the matrix APIs via fetch - for local traffic // Expose the matrix APIs via fetch - for local traffic
go func() { go func() {

View file

@ -192,14 +192,14 @@ func (m *DendriteMonolith) Start() {
monolith.AddAllPublicRoutes(base, caches) monolith.AddAllPublicRoutes(base, caches)
httpRouter := mux.NewRouter() httpRouter := mux.NewRouter()
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.Routers.Client)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.Routers.Media)
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux) httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.Routers.DendriteAdmin)
httpRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(base.SynapseAdminMux) httpRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(base.Routers.SynapseAdmin)
yggRouter := mux.NewRouter() yggRouter := mux.NewRouter()
yggRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.PublicFederationAPIMux) yggRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.Routers.Federation)
yggRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) yggRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.Routers.Media)
// Build both ends of a HTTP multiplex. // Build both ends of a HTTP multiplex.
m.httpServer = &http.Server{ m.httpServer = &http.Server{

View file

@ -73,7 +73,7 @@ func TestAdminResetPassword(t *testing.T) {
"password": password, "password": password,
})) }))
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(rec, req) base.Routers.Client.ServeHTTP(rec, req)
if rec.Code != http.StatusOK { if rec.Code != http.StatusOK {
t.Fatalf("failed to login: %s", rec.Body.String()) t.Fatalf("failed to login: %s", rec.Body.String())
} }
@ -126,7 +126,7 @@ func TestAdminResetPassword(t *testing.T) {
} }
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
base.DendriteAdminMux.ServeHTTP(rec, req) base.Routers.DendriteAdmin.ServeHTTP(rec, req)
t.Logf("%s", rec.Body.String()) t.Logf("%s", rec.Body.String())
if tc.wantOK && rec.Code != http.StatusOK { if tc.wantOK && rec.Code != http.StatusOK {
t.Fatalf("expected http status %d, got %d: %s", http.StatusOK, rec.Code, rec.Body.String()) t.Fatalf("expected http status %d, got %d: %s", http.StatusOK, rec.Code, rec.Body.String())
@ -196,7 +196,7 @@ func TestPurgeRoom(t *testing.T) {
"password": password, "password": password,
})) }))
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(rec, req) base.Routers.Client.ServeHTTP(rec, req)
if rec.Code != http.StatusOK { if rec.Code != http.StatusOK {
t.Fatalf("failed to login: %s", rec.Body.String()) t.Fatalf("failed to login: %s", rec.Body.String())
} }
@ -221,7 +221,7 @@ func TestPurgeRoom(t *testing.T) {
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin]) req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin])
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
base.DendriteAdminMux.ServeHTTP(rec, req) base.Routers.DendriteAdmin.ServeHTTP(rec, req)
t.Logf("%s", rec.Body.String()) t.Logf("%s", rec.Body.String())
if tc.wantOK && rec.Code != http.StatusOK { if tc.wantOK && rec.Code != http.StatusOK {
t.Fatalf("expected http status %d, got %d: %s", http.StatusOK, rec.Code, rec.Body.String()) t.Fatalf("expected http status %d, got %d: %s", http.StatusOK, rec.Code, rec.Body.String())

View file

@ -116,7 +116,7 @@ func TestLogin(t *testing.T) {
"password": password, "password": password,
})) }))
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(rec, req) base.Routers.Client.ServeHTTP(rec, req)
if tc.wantOK && rec.Code != http.StatusOK { if tc.wantOK && rec.Code != http.StatusOK {
t.Fatalf("failed to login: %s", rec.Body.String()) t.Fatalf("failed to login: %s", rec.Body.String())
} }

View file

@ -63,10 +63,10 @@ func Setup(
extRoomsProvider api.ExtraPublicRoomsProvider, extRoomsProvider api.ExtraPublicRoomsProvider,
mscCfg *config.MSCs, natsClient *nats.Conn, mscCfg *config.MSCs, natsClient *nats.Conn,
) { ) {
publicAPIMux := base.PublicClientAPIMux publicAPIMux := base.Routers.Client
wkMux := base.PublicWellKnownAPIMux wkMux := base.Routers.WellKnown
synapseAdminRouter := base.SynapseAdminMux synapseAdminRouter := base.Routers.SynapseAdmin
dendriteAdminRouter := base.DendriteAdminMux dendriteAdminRouter := base.Routers.DendriteAdmin
if base.EnableMetrics { if base.EnableMetrics {
prometheus.MustRegister(amtRegUsers, sendEventDuration) prometheus.MustRegister(amtRegUsers, sendEventDuration)

View file

@ -248,10 +248,10 @@ func (p *P2PMonolith) Addr() string {
func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) { func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider, enableWebsockets bool) {
p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath() p.httpMux = mux.NewRouter().SkipClean(true).UseEncodedPath()
p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.PublicClientAPIMux) p.httpMux.PathPrefix(httputil.PublicClientPathPrefix).Handler(p.BaseDendrite.Routers.Client)
p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux) p.httpMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.Routers.Media)
p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.DendriteAdminMux) p.httpMux.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(p.BaseDendrite.Routers.DendriteAdmin)
p.httpMux.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(p.BaseDendrite.SynapseAdminMux) p.httpMux.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(p.BaseDendrite.Routers.SynapseAdmin)
if enableWebsockets { if enableWebsockets {
wsUpgrader := websocket.Upgrader{ wsUpgrader := websocket.Upgrader{
@ -284,8 +284,8 @@ func (p *P2PMonolith) setupHttpServers(userProvider *users.PineconeUserProvider,
p.pineconeMux = mux.NewRouter().SkipClean(true).UseEncodedPath() p.pineconeMux = mux.NewRouter().SkipClean(true).UseEncodedPath()
p.pineconeMux.PathPrefix(users.PublicURL).HandlerFunc(userProvider.FederatedUserProfiles) p.pineconeMux.PathPrefix(users.PublicURL).HandlerFunc(userProvider.FederatedUserProfiles)
p.pineconeMux.PathPrefix(httputil.PublicFederationPathPrefix).Handler(p.BaseDendrite.PublicFederationAPIMux) p.pineconeMux.PathPrefix(httputil.PublicFederationPathPrefix).Handler(p.BaseDendrite.Routers.Federation)
p.pineconeMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.PublicMediaAPIMux) p.pineconeMux.PathPrefix(httputil.PublicMediaPathPrefix).Handler(p.BaseDendrite.Routers.Media)
pHTTP := p.Sessions.Protocol(SessionProtocol).HTTP() pHTTP := p.Sessions.Protocol(SessionProtocol).HTTP()
pHTTP.Mux().Handle(users.PublicURL, p.pineconeMux) pHTTP.Mux().Handle(users.PublicURL, p.pineconeMux)

View file

@ -190,15 +190,15 @@ func main() {
} }
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.PublicClientAPIMux) httpRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(base.Routers.Client)
httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) httpRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.Routers.Media)
httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.DendriteAdminMux) httpRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(base.Routers.DendriteAdmin)
httpRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(base.SynapseAdminMux) httpRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(base.Routers.SynapseAdmin)
embed.Embed(httpRouter, *instancePort, "Yggdrasil Demo") embed.Embed(httpRouter, *instancePort, "Yggdrasil Demo")
yggRouter := mux.NewRouter().SkipClean(true).UseEncodedPath() yggRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
yggRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.PublicFederationAPIMux) yggRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(base.Routers.Federation)
yggRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.PublicMediaAPIMux) yggRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(base.Routers.Media)
// Build both ends of a HTTP multiplex. // Build both ends of a HTTP multiplex.
httpServer := &http.Server{ httpServer := &http.Server{

View file

@ -280,7 +280,7 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) {
// TODO: This is pretty fragile, as if anything calls anything on these nils this test will break. // TODO: This is pretty fragile, as if anything calls anything on these nils this test will break.
// Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing. // Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing.
federationapi.AddPublicRoutes(b, nil, nil, keyRing, nil, &internal.FederationInternalAPI{}, nil) federationapi.AddPublicRoutes(b, nil, nil, keyRing, nil, &internal.FederationInternalAPI{}, nil)
baseURL, cancel := test.ListenAndServe(t, b.PublicFederationAPIMux, true) baseURL, cancel := test.ListenAndServe(t, b.Routers.Federation, true)
defer cancel() defer cancel()
serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://")) serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://"))

View file

@ -50,7 +50,7 @@ func TestHandleQueryProfile(t *testing.T) {
defer close() defer close()
fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath() fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath()
base.PublicFederationAPIMux = fedMux base.Routers.Federation = fedMux
base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin
base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false
fedClient := fakeFedClient{} fedClient := fakeFedClient{}

View file

@ -50,7 +50,7 @@ func TestHandleQueryDirectory(t *testing.T) {
defer close() defer close()
fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath() fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath()
base.PublicFederationAPIMux = fedMux base.Routers.Federation = fedMux
base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin
base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false
fedClient := fakeFedClient{} fedClient := fakeFedClient{}

View file

@ -65,9 +65,9 @@ func Setup(
servers federationAPI.ServersInRoomProvider, servers federationAPI.ServersInRoomProvider,
producer *producers.SyncAPIProducer, producer *producers.SyncAPIProducer,
) { ) {
fedMux := base.PublicFederationAPIMux fedMux := base.Routers.Federation
keyMux := base.PublicKeyAPIMux keyMux := base.Routers.Keys
wkMux := base.PublicWellKnownAPIMux wkMux := base.Routers.WellKnown
cfg := &base.Cfg.FederationAPI cfg := &base.Cfg.FederationAPI
if base.EnableMetrics { if base.EnableMetrics {

View file

@ -48,7 +48,7 @@ func TestHandleSend(t *testing.T) {
defer close() defer close()
fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath() fedMux := mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath()
base.PublicFederationAPIMux = fedMux base.Routers.Federation = fedMux
base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin base.Cfg.FederationAPI.Matrix.SigningIdentity.ServerName = testOrigin
base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false base.Cfg.FederationAPI.Matrix.Metrics.Enabled = false
fedapi := fedAPI.NewInternalAPI(base, nil, nil, nil, nil, true) fedapi := fedAPI.NewInternalAPI(base, nil, nil, nil, nil, true)

View file

@ -15,7 +15,11 @@
package httputil package httputil
import ( import (
"fmt"
"net/http"
"net/url" "net/url"
"github.com/gorilla/mux"
) )
// URLDecodeMapValues is a function that iterates through each of the items in a // URLDecodeMapValues is a function that iterates through each of the items in a
@ -33,3 +37,58 @@ func URLDecodeMapValues(vmap map[string]string) (map[string]string, error) {
return decoded, nil return decoded, nil
} }
type Routers struct {
Client *mux.Router
Federation *mux.Router
Keys *mux.Router
Media *mux.Router
WellKnown *mux.Router
Static *mux.Router
DendriteAdmin *mux.Router
SynapseAdmin *mux.Router
}
func NewRouters() Routers {
r := Routers{
Client: mux.NewRouter().SkipClean(true).PathPrefix(PublicClientPathPrefix).Subrouter().UseEncodedPath(),
Federation: mux.NewRouter().SkipClean(true).PathPrefix(PublicFederationPathPrefix).Subrouter().UseEncodedPath(),
Keys: mux.NewRouter().SkipClean(true).PathPrefix(PublicKeyPathPrefix).Subrouter().UseEncodedPath(),
Media: mux.NewRouter().SkipClean(true).PathPrefix(PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
WellKnown: mux.NewRouter().SkipClean(true).PathPrefix(PublicWellKnownPrefix).Subrouter().UseEncodedPath(),
Static: mux.NewRouter().SkipClean(true).PathPrefix(PublicStaticPath).Subrouter().UseEncodedPath(),
DendriteAdmin: mux.NewRouter().SkipClean(true).PathPrefix(DendriteAdminPathPrefix).Subrouter().UseEncodedPath(),
SynapseAdmin: mux.NewRouter().SkipClean(true).PathPrefix(SynapseAdminPathPrefix).Subrouter().UseEncodedPath(),
}
r.configureHTTPErrors()
return r
}
func (r *Routers) configureHTTPErrors() {
notAllowedHandler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
_, _ = w.Write([]byte(fmt.Sprintf("405 %s not allowed on this endpoint", r.Method)))
}
clientNotFoundHandler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"errcode":"M_UNRECOGNIZED","error":"Unrecognized request"}`)) // nolint:misspell
}
notFoundCORSHandler := WrapHandlerInCORS(http.NotFoundHandler())
notAllowedCORSHandler := WrapHandlerInCORS(http.HandlerFunc(notAllowedHandler))
for _, router := range []*mux.Router{
r.Media, r.DendriteAdmin,
r.SynapseAdmin, r.WellKnown,
r.Static,
} {
router.NotFoundHandler = notFoundCORSHandler
router.MethodNotAllowedHandler = notAllowedCORSHandler
}
// Special case so that we don't upset clients on the CS API.
r.Client.NotFoundHandler = http.HandlerFunc(clientNotFoundHandler)
r.Client.MethodNotAllowedHandler = http.HandlerFunc(clientNotFoundHandler)
}

View file

@ -38,6 +38,6 @@ func AddPublicRoutes(
} }
routing.Setup( routing.Setup(
base.PublicMediaAPIMux, cfg, rateCfg, mediaDB, userAPI, client, base.Routers.Media, cfg, rateCfg, mediaDB, userAPI, client,
) )
} }

View file

@ -42,7 +42,7 @@ func AddPublicRoutes(
} }
routing.Setup( routing.Setup(
base.PublicFederationAPIMux, base.Routers.Federation,
fedCfg, fedCfg,
relay, relay,
keyRing, keyRing,

View file

@ -147,7 +147,7 @@ func TestCreateRelayPublicRoutes(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicFederationAPIMux.ServeHTTP(w, tc.req) base.Routers.Federation.ServeHTTP(w, tc.req)
if w.Code != tc.wantCode { if w.Code != tc.wantCode {
t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode) t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode)
} }
@ -187,7 +187,7 @@ func TestDisableRelayPublicRoutes(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicFederationAPIMux.ServeHTTP(w, tc.req) base.Routers.Federation.ServeHTTP(w, tc.req)
if w.Code != tc.wantCode { if w.Code != tc.wantCode {
t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode) t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode)
} }

View file

@ -65,14 +65,7 @@ var staticContent embed.FS
type BaseDendrite struct { type BaseDendrite struct {
*process.ProcessContext *process.ProcessContext
tracerCloser io.Closer tracerCloser io.Closer
PublicClientAPIMux *mux.Router Routers httputil.Routers
PublicFederationAPIMux *mux.Router
PublicKeyAPIMux *mux.Router
PublicMediaAPIMux *mux.Router
PublicWellKnownAPIMux *mux.Router
PublicStaticMux *mux.Router
DendriteAdminMux *mux.Router
SynapseAdminMux *mux.Router
NATS *jetstream.NATSInstance NATS *jetstream.NATSInstance
Cfg *config.Dendrite Cfg *config.Dendrite
DNSCache *gomatrixserverlib.DNSCache DNSCache *gomatrixserverlib.DNSCache
@ -186,14 +179,7 @@ func NewBaseDendrite(cfg *config.Dendrite, options ...BaseDendriteOptions) *Base
tracerCloser: closer, tracerCloser: closer,
Cfg: cfg, Cfg: cfg,
DNSCache: dnsCache, DNSCache: dnsCache,
PublicClientAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicClientPathPrefix).Subrouter().UseEncodedPath(), Routers: httputil.NewRouters(),
PublicFederationAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicFederationPathPrefix).Subrouter().UseEncodedPath(),
PublicKeyAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicKeyPathPrefix).Subrouter().UseEncodedPath(),
PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
PublicWellKnownAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicWellKnownPrefix).Subrouter().UseEncodedPath(),
PublicStaticMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicStaticPath).Subrouter().UseEncodedPath(),
DendriteAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.DendriteAdminPathPrefix).Subrouter().UseEncodedPath(),
SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.SynapseAdminPathPrefix).Subrouter().UseEncodedPath(),
NATS: &jetstream.NATSInstance{}, NATS: &jetstream.NATSInstance{},
Database: db, // set if monolith with global connection pool only Database: db, // set if monolith with global connection pool only
DatabaseWriter: writer, // set if monolith with global connection pool only DatabaseWriter: writer, // set if monolith with global connection pool only
@ -275,40 +261,11 @@ func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationCli
return client return client
} }
func (b *BaseDendrite) configureHTTPErrors() {
notAllowedHandler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
_, _ = w.Write([]byte(fmt.Sprintf("405 %s not allowed on this endpoint", r.Method)))
}
clientNotFoundHandler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"errcode":"M_UNRECOGNIZED","error":"Unrecognized request"}`)) // nolint:misspell
}
notFoundCORSHandler := httputil.WrapHandlerInCORS(http.NotFoundHandler())
notAllowedCORSHandler := httputil.WrapHandlerInCORS(http.HandlerFunc(notAllowedHandler))
for _, router := range []*mux.Router{
b.PublicMediaAPIMux, b.DendriteAdminMux,
b.SynapseAdminMux, b.PublicWellKnownAPIMux,
b.PublicStaticMux,
} {
router.NotFoundHandler = notFoundCORSHandler
router.MethodNotAllowedHandler = notAllowedCORSHandler
}
// Special case so that we don't upset clients on the CS API.
b.PublicClientAPIMux.NotFoundHandler = http.HandlerFunc(clientNotFoundHandler)
b.PublicClientAPIMux.MethodNotAllowedHandler = http.HandlerFunc(clientNotFoundHandler)
}
func (b *BaseDendrite) ConfigureAdminEndpoints() { func (b *BaseDendrite) ConfigureAdminEndpoints() {
b.DendriteAdminMux.HandleFunc("/monitor/up", func(w http.ResponseWriter, r *http.Request) { b.Routers.DendriteAdmin.HandleFunc("/monitor/up", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200) w.WriteHeader(200)
}) })
b.DendriteAdminMux.HandleFunc("/monitor/health", func(w http.ResponseWriter, r *http.Request) { b.Routers.DendriteAdmin.HandleFunc("/monitor/health", func(w http.ResponseWriter, r *http.Request) {
if isDegraded, reasons := b.ProcessContext.IsDegraded(); isDegraded { if isDegraded, reasons := b.ProcessContext.IsDegraded(); isDegraded {
w.WriteHeader(503) w.WriteHeader(503)
_ = json.NewEncoder(w).Encode(struct { _ = json.NewEncoder(w).Encode(struct {
@ -343,8 +300,6 @@ func (b *BaseDendrite) SetupAndServeHTTP(
}, },
} }
b.configureHTTPErrors()
//Redirect for Landing Page //Redirect for Landing Page
externalRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { externalRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound) http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound)
@ -365,36 +320,36 @@ func (b *BaseDendrite) SetupAndServeHTTP(
logrus.WithError(err).Fatal("failed to execute landing page template") logrus.WithError(err).Fatal("failed to execute landing page template")
} }
b.PublicStaticMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { b.Routers.Static.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(landingPage.Bytes()) _, _ = w.Write(landingPage.Bytes())
}) })
var clientHandler http.Handler var clientHandler http.Handler
clientHandler = b.PublicClientAPIMux clientHandler = b.Routers.Client
if b.Cfg.Global.Sentry.Enabled { if b.Cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{ sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true, Repanic: true,
}) })
clientHandler = sentryHandler.Handle(b.PublicClientAPIMux) clientHandler = sentryHandler.Handle(b.Routers.Client)
} }
var federationHandler http.Handler var federationHandler http.Handler
federationHandler = b.PublicFederationAPIMux federationHandler = b.Routers.Federation
if b.Cfg.Global.Sentry.Enabled { if b.Cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{ sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true, Repanic: true,
}) })
federationHandler = sentryHandler.Handle(b.PublicFederationAPIMux) federationHandler = sentryHandler.Handle(b.Routers.Federation)
} }
externalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(b.DendriteAdminMux) externalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(b.Routers.DendriteAdmin)
externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler) externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler)
if !b.Cfg.Global.DisableFederation { if !b.Cfg.Global.DisableFederation {
externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux) externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.Routers.Keys)
externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(federationHandler) externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(federationHandler)
} }
externalRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(b.SynapseAdminMux) externalRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(b.Routers.SynapseAdmin)
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.PublicMediaAPIMux) externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.Routers.Media)
externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(b.PublicWellKnownAPIMux) externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(b.Routers.WellKnown)
externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(b.PublicStaticMux) externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(b.Routers.Static)
b.startupLock.Unlock() b.startupLock.Unlock()

View file

@ -125,11 +125,11 @@ func Enable(
} }
}) })
base.PublicClientAPIMux.Handle("/unstable/event_relationships", base.Routers.Client.Handle("/unstable/event_relationships",
httputil.MakeAuthAPI("eventRelationships", userAPI, eventRelationshipHandler(db, rsAPI, fsAPI)), httputil.MakeAuthAPI("eventRelationships", userAPI, eventRelationshipHandler(db, rsAPI, fsAPI)),
).Methods(http.MethodPost, http.MethodOptions) ).Methods(http.MethodPost, http.MethodOptions)
base.PublicFederationAPIMux.Handle("/unstable/event_relationships", httputil.MakeExternalAPI( base.Routers.Federation.Handle("/unstable/event_relationships", httputil.MakeExternalAPI(
"msc2836_event_relationships", func(req *http.Request) util.JSONResponse { "msc2836_event_relationships", func(req *http.Request) util.JSONResponse {
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), base.Cfg.Global.ServerName, base.Cfg.Global.IsLocalServerName, keyRing, req, time.Now(), base.Cfg.Global.ServerName, base.Cfg.Global.IsLocalServerName, keyRing,

View file

@ -556,8 +556,7 @@ func injectEvents(t *testing.T, userAPI userapi.UserInternalAPI, rsAPI roomserve
cfg.MSCs.MSCs = []string{"msc2836"} cfg.MSCs.MSCs = []string{"msc2836"}
base := &base.BaseDendrite{ base := &base.BaseDendrite{
Cfg: cfg, Cfg: cfg,
PublicClientAPIMux: mux.NewRouter().PathPrefix(httputil.PublicClientPathPrefix).Subrouter(), Routers: httputil.NewRouters(),
PublicFederationAPIMux: mux.NewRouter().PathPrefix(httputil.PublicFederationPathPrefix).Subrouter(),
} }
err := msc2836.Enable(base, rsAPI, nil, userAPI, nil) err := msc2836.Enable(base, rsAPI, nil, userAPI, nil)
@ -567,7 +566,7 @@ func injectEvents(t *testing.T, userAPI userapi.UserInternalAPI, rsAPI roomserve
for _, ev := range events { for _, ev := range events {
hooks.Run(hooks.KindNewEventPersisted, ev) hooks.Run(hooks.KindNewEventPersisted, ev)
} }
return base.PublicClientAPIMux return base.Routers.Client
} }
type fledglingEvent struct { type fledglingEvent struct {

View file

@ -58,8 +58,8 @@ func Enable(
fsAPI fs.FederationInternalAPI, keyRing gomatrixserverlib.JSONVerifier, cache caching.SpaceSummaryRoomsCache, fsAPI fs.FederationInternalAPI, keyRing gomatrixserverlib.JSONVerifier, cache caching.SpaceSummaryRoomsCache,
) error { ) error {
clientAPI := httputil.MakeAuthAPI("spaces", userAPI, spacesHandler(rsAPI, fsAPI, cache, base.Cfg.Global.ServerName), httputil.WithAllowGuests()) clientAPI := httputil.MakeAuthAPI("spaces", userAPI, spacesHandler(rsAPI, fsAPI, cache, base.Cfg.Global.ServerName), httputil.WithAllowGuests())
base.PublicClientAPIMux.Handle("/v1/rooms/{roomID}/hierarchy", clientAPI).Methods(http.MethodGet, http.MethodOptions) base.Routers.Client.Handle("/v1/rooms/{roomID}/hierarchy", clientAPI).Methods(http.MethodGet, http.MethodOptions)
base.PublicClientAPIMux.Handle("/unstable/org.matrix.msc2946/rooms/{roomID}/hierarchy", clientAPI).Methods(http.MethodGet, http.MethodOptions) base.Routers.Client.Handle("/unstable/org.matrix.msc2946/rooms/{roomID}/hierarchy", clientAPI).Methods(http.MethodGet, http.MethodOptions)
fedAPI := httputil.MakeExternalAPI( fedAPI := httputil.MakeExternalAPI(
"msc2946_fed_spaces", func(req *http.Request) util.JSONResponse { "msc2946_fed_spaces", func(req *http.Request) util.JSONResponse {
@ -78,8 +78,8 @@ func Enable(
return federatedSpacesHandler(req.Context(), fedReq, roomID, cache, rsAPI, fsAPI, base.Cfg.Global.ServerName) return federatedSpacesHandler(req.Context(), fedReq, roomID, cache, rsAPI, fsAPI, base.Cfg.Global.ServerName)
}, },
) )
base.PublicFederationAPIMux.Handle("/unstable/org.matrix.msc2946/hierarchy/{roomID}", fedAPI).Methods(http.MethodGet) base.Routers.Federation.Handle("/unstable/org.matrix.msc2946/hierarchy/{roomID}", fedAPI).Methods(http.MethodGet)
base.PublicFederationAPIMux.Handle("/v1/hierarchy/{roomID}", fedAPI).Methods(http.MethodGet) base.Routers.Federation.Handle("/v1/hierarchy/{roomID}", fedAPI).Methods(http.MethodGet)
return nil return nil
} }

View file

@ -140,7 +140,7 @@ func AddPublicRoutes(
} }
routing.Setup( routing.Setup(
base.PublicClientAPIMux, requestPool, syncDB, userAPI, base.Routers.Client, requestPool, syncDB, userAPI,
rsAPI, cfg, caches, fts, rsAPI, cfg, caches, fts,
) )
} }

View file

@ -164,7 +164,7 @@ func testSyncAccessTokens(t *testing.T, dbType test.DBType) {
for _, tc := range testCases { for _, tc := range testCases {
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, tc.req) base.Routers.Client.ServeHTTP(w, tc.req)
if w.Code != tc.wantCode { if w.Code != tc.wantCode {
t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode) t.Fatalf("%s: got HTTP %d want %d", tc.name, w.Code, tc.wantCode)
} }
@ -226,7 +226,7 @@ func testSyncAPICreateRoomSyncEarly(t *testing.T, dbType test.DBType) {
testrig.MustPublishMsgs(t, jsctx, msg) testrig.MustPublishMsgs(t, jsctx, msg)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": alice.AccessToken, "access_token": alice.AccessToken,
"timeout": "0", "timeout": "0",
}))) })))
@ -256,7 +256,7 @@ func testSyncAPICreateRoomSyncEarly(t *testing.T, dbType test.DBType) {
t.Logf("waited for events to be consumed; syncing with %v", sinceTokens) t.Logf("waited for events to be consumed; syncing with %v", sinceTokens)
for i, since := range sinceTokens { for i, since := range sinceTokens {
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": alice.AccessToken, "access_token": alice.AccessToken,
"timeout": "0", "timeout": "0",
"since": since, "since": since,
@ -308,7 +308,7 @@ func testSyncAPIUpdatePresenceImmediately(t *testing.T, dbType test.DBType) {
caches := caching.NewRistrettoCache(base.Cfg.Global.Cache.EstimatedMaxSize, base.Cfg.Global.Cache.MaxAge, caching.DisableMetrics) caches := caching.NewRistrettoCache(base.Cfg.Global.Cache.EstimatedMaxSize, base.Cfg.Global.Cache.MaxAge, caching.DisableMetrics)
AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, caches) AddPublicRoutes(base, &syncUserAPI{accounts: []userapi.Device{alice}}, &syncRoomserverAPI{}, caches)
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": alice.AccessToken, "access_token": alice.AccessToken,
"timeout": "0", "timeout": "0",
"set_presence": "online", "set_presence": "online",
@ -448,7 +448,7 @@ func testHistoryVisibility(t *testing.T, dbType test.DBType) {
// There is only one event, we expect only to be able to see this, if the room is world_readable // There is only one event, we expect only to be able to see this, if the room is world_readable
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
"access_token": bobDev.AccessToken, "access_token": bobDev.AccessToken,
"dir": "b", "dir": "b",
"filter": `{"lazy_load_members":true}`, // check that lazy loading doesn't break history visibility "filter": `{"lazy_load_members":true}`, // check that lazy loading doesn't break history visibility
@ -488,7 +488,7 @@ func testHistoryVisibility(t *testing.T, dbType test.DBType) {
// Verify the messages after/before invite are visible or not // Verify the messages after/before invite are visible or not
w = httptest.NewRecorder() w = httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/messages", room.ID), test.WithQueryParams(map[string]string{
"access_token": bobDev.AccessToken, "access_token": bobDev.AccessToken,
"dir": "b", "dir": "b",
}))) })))
@ -753,7 +753,7 @@ func TestGetMembership(t *testing.T) {
} }
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, tc.request(t, room)) base.Routers.Client.ServeHTTP(w, tc.request(t, room))
if w.Code != 200 && tc.wantOK { if w.Code != 200 && tc.wantOK {
t.Logf("%s", w.Body.String()) t.Logf("%s", w.Body.String())
t.Fatalf("got HTTP %d want %d", w.Code, 200) t.Fatalf("got HTTP %d want %d", w.Code, 200)
@ -890,7 +890,7 @@ func testSendToDevice(t *testing.T, dbType test.DBType) {
// Execute a /sync request, recording the response // Execute a /sync request, recording the response
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": alice.AccessToken, "access_token": alice.AccessToken,
"since": tc.since, "since": tc.since,
}))) })))
@ -1055,7 +1055,7 @@ func testContext(t *testing.T, dbType test.DBType) {
params[k] = v params[k] = v
} }
} }
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", requestPath, test.WithQueryParams(params))) base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", requestPath, test.WithQueryParams(params)))
if tc.wantError && w.Code == 200 { if tc.wantError && w.Code == 200 {
t.Fatalf("Expected an error, but got none") t.Fatalf("Expected an error, but got none")
@ -1184,7 +1184,7 @@ func syncUntil(t *testing.T,
go func() { go func() {
for { for {
w := httptest.NewRecorder() w := httptest.NewRecorder()
base.PublicClientAPIMux.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{ base.Routers.Client.ServeHTTP(w, test.NewRequest(t, "GET", "/_matrix/client/v3/sync", test.WithQueryParams(map[string]string{
"access_token": accessToken, "access_token": accessToken,
"timeout": "1000", "timeout": "1000",
}))) })))