From 87001d6a0c5d9d8b48e716ec733e5ba6c0c4afd4 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 17 Mar 2018 16:59:16 +0200 Subject: Add: HttpAPI class for using REST-ful HTTP API --- ick2/client.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 ick2/client.py (limited to 'ick2/client.py') diff --git a/ick2/client.py b/ick2/client.py new file mode 100644 index 0000000..a474987 --- /dev/null +++ b/ick2/client.py @@ -0,0 +1,105 @@ +# Copyright (C) 2018 Lars Wirzenius +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +import json + + +import requests + + +class HttpError(Exception): + + pass + + +class HttpAPI: + + # Make requests to an HTTP API. + + json_type = 'application/json' + + def __init__(self): + self._session = requests.Session() + self._token = None + + def set_session(self, session): + self._session = session + + def set_token(self, token): + self._token = token + + def get_dict(self, url, headers=None): + r = self._request(self._session.get, url, headers=headers) + ct = r.headers.get('Content-Type') + if ct != self.json_type: + raise HttpError('Not JSON response') + try: + return r.json() + except json.decoder.JSONDecodeError: + raise HttpError('JSON parsing error') + + def get_blob(self, url, headers=None): + r = self._request(self._session.get, url, headers=headers) + return r.content + + def post(self, url, headers=None, body=None): + self._send_request(self._session.post, url, headers=headers, body=body) + return None + + def put(self, url, headers=None, body=None): + self._send_request(self._session.put, url, headers=headers, body=body) + return None + + def _send_request(self, func, url, headers=None, body=None): + if headers is None: + headers = {} + headers = dict(headers) + h, body = self._get_content_type_header(body) + headers.update(h) + self._request(func, url, headers=headers, data=body) + return None + + def _get_content_type_header(self, body): + if isinstance(body, dict): + header = { + 'Content-Type': 'application/json', + } + body = json.dumps(body) + return header, body + return {}, body + + def _get_authorization_headers(self): + return { + 'Authorization': 'Bearer {}'.format(self._token), + } + + def _request(self, func, url, headers=None, **kwargs): + if headers is None: + headers = {} + headers.update(self._get_authorization_headers()) + + logging.debug('request: func=%r', func) + logging.debug('request: url=%r', url) + for h in headers: + logging.debug('request: %s: %s', h, headers[h]) + logging.debug('request: kwargs=%r', kwargs) + + r = func(url, headers=headers, verify=False, **kwargs) + logging.debug('response: status_code=%r', r.status_code) + logging.debug('response: content=%r', r.content) + + if not r.ok: + raise HttpError(r.status_code) + return r -- cgit v1.2.1