Internal API for Appservices (#541)

This commit is contained in:
Andrew Morgan 2018-07-17 07:36:04 -07:00 committed by GitHub
parent 2fb2f7ca7b
commit e3b9754d59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 235 additions and 105 deletions

View File

@ -113,7 +113,7 @@ listen:
media_api: "localhost:7774" media_api: "localhost:7774"
public_rooms_api: "localhost:7775" public_rooms_api: "localhost:7775"
federation_sender: "localhost:7776" federation_sender: "localhost:7776"
appservice: "localhost:7777" appservice_api: "localhost:7777"
# The configuration for tracing the dendrite components. # The configuration for tracing the dendrite components.
tracing: tracing:

View File

@ -0,0 +1,49 @@
// Copyright 2018 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 api contains methods used by dendrite components in multi-process
// mode to send requests to the appservice component, typically in order to ask
// an application service for some information.
package api
import (
"net/http"
)
// AppServiceQueryAPI is used to query user and room alias data from application
// services
type AppServiceQueryAPI interface {
// TODO: Check whether a room alias exists within any application service namespaces
// TODO: QueryUserIDExists
}
// httpAppServiceQueryAPI contains the URL to an appservice query API and a
// reference to a httpClient used to reach it
type httpAppServiceQueryAPI struct {
appserviceURL string
httpClient *http.Client
}
// NewAppServiceQueryAPIHTTP creates a AppServiceQueryAPI implemented by talking
// to a HTTP POST API.
// If httpClient is nil then it uses http.DefaultClient
func NewAppServiceQueryAPIHTTP(
appserviceURL string,
httpClient *http.Client,
) AppServiceQueryAPI {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &httpAppServiceQueryAPI{appserviceURL, httpClient}
}

View File

@ -15,9 +15,13 @@
package appservice package appservice
import ( import (
"net/http"
"sync" "sync"
"time"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/appservice/consumers" "github.com/matrix-org/dendrite/appservice/consumers"
"github.com/matrix-org/dendrite/appservice/query"
"github.com/matrix-org/dendrite/appservice/routing" "github.com/matrix-org/dendrite/appservice/routing"
"github.com/matrix-org/dendrite/appservice/storage" "github.com/matrix-org/dendrite/appservice/storage"
"github.com/matrix-org/dendrite/appservice/types" "github.com/matrix-org/dendrite/appservice/types"
@ -25,7 +29,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/common/basecomponent" "github.com/matrix-org/dendrite/common/basecomponent"
"github.com/matrix-org/dendrite/common/transactions" "github.com/matrix-org/dendrite/common/transactions"
"github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -36,10 +40,10 @@ func SetupAppServiceAPIComponent(
base *basecomponent.BaseDendrite, base *basecomponent.BaseDendrite,
accountsDB *accounts.Database, accountsDB *accounts.Database,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
aliasAPI api.RoomserverAliasAPI, roomserverAliasAPI roomserverAPI.RoomserverAliasAPI,
queryAPI api.RoomserverQueryAPI, roomserverQueryAPI roomserverAPI.RoomserverQueryAPI,
transactionsCache *transactions.Cache, transactionsCache *transactions.Cache,
) { ) appserviceAPI.AppServiceQueryAPI {
// Create a connection to the appservice postgres DB // Create a connection to the appservice postgres DB
appserviceDB, err := storage.NewDatabase(string(base.Cfg.Database.AppService)) appserviceDB, err := storage.NewDatabase(string(base.Cfg.Database.AppService))
if err != nil { if err != nil {
@ -59,9 +63,22 @@ func SetupAppServiceAPIComponent(
workerStates[i] = ws workerStates[i] = ws
} }
// Create a HTTP client that this component will use for all outbound and
// inbound requests (inbound only for the internal API)
httpClient := &http.Client{
Timeout: time.Second * 30,
}
appserviceQueryAPI := query.AppServiceQueryAPI{
HTTPClient: httpClient,
Cfg: base.Cfg,
}
appserviceQueryAPI.SetupHTTP(http.DefaultServeMux)
consumer := consumers.NewOutputRoomEventConsumer( consumer := consumers.NewOutputRoomEventConsumer(
base.Cfg, base.KafkaConsumer, accountsDB, appserviceDB, base.Cfg, base.KafkaConsumer, accountsDB, appserviceDB,
queryAPI, aliasAPI, workerStates, roomserverQueryAPI, roomserverAliasAPI, workerStates,
) )
if err := consumer.Start(); err != nil { if err := consumer.Start(); err != nil {
logrus.WithError(err).Panicf("failed to start app service roomserver consumer") logrus.WithError(err).Panicf("failed to start app service roomserver consumer")
@ -74,7 +91,9 @@ func SetupAppServiceAPIComponent(
// Set up HTTP Endpoints // Set up HTTP Endpoints
routing.Setup( routing.Setup(
base.APIMux, *base.Cfg, queryAPI, aliasAPI, accountsDB, base.APIMux, *base.Cfg, roomserverQueryAPI, roomserverAliasAPI,
federation, transactionsCache, accountsDB, federation, transactionsCache,
) )
return &appserviceQueryAPI
} }

View File

@ -0,0 +1,34 @@
// Copyright 2018 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 query handles requests from other internal dendrite components when
// they interact with the AppServiceQueryAPI.
package query
import (
"net/http"
"github.com/matrix-org/dendrite/common/config"
)
// AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI
type AppServiceQueryAPI struct {
HTTPClient *http.Client
Cfg *config.Dendrite
}
// SetupHTTP adds the AppServiceQueryPAI handlers to the http.ServeMux. This
// handles and muxes incoming api requests the to internal AppServiceQueryAPI.
func (a *AppServiceQueryAPI) SetupHTTP(servMux *http.ServeMux) {
}

View File

@ -65,7 +65,7 @@ func worker(db *storage.Database, ws types.ApplicationServiceWorkerState) {
}).Info("starting application service") }).Info("starting application service")
ctx := context.Background() ctx := context.Background()
// Grab the HTTP client for sending requests to app services // Create a HTTP client for sending requests to app services
client := &http.Client{ client := &http.Client{
Timeout: transactionTimeout, Timeout: transactionTimeout,
// TODO: Verify certificates // TODO: Verify certificates

View File

@ -22,7 +22,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/routing" "github.com/matrix-org/dendrite/clientapi/routing"
"github.com/matrix-org/dendrite/common/basecomponent" "github.com/matrix-org/dendrite/common/basecomponent"
"github.com/matrix-org/dendrite/common/transactions" "github.com/matrix-org/dendrite/common/transactions"
"github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -35,9 +35,9 @@ func SetupClientAPIComponent(
accountsDB *accounts.Database, accountsDB *accounts.Database,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
keyRing *gomatrixserverlib.KeyRing, keyRing *gomatrixserverlib.KeyRing,
aliasAPI api.RoomserverAliasAPI, aliasAPI roomserverAPI.RoomserverAliasAPI,
inputAPI api.RoomserverInputAPI, inputAPI roomserverAPI.RoomserverInputAPI,
queryAPI api.RoomserverQueryAPI, queryAPI roomserverAPI.RoomserverQueryAPI,
transactionsCache *transactions.Cache, transactionsCache *transactions.Cache,
) { ) {
roomserverProducer := producers.NewRoomserverProducer(inputAPI) roomserverProducer := producers.NewRoomserverProducer(inputAPI)
@ -60,10 +60,8 @@ func SetupClientAPIComponent(
} }
routing.Setup( routing.Setup(
base.APIMux, *base.Cfg, roomserverProducer, base.APIMux, *base.Cfg, roomserverProducer, queryAPI, aliasAPI,
queryAPI, aliasAPI, accountsDB, deviceDB, accountsDB, deviceDB, federation, *keyRing, userUpdateProducer,
federation, *keyRing, syncProducer, transactionsCache,
userUpdateProducer, syncProducer,
transactionsCache,
) )
} }

View File

@ -27,7 +27,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
@ -42,8 +42,8 @@ func JoinRoomByIDOrAlias(
cfg config.Dendrite, cfg config.Dendrite,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
producer *producers.RoomserverProducer, producer *producers.RoomserverProducer,
queryAPI api.RoomserverQueryAPI, queryAPI roomserverAPI.RoomserverQueryAPI,
aliasAPI api.RoomserverAliasAPI, aliasAPI roomserverAPI.RoomserverAliasAPI,
keyRing gomatrixserverlib.KeyRing, keyRing gomatrixserverlib.KeyRing,
accountDB *accounts.Database, accountDB *accounts.Database,
) util.JSONResponse { ) util.JSONResponse {
@ -87,8 +87,8 @@ type joinRoomReq struct {
cfg config.Dendrite cfg config.Dendrite
federation *gomatrixserverlib.FederationClient federation *gomatrixserverlib.FederationClient
producer *producers.RoomserverProducer producer *producers.RoomserverProducer
queryAPI api.RoomserverQueryAPI queryAPI roomserverAPI.RoomserverQueryAPI
aliasAPI api.RoomserverAliasAPI aliasAPI roomserverAPI.RoomserverAliasAPI
keyRing gomatrixserverlib.KeyRing keyRing gomatrixserverlib.KeyRing
} }
@ -100,10 +100,10 @@ func (r joinRoomReq) joinRoomByID(roomID string) util.JSONResponse {
// If the server is not in the room the we will need to look up the // If the server is not in the room the we will need to look up the
// remote server the invite came from in order to request a join event // remote server the invite came from in order to request a join event
// from that server. // from that server.
queryReq := api.QueryInvitesForUserRequest{ queryReq := roomserverAPI.QueryInvitesForUserRequest{
RoomID: roomID, TargetUserID: r.userID, RoomID: roomID, TargetUserID: r.userID,
} }
var queryRes api.QueryInvitesForUserResponse var queryRes roomserverAPI.QueryInvitesForUserResponse
if err := r.queryAPI.QueryInvitesForUser(r.req.Context(), &queryReq, &queryRes); err != nil { if err := r.queryAPI.QueryInvitesForUser(r.req.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(r.req, err) return httputil.LogThenError(r.req, err)
} }
@ -145,8 +145,8 @@ func (r joinRoomReq) joinRoomByAlias(roomAlias string) util.JSONResponse {
} }
} }
if domain == r.cfg.Matrix.ServerName { if domain == r.cfg.Matrix.ServerName {
queryReq := api.GetRoomIDForAliasRequest{Alias: roomAlias} queryReq := roomserverAPI.GetRoomIDForAliasRequest{Alias: roomAlias}
var queryRes api.GetRoomIDForAliasResponse var queryRes roomserverAPI.GetRoomIDForAliasResponse
if err = r.aliasAPI.GetRoomIDForAlias(r.req.Context(), &queryReq, &queryRes); err != nil { if err = r.aliasAPI.GetRoomIDForAlias(r.req.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(r.req, err) return httputil.LogThenError(r.req, err)
} }
@ -214,7 +214,7 @@ func (r joinRoomReq) joinRoomUsingServers(
return httputil.LogThenError(r.req, err) return httputil.LogThenError(r.req, err)
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
event, err := common.BuildEvent(r.req.Context(), &eb, r.cfg, r.queryAPI, &queryRes) event, err := common.BuildEvent(r.req.Context(), &eb, r.cfg, r.queryAPI, &queryRes)
if err == nil { if err == nil {
if _, err = r.producer.SendEvents(r.req.Context(), []gomatrixserverlib.Event{*event}, r.cfg.Matrix.ServerName, nil); err != nil { if _, err = r.producer.SendEvents(r.req.Context(), []gomatrixserverlib.Event{*event}, r.cfg.Matrix.ServerName, nil); err != nil {

View File

@ -318,8 +318,8 @@ func UserIDIsWithinApplicationServiceNamespace(
} }
// Loop through all known application service's namespaces and see if any match // Loop through all known application service's namespaces and see if any match
for _, knownAppservice := range cfg.Derived.ApplicationServices { for _, knownAppService := range cfg.Derived.ApplicationServices {
for _, namespace := range knownAppservice.NamespaceMap["users"] { for _, namespace := range knownAppService.NamespaceMap["users"] {
// AS namespaces are checked for validity in config // AS namespaces are checked for validity in config
if namespace.RegexpObject.MatchString(userID) { if namespace.RegexpObject.MatchString(userID) {
return true return true

View File

@ -21,7 +21,6 @@ import (
"github.com/matrix-org/dendrite/common/keydb" "github.com/matrix-org/dendrite/common/keydb"
"github.com/matrix-org/dendrite/common/transactions" "github.com/matrix-org/dendrite/common/transactions"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/clientapi" "github.com/matrix-org/dendrite/clientapi"
"github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/basecomponent" "github.com/matrix-org/dendrite/common/basecomponent"
@ -66,7 +65,6 @@ func main() {
mediaapi.SetupMediaAPIComponent(base, deviceDB) mediaapi.SetupMediaAPIComponent(base, deviceDB)
publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB) publicroomsapi.SetupPublicRoomsAPIComponent(base, deviceDB)
syncapi.SetupSyncAPIComponent(base, deviceDB, accountDB, query) syncapi.SetupSyncAPIComponent(base, deviceDB, accountDB, query)
appservice.SetupAppServiceAPIComponent(base, accountDB, federation, alias, query, transactions.New())
httpHandler := common.WrapHandlerInCORS(base.APIMux) httpHandler := common.WrapHandlerInCORS(base.APIMux)

View File

@ -30,8 +30,9 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
sarama "gopkg.in/Shopify/sarama.v1" sarama "gopkg.in/Shopify/sarama.v1"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/dendrite/roomserver/api" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -80,12 +81,22 @@ func (b *BaseDendrite) Close() error {
return b.tracerCloser.Close() return b.tracerCloser.Close()
} }
// CreateHTTPRoomserverAPIs returns the AliasAPI, InputAPI and QueryAPI to hit // CreateHTTPAppServiceAPIs returns the QueryAPI for hitting the appservice
// component over HTTP.
func (b *BaseDendrite) CreateHTTPAppServiceAPIs() appserviceAPI.AppServiceQueryAPI {
return appserviceAPI.NewAppServiceQueryAPIHTTP(b.Cfg.AppServiceURL(), nil)
}
// CreateHTTPRoomserverAPIs returns the AliasAPI, InputAPI and QueryAPI for hitting
// the roomserver over HTTP. // the roomserver over HTTP.
func (b *BaseDendrite) CreateHTTPRoomserverAPIs() (api.RoomserverAliasAPI, api.RoomserverInputAPI, api.RoomserverQueryAPI) { func (b *BaseDendrite) CreateHTTPRoomserverAPIs() (
alias := api.NewRoomserverAliasAPIHTTP(b.Cfg.RoomServerURL(), nil) roomserverAPI.RoomserverAliasAPI,
input := api.NewRoomserverInputAPIHTTP(b.Cfg.RoomServerURL(), nil) roomserverAPI.RoomserverInputAPI,
query := api.NewRoomserverQueryAPIHTTP(b.Cfg.RoomServerURL(), nil) roomserverAPI.RoomserverQueryAPI,
) {
alias := roomserverAPI.NewRoomserverAliasAPIHTTP(b.Cfg.RoomServerURL(), nil)
input := roomserverAPI.NewRoomserverInputAPIHTTP(b.Cfg.RoomServerURL(), nil)
query := roomserverAPI.NewRoomserverQueryAPIHTTP(b.Cfg.RoomServerURL(), nil)
return alias, input, query return alias, input, query
} }

View File

@ -114,9 +114,9 @@ func (a *ApplicationService) IsInterestedInRoomAlias(
return false return false
} }
// loadAppservices iterates through all application service config files // loadAppServices iterates through all application service config files
// and loads their data into the config object for later access. // and loads their data into the config object for later access.
func loadAppservices(config *Dendrite) error { func loadAppServices(config *Dendrite) error {
for _, configPath := range config.ApplicationServices.ConfigFiles { for _, configPath := range config.ApplicationServices.ConfigFiles {
// Create a new application service with default options // Create a new application service with default options
appservice := ApplicationService{ appservice := ApplicationService{

View File

@ -198,6 +198,7 @@ type Dendrite struct {
MediaAPI Address `yaml:"media_api"` MediaAPI Address `yaml:"media_api"`
ClientAPI Address `yaml:"client_api"` ClientAPI Address `yaml:"client_api"`
FederationAPI Address `yaml:"federation_api"` FederationAPI Address `yaml:"federation_api"`
AppServiceAPI Address `yaml:"appservice_api"`
SyncAPI Address `yaml:"sync_api"` SyncAPI Address `yaml:"sync_api"`
RoomServer Address `yaml:"room_server"` RoomServer Address `yaml:"room_server"`
FederationSender Address `yaml:"federation_sender"` FederationSender Address `yaml:"federation_sender"`
@ -408,7 +409,7 @@ func (config *Dendrite) derive() error {
} }
// Load application service configuration files // Load application service configuration files
if err := loadAppservices(config); err != nil { if err := loadAppServices(config); err != nil {
return err return err
} }
@ -640,6 +641,15 @@ func fingerprintPEM(data []byte) *gomatrixserverlib.TLSFingerprint {
} }
} }
// AppServiceURL returns a HTTP URL for where the appservice component is listening.
func (config *Dendrite) AppServiceURL() string {
// Hard code the roomserver 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.AppServiceAPI)
}
// RoomServerURL returns an HTTP URL for where the roomserver is listening. // RoomServerURL returns an HTTP URL for where the roomserver is listening.
func (config *Dendrite) RoomServerURL() string { func (config *Dendrite) RoomServerURL() string {
// Hard code the roomserver to talk HTTP for now. // Hard code the roomserver to talk HTTP for now.

View File

@ -0,0 +1,57 @@
package http
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
opentracing "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
)
// PostJSON performs a POST request with JSON on an internal HTTP API
func PostJSON(
ctx context.Context, span opentracing.Span, httpClient *http.Client,
apiURL string, request, response interface{},
) error {
jsonBytes, err := json.Marshal(request)
if err != nil {
return err
}
req, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(jsonBytes))
if err != nil {
return err
}
// Mark the span as being an RPC client.
ext.SpanKindRPCClient.Set(span)
carrier := opentracing.HTTPHeadersCarrier(req.Header)
tracer := opentracing.GlobalTracer()
if err = tracer.Inject(span.Context(), opentracing.HTTPHeaders, carrier); err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
res, err := httpClient.Do(req.WithContext(ctx))
if res != nil {
defer (func() { err = res.Body.Close() })()
}
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
var errorBody struct {
Message string `json:"message"`
}
if err = json.NewDecoder(res.Body).Decode(&errorBody); err != nil {
return err
}
return fmt.Errorf("api: %d: %s", res.StatusCode, errorBody.Message)
}
return json.NewDecoder(res.Body).Decode(response)
}

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"net/http" "net/http"
commonHTTP "github.com/matrix-org/dendrite/common/http"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
) )
@ -139,7 +140,7 @@ func (h *httpRoomserverAliasAPI) SetRoomAlias(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverSetRoomAliasPath apiURL := h.roomserverURL + RoomserverSetRoomAliasPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// GetRoomIDForAlias implements RoomserverAliasAPI // GetRoomIDForAlias implements RoomserverAliasAPI
@ -152,7 +153,7 @@ func (h *httpRoomserverAliasAPI) GetRoomIDForAlias(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverGetRoomIDForAliasPath apiURL := h.roomserverURL + RoomserverGetRoomIDForAliasPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// GetAliasesForRoomID implements RoomserverAliasAPI // GetAliasesForRoomID implements RoomserverAliasAPI
@ -165,7 +166,7 @@ func (h *httpRoomserverAliasAPI) GetAliasesForRoomID(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverGetAliasesForRoomIDPath apiURL := h.roomserverURL + RoomserverGetAliasesForRoomIDPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// RemoveRoomAlias implements RoomserverAliasAPI // RemoveRoomAlias implements RoomserverAliasAPI
@ -178,5 +179,5 @@ func (h *httpRoomserverAliasAPI) RemoveRoomAlias(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverRemoveRoomAliasPath apiURL := h.roomserverURL + RoomserverRemoveRoomAliasPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }

View File

@ -19,6 +19,7 @@ import (
"context" "context"
"net/http" "net/http"
commonHTTP "github.com/matrix-org/dendrite/common/http"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
) )
@ -134,5 +135,5 @@ func (h *httpRoomserverInputAPI) InputRoomEvents(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverInputRoomEventsPath apiURL := h.roomserverURL + RoomserverInputRoomEventsPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }

View File

@ -15,16 +15,12 @@
package api package api
import ( import (
"bytes"
"context" "context"
"encoding/json"
"fmt"
"net/http" "net/http"
opentracing "github.com/opentracing/opentracing-go" commonHTTP "github.com/matrix-org/dendrite/common/http"
"github.com/opentracing/opentracing-go/ext"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
opentracing "github.com/opentracing/opentracing-go"
) )
// QueryLatestEventsAndStateRequest is a request to QueryLatestEventsAndState // QueryLatestEventsAndStateRequest is a request to QueryLatestEventsAndState
@ -337,7 +333,7 @@ func (h *httpRoomserverQueryAPI) QueryLatestEventsAndState(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryLatestEventsAndStatePath apiURL := h.roomserverURL + RoomserverQueryLatestEventsAndStatePath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryStateAfterEvents implements RoomserverQueryAPI // QueryStateAfterEvents implements RoomserverQueryAPI
@ -350,7 +346,7 @@ func (h *httpRoomserverQueryAPI) QueryStateAfterEvents(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryStateAfterEventsPath apiURL := h.roomserverURL + RoomserverQueryStateAfterEventsPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryEventsByID implements RoomserverQueryAPI // QueryEventsByID implements RoomserverQueryAPI
@ -363,7 +359,7 @@ func (h *httpRoomserverQueryAPI) QueryEventsByID(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryEventsByIDPath apiURL := h.roomserverURL + RoomserverQueryEventsByIDPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryMembershipForUser implements RoomserverQueryAPI // QueryMembershipForUser implements RoomserverQueryAPI
@ -376,7 +372,7 @@ func (h *httpRoomserverQueryAPI) QueryMembershipForUser(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryMembershipForUserPath apiURL := h.roomserverURL + RoomserverQueryMembershipForUserPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryMembershipsForRoom implements RoomserverQueryAPI // QueryMembershipsForRoom implements RoomserverQueryAPI
@ -389,7 +385,7 @@ func (h *httpRoomserverQueryAPI) QueryMembershipsForRoom(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryMembershipsForRoomPath apiURL := h.roomserverURL + RoomserverQueryMembershipsForRoomPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryInvitesForUser implements RoomserverQueryAPI // QueryInvitesForUser implements RoomserverQueryAPI
@ -402,7 +398,7 @@ func (h *httpRoomserverQueryAPI) QueryInvitesForUser(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryInvitesForUserPath apiURL := h.roomserverURL + RoomserverQueryInvitesForUserPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryServerAllowedToSeeEvent implements RoomserverQueryAPI // QueryServerAllowedToSeeEvent implements RoomserverQueryAPI
@ -415,7 +411,7 @@ func (h *httpRoomserverQueryAPI) QueryServerAllowedToSeeEvent(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryServerAllowedToSeeEventPath apiURL := h.roomserverURL + RoomserverQueryServerAllowedToSeeEventPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryMissingEvents implements RoomServerQueryAPI // QueryMissingEvents implements RoomServerQueryAPI
@ -428,7 +424,7 @@ func (h *httpRoomserverQueryAPI) QueryMissingEvents(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryMissingEventsPath apiURL := h.roomserverURL + RoomserverQueryMissingEventsPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// QueryStateAndAuthChain implements RoomserverQueryAPI // QueryStateAndAuthChain implements RoomserverQueryAPI
@ -441,49 +437,5 @@ func (h *httpRoomserverQueryAPI) QueryStateAndAuthChain(
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverQueryStateAndAuthChainPath apiURL := h.roomserverURL + RoomserverQueryStateAndAuthChainPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
}
func postJSON(
ctx context.Context, span opentracing.Span, httpClient *http.Client,
apiURL string, request, response interface{},
) error {
jsonBytes, err := json.Marshal(request)
if err != nil {
return err
}
req, err := http.NewRequest(http.MethodPost, apiURL, bytes.NewReader(jsonBytes))
if err != nil {
return err
}
// Mark the span as being an RPC client.
ext.SpanKindRPCClient.Set(span)
carrier := opentracing.HTTPHeadersCarrier(req.Header)
tracer := opentracing.GlobalTracer()
if err = tracer.Inject(span.Context(), opentracing.HTTPHeaders, carrier); err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
res, err := httpClient.Do(req.WithContext(ctx))
if res != nil {
defer (func() { err = res.Body.Close() })()
}
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
var errorBody struct {
Message string `json:"message"`
}
if err = json.NewDecoder(res.Body).Decode(&errorBody); err != nil {
return err
}
return fmt.Errorf("api: %d: %s", res.StatusCode, errorBody.Message)
}
return json.NewDecoder(res.Body).Decode(response)
} }