package inthttp import ( "context" "errors" "net/http" fsInputAPI "github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/internal/caching" internalHTTP "github.com/matrix-org/dendrite/internal/http" "github.com/matrix-org/dendrite/roomserver/api" "github.com/opentracing/opentracing-go" ) const ( // Alias operations RoomserverSetRoomAliasPath = "/roomserver/setRoomAlias" RoomserverGetRoomIDForAliasPath = "/roomserver/GetRoomIDForAlias" RoomserverGetAliasesForRoomIDPath = "/roomserver/GetAliasesForRoomID" RoomserverGetCreatorIDForAliasPath = "/roomserver/GetCreatorIDForAlias" RoomserverRemoveRoomAliasPath = "/roomserver/removeRoomAlias" // Input operations RoomserverInputRoomEventsPath = "/roomserver/inputRoomEvents" // Perform operations RoomserverPerformJoinPath = "/roomserver/performJoin" RoomserverPerformLeavePath = "/roomserver/performLeave" // Query operations RoomserverQueryLatestEventsAndStatePath = "/roomserver/queryLatestEventsAndState" RoomserverQueryStateAfterEventsPath = "/roomserver/queryStateAfterEvents" RoomserverQueryEventsByIDPath = "/roomserver/queryEventsByID" RoomserverQueryMembershipForUserPath = "/roomserver/queryMembershipForUser" RoomserverQueryMembershipsForRoomPath = "/roomserver/queryMembershipsForRoom" RoomserverQueryInvitesForUserPath = "/roomserver/queryInvitesForUser" RoomserverQueryServerAllowedToSeeEventPath = "/roomserver/queryServerAllowedToSeeEvent" RoomserverQueryMissingEventsPath = "/roomserver/queryMissingEvents" RoomserverQueryStateAndAuthChainPath = "/roomserver/queryStateAndAuthChain" RoomserverQueryBackfillPath = "/roomserver/queryBackfill" RoomserverQueryRoomVersionCapabilitiesPath = "/roomserver/queryRoomVersionCapabilities" RoomserverQueryRoomVersionForRoomPath = "/roomserver/queryRoomVersionForRoom" ) type httpRoomserverInternalAPI struct { roomserverURL string httpClient *http.Client fsAPI fsInputAPI.FederationSenderInternalAPI immutableCache caching.ImmutableCache } // NewRoomserverClient creates a RoomserverInputAPI implemented by talking to a HTTP POST API. // If httpClient is nil an error is returned func NewRoomserverClient( roomserverURL string, httpClient *http.Client, immutableCache caching.ImmutableCache, ) (api.RoomserverInternalAPI, error) { if httpClient == nil { return nil, errors.New("NewRoomserverInternalAPIHTTP: httpClient is ") } return &httpRoomserverInternalAPI{ roomserverURL: roomserverURL, httpClient: httpClient, immutableCache: immutableCache, }, nil } // SetFederationSenderInputAPI passes in a federation sender input API reference // so that we can avoid the chicken-and-egg problem of both the roomserver input API // and the federation sender input API being interdependent. func (h *httpRoomserverInternalAPI) SetFederationSenderAPI(fsAPI fsInputAPI.FederationSenderInternalAPI) { h.fsAPI = fsAPI } // SetRoomAlias implements RoomserverAliasAPI func (h *httpRoomserverInternalAPI) SetRoomAlias( ctx context.Context, request *api.SetRoomAliasRequest, response *api.SetRoomAliasResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "SetRoomAlias") defer span.Finish() apiURL := h.roomserverURL + RoomserverSetRoomAliasPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // GetRoomIDForAlias implements RoomserverAliasAPI func (h *httpRoomserverInternalAPI) GetRoomIDForAlias( ctx context.Context, request *api.GetRoomIDForAliasRequest, response *api.GetRoomIDForAliasResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "GetRoomIDForAlias") defer span.Finish() apiURL := h.roomserverURL + RoomserverGetRoomIDForAliasPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // GetAliasesForRoomID implements RoomserverAliasAPI func (h *httpRoomserverInternalAPI) GetAliasesForRoomID( ctx context.Context, request *api.GetAliasesForRoomIDRequest, response *api.GetAliasesForRoomIDResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "GetAliasesForRoomID") defer span.Finish() apiURL := h.roomserverURL + RoomserverGetAliasesForRoomIDPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // GetCreatorIDForAlias implements RoomserverAliasAPI func (h *httpRoomserverInternalAPI) GetCreatorIDForAlias( ctx context.Context, request *api.GetCreatorIDForAliasRequest, response *api.GetCreatorIDForAliasResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "GetCreatorIDForAlias") defer span.Finish() apiURL := h.roomserverURL + RoomserverGetCreatorIDForAliasPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // RemoveRoomAlias implements RoomserverAliasAPI func (h *httpRoomserverInternalAPI) RemoveRoomAlias( ctx context.Context, request *api.RemoveRoomAliasRequest, response *api.RemoveRoomAliasResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "RemoveRoomAlias") defer span.Finish() apiURL := h.roomserverURL + RoomserverRemoveRoomAliasPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // InputRoomEvents implements RoomserverInputAPI func (h *httpRoomserverInternalAPI) InputRoomEvents( ctx context.Context, request *api.InputRoomEventsRequest, response *api.InputRoomEventsResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "InputRoomEvents") defer span.Finish() apiURL := h.roomserverURL + RoomserverInputRoomEventsPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } func (h *httpRoomserverInternalAPI) PerformJoin( ctx context.Context, request *api.PerformJoinRequest, response *api.PerformJoinResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "PerformJoin") defer span.Finish() apiURL := h.roomserverURL + RoomserverPerformJoinPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } func (h *httpRoomserverInternalAPI) PerformLeave( ctx context.Context, request *api.PerformLeaveRequest, response *api.PerformLeaveResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "PerformLeave") defer span.Finish() apiURL := h.roomserverURL + RoomserverPerformLeavePath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryLatestEventsAndState implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryLatestEventsAndState( ctx context.Context, request *api.QueryLatestEventsAndStateRequest, response *api.QueryLatestEventsAndStateResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryLatestEventsAndState") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryLatestEventsAndStatePath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryStateAfterEvents implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryStateAfterEvents( ctx context.Context, request *api.QueryStateAfterEventsRequest, response *api.QueryStateAfterEventsResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryStateAfterEvents") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryStateAfterEventsPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryEventsByID implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryEventsByID( ctx context.Context, request *api.QueryEventsByIDRequest, response *api.QueryEventsByIDResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryEventsByID") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryEventsByIDPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryMembershipForUser implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryMembershipForUser( ctx context.Context, request *api.QueryMembershipForUserRequest, response *api.QueryMembershipForUserResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryMembershipForUser") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryMembershipForUserPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryMembershipsForRoom implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryMembershipsForRoom( ctx context.Context, request *api.QueryMembershipsForRoomRequest, response *api.QueryMembershipsForRoomResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryMembershipsForRoom") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryMembershipsForRoomPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryInvitesForUser implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryInvitesForUser( ctx context.Context, request *api.QueryInvitesForUserRequest, response *api.QueryInvitesForUserResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryInvitesForUser") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryInvitesForUserPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryServerAllowedToSeeEvent implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryServerAllowedToSeeEvent( ctx context.Context, request *api.QueryServerAllowedToSeeEventRequest, response *api.QueryServerAllowedToSeeEventResponse, ) (err error) { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryServerAllowedToSeeEvent") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryServerAllowedToSeeEventPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryMissingEvents implements RoomServerQueryAPI func (h *httpRoomserverInternalAPI) QueryMissingEvents( ctx context.Context, request *api.QueryMissingEventsRequest, response *api.QueryMissingEventsResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryMissingEvents") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryMissingEventsPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryStateAndAuthChain implements RoomserverQueryAPI func (h *httpRoomserverInternalAPI) QueryStateAndAuthChain( ctx context.Context, request *api.QueryStateAndAuthChainRequest, response *api.QueryStateAndAuthChainResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryStateAndAuthChain") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryStateAndAuthChainPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryBackfill implements RoomServerQueryAPI func (h *httpRoomserverInternalAPI) QueryBackfill( ctx context.Context, request *api.QueryBackfillRequest, response *api.QueryBackfillResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryBackfill") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryBackfillPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryRoomVersionCapabilities implements RoomServerQueryAPI func (h *httpRoomserverInternalAPI) QueryRoomVersionCapabilities( ctx context.Context, request *api.QueryRoomVersionCapabilitiesRequest, response *api.QueryRoomVersionCapabilitiesResponse, ) error { span, ctx := opentracing.StartSpanFromContext(ctx, "QueryRoomVersionCapabilities") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryRoomVersionCapabilitiesPath return internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) } // QueryRoomVersionForRoom implements RoomServerQueryAPI func (h *httpRoomserverInternalAPI) QueryRoomVersionForRoom( ctx context.Context, request *api.QueryRoomVersionForRoomRequest, response *api.QueryRoomVersionForRoomResponse, ) error { if roomVersion, ok := h.immutableCache.GetRoomVersion(request.RoomID); ok { response.RoomVersion = roomVersion return nil } span, ctx := opentracing.StartSpanFromContext(ctx, "QueryRoomVersionForRoom") defer span.Finish() apiURL := h.roomserverURL + RoomserverQueryRoomVersionForRoomPath err := internalHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) if err == nil { h.immutableCache.StoreRoomVersion(request.RoomID, response.RoomVersion) } return err }