-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.py
More file actions
80 lines (63 loc) · 3.54 KB
/
client.py
File metadata and controls
80 lines (63 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from urllib import parse
import warnings
import requests
class ApiClient:
def __init__(self, api_key, base_url="https://cockpit.shirtigo.com/api/", ignore_certificates=False):
# store base url, resource url will be appended
self.base_url = base_url
# warn on very short api key
if len(api_key) < 100:
warnings.warn("The provided API token appears to be shorter than expected.")
# initialize requests Session in order to share headers/cookies between requests
self.session = requests.Session()
# set OAuth/Authorization header
self.session.headers.update({
"User-Agent": "Shirtigo Cockpit Python REST API Client",
"Authorization": "Bearer " + str(api_key),
"Accept": "application/json"
})
if ignore_certificates:
# disable SSL certificate validation
self.session.verify = False
def _request(self, url, method="GET", data=None, params=None, files=None):
# construct full URL
url = parse.urljoin(self.base_url, url)
headers = {}
if not files:
# don't send a json header if the request contains files
# as a multipart-formdata value will be generated by requests
headers["Content-Type"] = "application/json"
# issue request
response = self.session.request(method, url, json=data, params=params, files=files, headers=headers)
if response.status_code == 204:
# 204 = No Content (expected)
return None
if response.headers['content-type'].startswith('application/json'):
response_data = response.json()
if not response.ok:
# extract error and throw Python exception
if response.status_code == 401:
if response.request.url != url:
raise RuntimeError("Authentication error. Make sure that the client base url exactly matches the documentation.")
else:
raise RuntimeError("Authentication error. Check whether the provided API token is valid.")
elif response.status_code == 403 and "required_scopes" in response_data:
raise RuntimeError("Authorization error. API token requires the following scope(s): %s" % ", ".join(response_data["required_scopes"]))
elif response.status_code == 422 and "errors" in response_data :
raise ValueError("Input validation failed: %r" % response_data["errors"])
elif "message" in response_data:
raise RuntimeError("Endpoint returned HTTP status %d: %s" %
(response.status_code, response_data["message"]))
else:
raise RuntimeError("Endpoint returned unhandled HTTP status %d", response.status_code)
return response_data
else:
raise RuntimeError("The response is expected to be in json format. The actual response is: {}".format(response.text))
def get(self, url, params=None):
return self._request(url, "GET", None, params)
def post(self, url, data=None, params=None, files=None):
return self._request(url, "POST", data, params, files)
def put(self, url, data=None, params=None, files=None):
return self._request(url, "PUT", data, params, files)
def delete(self, url, params=None):
return self._request(url, "DELETE", None, params)