matrix-org.dendrite/src/github.com/matrix-org/dendrite/roomserver/api/query.go

105 lines
3.4 KiB
Go

// Copyright 2017 Vector Creations 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
import (
"bytes"
"encoding/json"
"fmt"
"github.com/matrix-org/gomatrixserverlib"
"net/http"
)
// QueryLatestEventsAndStateRequest is a request to QueryLatestEventsAndState
type QueryLatestEventsAndStateRequest struct {
// The roomID to query the latest events for.
RoomID string
// The state key tuples to fetch from the room current state.
// If this list is empty or nil then no state events are returned.
StateToFetch []gomatrixserverlib.StateKeyTuple
}
// QueryLatestEventsAndStateResponse is a response to QueryLatestEventsAndState
type QueryLatestEventsAndStateResponse struct {
// Copy of the request for debugging.
QueryLatestEventsAndStateRequest
// Does the room exist?
// If the room doesn't exist this will be false and LatestEvents will be empty.
RoomExists bool
// The latest events in the room.
LatestEvents []gomatrixserverlib.EventReference
// The state events requested.
StateEvents []gomatrixserverlib.Event
}
// RoomserverQueryAPI is used to query information from the room server.
type RoomserverQueryAPI interface {
// Query the latest events and state for a room from the room server.
QueryLatestEventsAndState(
request *QueryLatestEventsAndStateRequest,
response *QueryLatestEventsAndStateResponse,
) error
}
// RoomserverQueryLatestEventsAndStatePath is the HTTP path for the QueryLatestEventsAndState API.
const RoomserverQueryLatestEventsAndStatePath = "/api/roomserver/QueryLatestEventsAndState"
// NewRoomserverQueryAPIHTTP creates a RoomserverQueryAPI implemented by talking to a HTTP POST API.
// If httpClient is nil then it uses the http.DefaultClient
func NewRoomserverQueryAPIHTTP(roomserverURL string, httpClient *http.Client) RoomserverQueryAPI {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &httpRoomserverQueryAPI{roomserverURL, *httpClient}
}
type httpRoomserverQueryAPI struct {
roomserverURL string
httpClient http.Client
}
// QueryLatestEventsAndState implements RoomserverQueryAPI
func (h *httpRoomserverQueryAPI) QueryLatestEventsAndState(
request *QueryLatestEventsAndStateRequest,
response *QueryLatestEventsAndStateResponse,
) error {
apiURL := h.roomserverURL + RoomserverQueryLatestEventsAndStatePath
return postJSON(h.httpClient, apiURL, request, response)
}
func postJSON(httpClient http.Client, apiURL string, request, response interface{}) error {
jsonBytes, err := json.Marshal(request)
if err != nil {
return err
}
res, err := httpClient.Post(apiURL, "application/json", bytes.NewReader(jsonBytes))
if res != nil {
defer res.Body.Close()
}
if err != nil {
return err
}
if res.StatusCode != 200 {
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)
}