Add missing servers field in /directory/room/:alias response
MODIFY
clientapi/clientapi.go
clientapi/clientapi.go
@@ -23,6 +23,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/routing"
"github.com/matrix-org/dendrite/common/basecomponent"
"github.com/matrix-org/dendrite/common/transactions"
+ federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
typingServerAPI "github.com/matrix-org/dendrite/typingserver/api"
"github.com/matrix-org/gomatrixserverlib"
@@ -43,6 +44,7 @@ func SetupClientAPIComponent(
typingInputAPI typingServerAPI.TypingServerInputAPI,
asAPI appserviceAPI.AppServiceQueryAPI,
transactionsCache *transactions.Cache,
+ fedSenderAPI federationSenderAPI.FederationSenderQueryAPI,
) {
roomserverProducer := producers.NewRoomserverProducer(inputAPI)
typingProducer := producers.NewTypingServerProducer(typingInputAPI)
@@ -67,6 +69,6 @@ func SetupClientAPIComponent(
routing.Setup(
base.APIMux, *base.Cfg, roomserverProducer, queryAPI, aliasAPI, asAPI,
accountsDB, deviceDB, federation, *keyRing, userUpdateProducer,
- syncProducer, typingProducer, transactionsCache,
+ syncProducer, typingProducer, transactionsCache, fedSenderAPI,
)
}

MODIFY
clientapi/routing/directory.go
clientapi/routing/directory.go
@@ -22,12 +22,24 @@ import (
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/common/config"
+ federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
- "github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
+type roomDirectoryResponse struct {
+ RoomID string `json:"room_id"`
+ Servers []string `json:"servers"`
+}
+
+func (r *roomDirectoryResponse) fillServers(servers []gomatrixserverlib.ServerName) {
+ r.Servers = make([]string, len(servers))
+ for i, s := range servers {
+ r.Servers[i] = string(s)
+ }
+}
+
// DirectoryRoom looks up a room alias
func DirectoryRoom(
req *http.Request,
@@ -35,6 +47,7 @@ func DirectoryRoom(
federation *gomatrixserverlib.FederationClient,
cfg *config.Dendrite,
rsAPI roomserverAPI.RoomserverAliasAPI,
+ fedSenderAPI federationSenderAPI.FederationSenderQueryAPI,
) util.JSONResponse {
_, domain, err := gomatrixserverlib.SplitID('#', roomAlias)
if err != nil {
@@ -44,41 +57,32 @@ func DirectoryRoom(
}
}
- if domain == cfg.Matrix.ServerName {
- // Query the roomserver API to check if the alias exists locally
+ var res roomDirectoryResponse
+
+ // Query the roomserver API to check if the alias exists locally.
queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
var queryRes roomserverAPI.GetRoomIDForAliasResponse
if err = rsAPI.GetRoomIDForAlias(req.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(req, err)
}
- // List any roomIDs found associated with this alias
- if len(queryRes.RoomID) > 0 {
- return util.JSONResponse{
- Code: http.StatusOK,
- JSON: queryRes,
- }
- }
- } else {
- // Query the federation for this room alias
- resp, err := federation.LookupRoomAlias(req.Context(), domain, roomAlias)
- if err != nil {
- switch err.(type) {
- case gomatrix.HTTPError:
- default:
+ res.RoomID = queryRes.RoomID
+
+ if res.RoomID == "" {
+ // If we don't know it locally, do a federation query.
+ // But don't send the query to ourselves.
+ if domain != cfg.Matrix.ServerName {
+ fedRes, fedErr := federation.LookupRoomAlias(req.Context(), domain, roomAlias)
+ if fedErr != nil {
// TODO: Return 502 if the remote server errored.
// TODO: Return 504 if the remote server timed out.
- return httputil.LogThenError(req, err)
- }
- }
- if len(resp.RoomID) > 0 {
- return util.JSONResponse{
- Code: http.StatusOK,
- JSON: resp,
- }
+ return httputil.LogThenError(req, fedErr)
}
+ res.RoomID = fedRes.RoomID
+ res.fillServers(fedRes.Servers)
}
+ if res.RoomID == "" {
return util.JSONResponse{
Code: http.StatusNotFound,
JSON: jsonerror.NotFound(
@@ -86,6 +90,20 @@ func DirectoryRoom(
),
}
}
+ } else {
+ joinedHostsReq := federationSenderAPI.QueryJoinedHostServerNamesInRoomRequest{RoomID: res.RoomID}
+ var joinedHostsRes federationSenderAPI.QueryJoinedHostServerNamesInRoomResponse
+ if err = fedSenderAPI.QueryJoinedHostServerNamesInRoom(req.Context(), &joinedHostsReq, &joinedHostsRes); err != nil {
+ return httputil.LogThenError(req, err)
+ }
+ res.fillServers(joinedHostsRes.ServerNames)
+ }
+
+ return util.JSONResponse{
+ Code: http.StatusOK,
+ JSON: res,
+ }
+}
// SetLocalAlias implements PUT /directory/room/{roomAlias}
// TODO: Check if the user has the power level to set an alias

MODIFY
clientapi/routing/routing.go
clientapi/routing/routing.go
@@ -30,6 +30,7 @@ import (
"github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/dendrite/common/transactions"
+ federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@@ -59,6 +60,7 @@ func Setup(
syncProducer *producers.SyncAPIProducer,
typingProducer *producers.TypingServerProducer,
transactionsCache *transactions.Cache,
+ federationSender federationSenderAPI.FederationSenderQueryAPI,
) {
apiMux.Handle("/_matrix/client/versions",
@@ -185,7 +187,7 @@ func Setup(
if err != nil {
return util.ErrorResponse(err)
}
- return DirectoryRoom(req, vars["roomAlias"], federation, &cfg, aliasAPI)
+ return DirectoryRoom(req, vars["roomAlias"], federation, &cfg, aliasAPI, federationSender)
}),
).Methods(http.MethodGet, http.MethodOptions)

MODIFY
cmd/dendrite-client-api-server/main.go
cmd/dendrite-client-api-server/main.go
@@ -37,11 +37,12 @@ func main() {
asQuery := base.CreateHTTPAppServiceAPIs()
alias, input, query := base.CreateHTTPRoomserverAPIs()
+ fedSenderAPI := base.CreateHTTPFederationSenderAPIs()
typingInputAPI := typingserver.SetupTypingServerComponent(base, cache.NewTypingCache())
clientapi.SetupClientAPIComponent(
base, deviceDB, accountDB, federation, &keyRing,
- alias, input, query, typingInputAPI, asQuery, transactions.New(),
+ alias, input, query, typingInputAPI, asQuery, transactions.New(), fedSenderAPI,
)
base.SetupAndServeHTTP(string(base.Cfg.Listen.ClientAPI))

MODIFY
cmd/dendrite-monolith-server/main.go
cmd/dendrite-monolith-server/main.go
@@ -60,14 +60,14 @@ func main() {
asQuery := appservice.SetupAppServiceAPIComponent(
base, accountDB, deviceDB, federation, alias, query, transactions.New(),
)
+ fedSenderAPI := federationsender.SetupFederationSenderComponent(base, federation, query)
clientapi.SetupClientAPIComponent(
base, deviceDB, accountDB,
federation, &keyRing, alias, input, query,
- typingInputAPI, asQuery, transactions.New(),
+ typingInputAPI, asQuery, transactions.New(), fedSenderAPI,
)
federationapi.SetupFederationAPIComponent(base, accountDB, deviceDB, federation, &keyRing, alias, input, query, asQuery)
- federationsender.SetupFederationSenderComponent(base, federation, query)
mediaapi.SetupMediaAPIComponent(base, deviceDB)
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB)
syncapi.SetupSyncAPIComponent(base, deviceDB, accountDB, query)

MODIFY
common/basecomponent/base.go
common/basecomponent/base.go
@@ -32,6 +32,7 @@ import (
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/common/config"
+ federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
typingServerAPI "github.com/matrix-org/dendrite/typingserver/api"
"github.com/sirupsen/logrus"
@@ -107,6 +108,12 @@ func (b *BaseDendrite) CreateHTTPTypingServerAPIs() typingServerAPI.TypingServer
return typingServerAPI.NewTypingServerInputAPIHTTP(b.Cfg.TypingServerURL(), nil)
}
+// CreateHTTPFederationSenderAPIs returns FederationSenderQueryAPI for hitting
+// the federation sender over HTTP
+func (b *BaseDendrite) CreateHTTPFederationSenderAPIs() federationSenderAPI.FederationSenderQueryAPI {
+ return federationSenderAPI.NewFederationSenderQueryAPIHTTP(b.Cfg.FederationSenderURL(), nil)
+}
+
// CreateDeviceDB creates a new instance of the device database. Should only be
// called once per component.
func (b *BaseDendrite) CreateDeviceDB() *devices.Database {

MODIFY
common/config/config.go
common/config/config.go
@@ -678,6 +678,15 @@ func (config *Dendrite) TypingServerURL() string {
return "http://" + string(config.Listen.TypingServer)
}
+// FederationSenderURL returns an HTTP URL for where the federation sender is listening.
+func (config *Dendrite) FederationSenderURL() string {
+ // Hard code the typing server to talk HTTP for now.
+ // If we support HTTPS we need to think of a practical way to do certificate validation.
+ // People setting up servers shouldn't need to get a certificate valid for the public
+ // internet for an internal API.
+ return "http://" + string(config.Listen.FederationSender)
+}
+
// SetupTracing configures the opentracing using the supplied configuration.
func (config *Dendrite) SetupTracing(serviceName string) (closer io.Closer, err error) {
return config.Tracing.Jaeger.InitGlobalTracer(

MODIFY
testfile
testfile
@@ -172,3 +172,13 @@ Outbound federation can query profile data
/event/ does not allow access to events before the user joined
Federation key API allows unsigned requests for keys
Can paginate public room list
+GET /directory/room/:room_alias yields room ID
+PUT /directory/room/:room_alias creates alias
+Room aliases can contain Unicode
+Creators can delete alias
+Alias creators can delete alias with no ops
+Alias creators can delete canonical alias with no ops
+Regular users cannot create room aliases within the AS namespace
+Deleting a non-existent alias should return a 404
+Users can't delete other's aliases
+Outbound federation can query room alias directory

Add missing servers field in /directory/room/:alias response (#732)