From f45e3e4a83c14805a8a995b82b42cbb067480f0b Mon Sep 17 00:00:00 2001 From: Ross Schulman Date: Wed, 15 Nov 2017 19:42:03 -0500 Subject: [PATCH] Add room alias query endpoint --- .../dendrite-federation-api-server/main.go | 3 +- .../cmd/dendrite-monolith-server/main.go | 2 +- .../dendrite/federationapi/routing/query.go | 90 +++++++++++++++++++ .../dendrite/federationapi/routing/routing.go | 69 ++++++++------ 4 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 src/github.com/matrix-org/dendrite/federationapi/routing/query.go diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-federation-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-federation-api-server/main.go index ba981d8cf..53587ee20 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-federation-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-federation-api-server/main.go @@ -80,6 +80,7 @@ func main() { queryAPI := api.NewRoomserverQueryAPIHTTP(cfg.RoomServerURL(), nil) inputAPI := api.NewRoomserverInputAPIHTTP(cfg.RoomServerURL(), nil) + aliasAPI := api.NewRoomserverAliasAPIHTTP(cfg.RoomServerURL(), nil) roomserverProducer := producers.NewRoomserverProducer(inputAPI) @@ -90,7 +91,7 @@ func main() { log.Info("Starting federation API server on ", cfg.Listen.FederationAPI) api := mux.NewRouter() - routing.Setup(api, *cfg, queryAPI, roomserverProducer, keyRing, federation, accountDB) + routing.Setup(api, *cfg, queryAPI, aliasAPI, roomserverProducer, keyRing, federation, accountDB) common.SetupHTTPAPI(http.DefaultServeMux, api) log.Fatal(http.ListenAndServe(string(cfg.Listen.FederationAPI), nil)) diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go index b18d0360c..0ff1e3e1d 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go @@ -339,7 +339,7 @@ func (m *monolith) setupAPIs() { ), m.deviceDB) federationapi_routing.Setup( - m.api, *m.cfg, m.queryAPI, m.roomServerProducer, m.keyRing, m.federation, + m.api, *m.cfg, m.queryAPI, m.aliasAPI, m.roomServerProducer, m.keyRing, m.federation, m.accountDB, ) diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/query.go b/src/github.com/matrix-org/dendrite/federationapi/routing/query.go new file mode 100644 index 000000000..7e01ef5fd --- /dev/null +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/query.go @@ -0,0 +1,90 @@ +// Copyright 2017 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "net/http" + + "github.com/matrix-org/util" + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/clientapi/jsonerror" + "github.com/matrix-org/dendrite/common/config" + "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/gomatrix" + "github.com/matrix-org/gomatrixserverlib" +) + +func RoomAliasToID ( + httpReq *http.Request, + federation *gomatrixserverlib.FederationClient, + request *gomatrixserverlib.FederationRequest, + cfg config.Dendrite, + aliasAPI api.RoomserverAliasAPI, + query api.RoomserverQueryAPI, + roomAlias string, +) util.JSONResponse { + _, domain, err := gomatrixserverlib.SplitID('#', roomAlias) + if err != nil { + return util.JSONResponse{ + Code: 400, + JSON: jsonerror.BadJSON("Room alias must be in the form '#localpart:domain'"), + } + } + +var resp gomatrixserverlib.RespDirectory + + if domain == cfg.Matrix.ServerName { + queryReq := api.GetAliasRoomIDRequest{Alias: roomAlias} + var queryRes api.GetAliasRoomIDResponse + if err = aliasAPI.GetAliasRoomID(httpReq.Context(), &queryReq, &queryRes); err != nil { + return httputil.LogThenError(httpReq, err) + } + + if len(queryRes.RoomID) > 0 { + // TODO: List servers that are aware of this room alias + resp = gomatrixserverlib.RespDirectory{ + RoomID: queryRes.RoomID, + Servers: []gomatrixserverlib.ServerName{}, + } + } else { + // If the response doesn't contain a non-empty string, return an error + return util.JSONResponse{ + Code: 404, + JSON: jsonerror.NotFound("Room alias " + roomAlias + " not found."), + } + } + } else { + resp, err = federation.LookupRoomAlias(httpReq.Context(), domain, roomAlias) + if err != nil { + switch x := err.(type) { + case gomatrix.HTTPError: + if x.Code == 404 { + return util.JSONResponse{ + Code: 404, + JSON: jsonerror.NotFound("Room alias not found"), + } + } + } + // TODO: Return 502 if the remote server errored. + // TODO: Return 504 if the remote server timed out. + return httputil.LogThenError(httpReq, err) + } + } + + return util.JSONResponse{ + Code: 200, + JSON: resp, +} +} \ No newline at end of file diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go index c22dd1879..33b330f60 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go @@ -38,6 +38,7 @@ func Setup( apiMux *mux.Router, cfg config.Dendrite, query api.RoomserverQueryAPI, + aliasAPI api.RoomserverAliasAPI, producer *producers.RoomserverProducer, keys gomatrixserverlib.KeyRing, federation *gomatrixserverlib.FederationClient, @@ -80,35 +81,45 @@ func Setup( )).Methods("PUT", "OPTIONS") v1fedmux.Handle("/3pid/onbind", common.MakeExternalAPI("3pid_onbind", - func(req *http.Request) util.JSONResponse { - return CreateInvitesFrom3PIDInvites(req, query, cfg, producer, federation, accountDB) - }, - )).Methods("POST", "OPTIONS") + func(req *http.Request) util.JSONResponse { + return CreateInvitesFrom3PIDInvites(req, query, cfg, producer, federation, accountDB) + }, +)).Methods("POST", "OPTIONS") - v1fedmux.Handle("/exchange_third_party_invite/{roomID}", common.MakeFedAPI( - "exchange_third_party_invite", cfg.Matrix.ServerName, keys, - func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { - vars := mux.Vars(httpReq) - return ExchangeThirdPartyInvite( - httpReq, request, vars["roomID"], query, cfg, federation, producer, - ) - }, - )).Methods("PUT", "OPTIONS") +v1fedmux.Handle("/exchange_third_party_invite/{roomID}", common.MakeFedAPI( + "exchange_third_party_invite", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + vars := mux.Vars(httpReq) + return ExchangeThirdPartyInvite( + httpReq, request, vars["roomID"], query, cfg, federation, producer, + ) + }, +)).Methods("PUT", "OPTIONS") - v1fedmux.Handle("/event/{eventID}", common.MakeFedAPI( - "federation_get_event", cfg.Matrix.ServerName, keys, - func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { - vars := mux.Vars(httpReq) - return GetEvent( - httpReq.Context(), request, cfg, query, time.Now(), keys, vars["eventID"], - ) - }, - )).Methods("GET") +v1fedmux.Handle("/event/{eventID}", common.MakeFedAPI( + "federation_get_event", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + vars := mux.Vars(httpReq) + return GetEvent( + httpReq.Context(), request, cfg, query, time.Now(), keys, vars["eventID"], + ) + }, +)).Methods("GET") - v1fedmux.Handle("/version", common.MakeExternalAPI( - "federation_version", - func(httpReq *http.Request) util.JSONResponse { - return Version() - }, - )).Methods("GET") -} +v1fedmux.Handle("/version", common.MakeExternalAPI( + "federation_version", + func(httpReq *http.Request) util.JSONResponse { + return Version() + }, +)).Methods("GET") + +v1fedmux.Handle("/query/directory/?room_alias={alias}", common.MakeFedAPI( + "federation_query_room_alias", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + vars := mux.Vars(httpReq) + return RoomAliasToID( + httpReq, federation, request, cfg, aliasAPI, query, vars["alias"], + ) + }, +)).Methods("Get") +} \ No newline at end of file