Skip to content

Commit cbd610a

Browse files
committed
Move main api methods into transport-agnostic class
This allows easy implementation of alternative transports (e.g. websockets) in the future by subclassing MatrixApi. It also allows testing of the api without mocking requests. Signed-off-by: Adam Beckmeyer <adam_git@thebeckmeyers.xyz>
1 parent 22b99b1 commit cbd610a

File tree

1 file changed

+58
-48
lines changed

1 file changed

+58
-48
lines changed

matrix_client/api.py

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,14 @@
2626
MATRIX_V2_API_PATH = "/_matrix/client/r0"
2727

2828

29-
class MatrixHttpApi(object):
30-
"""Contains all raw Matrix HTTP Client-Server API calls.
29+
class MatrixApi(object):
30+
"""Contains transport-agnostic Matrix Client-Server API calls.
3131
32-
Usage:
33-
matrix = MatrixHttpApi("https://matrix.org", token="foobar")
34-
response = matrix.sync()
35-
response = matrix.send_message("!roomid:matrix.org", "Hello!")
36-
37-
For room and sync handling, consider using MatrixClient.
32+
For usage, MatrixApi must be subclassed with a valid _send method.
3833
"""
3934

4035
def __init__(self, base_url, token=None, identity=None):
41-
"""Construct and configure the HTTP API.
36+
"""Construct and configure the API.
4237
4338
Args:
4439
base_url(str): The home server URL e.g. 'http://localhost:8008'
@@ -524,45 +519,8 @@ def create_filter(self, user_id, filter_params):
524519
filter_params,
525520
api_path=MATRIX_V2_API_PATH)
526521

527-
def _send(self, method, path, content=None, query_params={}, headers={},
528-
api_path="/_matrix/client/api/v1"):
529-
method = method.upper()
530-
if method not in ["GET", "PUT", "DELETE", "POST"]:
531-
raise MatrixError("Unsupported HTTP method: %s" % method)
532-
533-
if "Content-Type" not in headers:
534-
headers["Content-Type"] = "application/json"
535-
536-
query_params["access_token"] = self.token
537-
if self.identity:
538-
query_params["user_id"] = self.identity
539-
540-
endpoint = self.base_url + api_path + path
541-
542-
if headers["Content-Type"] == "application/json" and content is not None:
543-
content = json.dumps(content)
544-
545-
response = None
546-
while True:
547-
response = requests.request(
548-
method, endpoint,
549-
params=query_params,
550-
data=content,
551-
headers=headers,
552-
verify=self.validate_cert
553-
)
554-
555-
if response.status_code == 429:
556-
sleep(response.json()['retry_after_ms'] / 1000)
557-
else:
558-
break
559-
560-
if response.status_code < 200 or response.status_code >= 300:
561-
raise MatrixRequestError(
562-
code=response.status_code, content=response.text
563-
)
564-
565-
return response.json()
522+
def _send(self, *args, **kwargs):
523+
raise NotImplementedError("MatrixApi must be subclassed by a transport class.")
566524

567525
def media_upload(self, content, content_type):
568526
return self._send(
@@ -641,3 +599,55 @@ def get_room_members(self, room_id):
641599
"""
642600
return self._send("GET", "/rooms/{}/members".format(quote(room_id)),
643601
api_path=MATRIX_V2_API_PATH)
602+
603+
604+
class MatrixHttpApi(MatrixApi):
605+
"""Contains all Matrix Client-Server API calls with Http transport.
606+
607+
Usage:
608+
matrix = MatrixHttpApi("https://matrix.org", token="foobar")
609+
response = matrix.sync()
610+
response = matrix.send_message("!roomid:matrix.org", "Hello!")
611+
612+
For room and sync handling, consider using MatrixClient.
613+
"""
614+
615+
def _send(self, method, path, content=None, query_params={}, headers={},
616+
api_path="/_matrix/client/api/v1"):
617+
method = method.upper()
618+
if method not in ["GET", "PUT", "DELETE", "POST"]:
619+
raise MatrixError("Unsupported HTTP method: %s" % method)
620+
621+
if "Content-Type" not in headers:
622+
headers["Content-Type"] = "application/json"
623+
624+
query_params["access_token"] = self.token
625+
if self.identity:
626+
query_params["user_id"] = self.identity
627+
628+
endpoint = self.base_url + api_path + path
629+
630+
if headers["Content-Type"] == "application/json" and content is not None:
631+
content = json.dumps(content)
632+
633+
response = None
634+
while True:
635+
response = requests.request(
636+
method, endpoint,
637+
params=query_params,
638+
data=content,
639+
headers=headers,
640+
verify=self.validate_cert
641+
)
642+
643+
if response.status_code == 429:
644+
sleep(response.json()['retry_after_ms'] / 1000)
645+
else:
646+
break
647+
648+
if response.status_code < 200 or response.status_code >= 300:
649+
raise MatrixRequestError(
650+
code=response.status_code, content=response.text
651+
)
652+
653+
return response.json()

0 commit comments

Comments
 (0)