Merge pull request #2 from matrix-org/kegan/factor-send-recv-json

Refactor how requests are sent
This commit is contained in:
Kegsay 2016-12-02 15:36:21 +00:00 committed by GitHub
commit d43c5df302
1 changed files with 41 additions and 67 deletions

104
client.go
View File

@ -159,17 +159,26 @@ func (cli *Client) StopSync() {
cli.incrementSyncingID() cli.incrementSyncingID()
} }
// SendJSON sends JSON to the given URL. // MakeRequest makes a JSON HTTP request to the given URL.
// If "resBody" is not nil, the response body will be json.Unmarshalled into it.
// //
// Returns the HTTP body as bytes on 2xx. Returns an error if the response is not 2xx. This error // Returns the HTTP body as bytes on 2xx. Returns an error if the response is not 2xx. This error
// is an HTTPError which includes the returned HTTP status code and possibly a RespError as the // is an HTTPError which includes the returned HTTP status code and possibly a RespError as the
// WrappedError, if the HTTP body could be decoded as a RespError. // WrappedError, if the HTTP body could be decoded as a RespError.
func (cli *Client) SendJSON(method string, httpURL string, contentJSON interface{}) ([]byte, error) { func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) {
jsonStr, err := json.Marshal(contentJSON) var req *http.Request
var err error
if reqBody != nil {
var jsonStr []byte
jsonStr, err = json.Marshal(reqBody)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req, err := http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr)) req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr))
} else {
req, err = http.NewRequest(method, httpURL, nil)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -182,7 +191,7 @@ func (cli *Client) SendJSON(method string, httpURL string, contentJSON interface
return nil, err return nil, err
} }
contents, err := ioutil.ReadAll(res.Body) contents, err := ioutil.ReadAll(res.Body)
if res.StatusCode >= 300 || res.StatusCode < 200 { if res.StatusCode/100 != 2 { // not 2xx
var wrap error var wrap error
var respErr RespError var respErr RespError
if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" { if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" {
@ -205,25 +214,25 @@ func (cli *Client) SendJSON(method string, httpURL string, contentJSON interface
if err != nil { if err != nil {
return nil, err return nil, err
} }
if resBody != nil {
if err = json.Unmarshal(contents, &resBody); err != nil {
return nil, err
}
}
return contents, nil return contents, nil
} }
// CreateFilter makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter // CreateFilter makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter
func (cli *Client) CreateFilter(filter json.RawMessage) (*RespCreateFilter, error) { func (cli *Client) CreateFilter(filter json.RawMessage) (resp *RespCreateFilter, err error) {
urlPath := cli.BuildURL("user", cli.UserID, "filter") urlPath := cli.BuildURL("user", cli.UserID, "filter")
resBytes, err := cli.SendJSON("POST", urlPath, &filter) _, err = cli.MakeRequest("POST", urlPath, &filter, &resp)
if err != nil { return
return nil, err
}
var filterResponse RespCreateFilter
if err = json.Unmarshal(resBytes, &filterResponse); err != nil {
return nil, err
}
return &filterResponse, nil
} }
// SyncRequest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync // SyncRequest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync
func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bool, setPresence string) (*RespSync, error) { func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bool, setPresence string) (resp *RespSync, err error) {
query := map[string]string{ query := map[string]string{
"timeout": strconv.Itoa(timeout), "timeout": strconv.Itoa(timeout),
} }
@ -240,28 +249,15 @@ func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bo
query["full_state"] = "true" query["full_state"] = "true"
} }
urlPath := cli.BuildURLWithQuery([]string{"sync"}, query) urlPath := cli.BuildURLWithQuery([]string{"sync"}, query)
req, err := http.NewRequest("GET", urlPath, nil) _, err = cli.MakeRequest("GET", urlPath, nil, &resp)
if err != nil { return
return nil, err
}
res, err := cli.Client.Do(req)
if res != nil {
defer res.Body.Close()
}
if err != nil {
return nil, err
}
var syncResponse RespSync
err = json.NewDecoder(res.Body).Decode(&syncResponse)
return &syncResponse, err
} }
// JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias // JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias
// //
// If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will // If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will
// be JSON encoded and used as the request body. // be JSON encoded and used as the request body.
func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{}) (*RespJoinRoom, error) { func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{}) (resp *RespJoinRoom, err error) {
var urlPath string var urlPath string
if serverName != "" { if serverName != "" {
urlPath = cli.BuildURLWithQuery([]string{"join", roomIDorAlias}, map[string]string{ urlPath = cli.BuildURLWithQuery([]string{"join", roomIDorAlias}, map[string]string{
@ -270,42 +266,27 @@ func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{
} else { } else {
urlPath = cli.BuildURL("join", roomIDorAlias) urlPath = cli.BuildURL("join", roomIDorAlias)
} }
_, err = cli.MakeRequest("POST", urlPath, content, &resp)
resBytes, err := cli.SendJSON("POST", urlPath, content) return
if err != nil {
return nil, err
}
var joinRoomResponse RespJoinRoom
if err = json.Unmarshal(resBytes, &joinRoomResponse); err != nil {
return nil, err
}
return &joinRoomResponse, nil
} }
// SetDisplayName sets the user's profile display name. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-displayname // SetDisplayName sets the user's profile display name. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-displayname
func (cli *Client) SetDisplayName(displayName string) error { func (cli *Client) SetDisplayName(displayName string) (err error) {
urlPath := cli.BuildURL("profile", cli.UserID, "displayname") urlPath := cli.BuildURL("profile", cli.UserID, "displayname")
s := struct { s := struct {
DisplayName string `json:"displayname"` DisplayName string `json:"displayname"`
}{displayName} }{displayName}
_, err := cli.SendJSON("PUT", urlPath, &s) _, err = cli.MakeRequest("PUT", urlPath, &s, nil)
return err return
} }
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid // SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. // contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (*RespSendEvent, error) { func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) {
txnID := "go" + strconv.FormatInt(time.Now().UnixNano(), 10) txnID := "go" + strconv.FormatInt(time.Now().UnixNano(), 10)
urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID) urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID)
resBytes, err := cli.SendJSON("PUT", urlPath, contentJSON) _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
if err != nil { return
return nil, err
}
var sendEventResponse RespSendEvent
if err = json.Unmarshal(resBytes, &sendEventResponse); err != nil {
return nil, err
}
return &sendEventResponse, nil
} }
// SendText sends an m.room.message event into the given room with a msgtype of m.text // SendText sends an m.room.message event into the given room with a msgtype of m.text
@ -316,17 +297,10 @@ func (cli *Client) SendText(roomID, text string) (*RespSendEvent, error) {
} }
// LeaveRoom leaves the given room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave // LeaveRoom leaves the given room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave
func (cli *Client) LeaveRoom(roomID string) (*RespLeaveRoom, error) { func (cli *Client) LeaveRoom(roomID string) (resp *RespLeaveRoom, err error) {
u := cli.BuildURL("rooms", roomID, "leave") u := cli.BuildURL("rooms", roomID, "leave")
resBytes, err := cli.SendJSON("POST", u, struct{}{}) _, err = cli.MakeRequest("POST", u, struct{}{}, &resp)
if err != nil { return
return nil, err
}
var resp RespLeaveRoom
if err = json.Unmarshal(resBytes, &resp); err != nil {
return nil, err
}
return &resp, nil
} }
// UploadLink uploads an HTTP URL and then returns an MXC URI. // UploadLink uploads an HTTP URL and then returns an MXC URI.