Skip to content

Commit f6c3ef7

Browse files
authored
Merge pull request #13 from corywright/pass-headers-to-requests
Add ability to pass additional headers to the api request
2 parents 18979f4 + 0e9e60f commit f6c3ef7

File tree

4 files changed

+70
-11
lines changed

4 files changed

+70
-11
lines changed

HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ History
77

88
* Force iland API v0.8.
99
* Update dev requirements.
10+
* Add support for passing additional headers with api requests.
1011

1112
0.7.4 (2017-05-26)
1213
------------------

iland/api.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def _get_access_token_string(self):
112112
token_string = self._get_access_token()['access_token']
113113
return token_string
114114

115-
def _do_request(self, rpath, verb='GET', form_data=None):
115+
def _do_request(self, rpath, verb='GET', form_data=None, headers=None):
116116
self._refresh_token()
117117
data = None
118118
if form_data is not None:
@@ -121,14 +121,24 @@ def _do_request(self, rpath, verb='GET', form_data=None):
121121

122122
LOG.info("Request %s rpath %s" % (verb, url))
123123

124-
headers = {
124+
default_headers = {
125125
'Authorization': 'Bearer %s' % self._get_access_token_string(),
126126
'Content-Type': 'application/vnd.ilandcloud.api.v0.8+json',
127127
'Accept': 'application/vnd.ilandcloud.api.v0.8+json'
128128
}
129129

130+
merged_headers = default_headers.copy()
131+
132+
if headers and isinstance(headers, dict):
133+
for header, value in headers.items():
134+
# don't allow overriding of our default headers
135+
if header in default_headers:
136+
LOG.warning("Header '%s' can't be overridden" % header)
137+
else:
138+
merged_headers[header] = value
139+
130140
request_params = {
131-
'headers': headers,
141+
'headers': merged_headers,
132142
'verify': self._verify_ssl
133143
}
134144

@@ -156,59 +166,69 @@ def _do_request(self, rpath, verb='GET', form_data=None):
156166
raise ApiException(json_obj)
157167
return json_obj
158168

159-
def get(self, rpath):
169+
def get(self, rpath, headers=None):
160170
""" Perform a GET request against the iland cloud API given its
161171
resource path.
162172
163173
`iland.Api` will refresh the access token if non valid.
164174
165175
:param rpath: the resource path as a Python builtin String object
176+
:param headers: an optional dictionary of http headers to send with \
177+
the request
166178
:raises: ApiException: API requests returns an error
167179
:raises: UnauthorizedException: credentials / grants invalids
168180
:return: a JSON Object or a list of JSON Objects.
169181
"""
170-
return self._do_request(rpath)
182+
return self._do_request(rpath, headers=headers)
171183

172-
def put(self, rpath, form_data=None):
184+
def put(self, rpath, form_data=None, headers=None):
173185
""" Perform a PUT request against the iland cloud API given its
174186
resource path.
175187
176188
`iland.Api` will refresh the access token if non valid.
177189
178190
:param rpath: the resource path as a Python builtin String object
179191
:param form_data: a Python builtin dict object
192+
:param headers: an optional dictionary of http headers to send with \
193+
the request
180194
:raises: ApiException: API requests returns an error
181195
:raises: UnauthorizedException: credentials / grants invalids
182196
:return: a JSON Object or a list of JSON Objects.
183197
"""
184-
return self._do_request(rpath, verb='PUT', form_data=form_data)
198+
return self._do_request(rpath, verb='PUT', form_data=form_data,
199+
headers=headers)
185200

186-
def post(self, rpath, form_data=None):
201+
def post(self, rpath, form_data=None, headers=None):
187202
""" Perform a POST request against the iland cloud API given its
188203
resource path.
189204
190205
`iland.Api` will refresh the access token if non valid.
191206
192207
:param rpath: the resource path as a Python builtin String object
193208
:param form_data: a Python builtin dict object
209+
:param headers: an optional dictionary of http headers to send with \
210+
the request
194211
:raises: ApiException: API requests returns an error
195212
:raises: UnauthorizedException: credentials / grants invalids
196213
:return: a JSON Object or a list of JSON Objects.
197214
"""
198-
return self._do_request(rpath, verb='POST', form_data=form_data)
215+
return self._do_request(rpath, verb='POST', form_data=form_data,
216+
headers=headers)
199217

200-
def delete(self, rpath):
218+
def delete(self, rpath, headers=None):
201219
""" Perform a DELETE request against the iland cloud API given its
202220
resource path.
203221
204222
`iland.Api` will refresh the access token if non valid.
205223
206224
:param rpath: the resource path as a Python builtin String object
225+
:param headers: an optional dictionary of http headers to send with \
226+
the request
207227
:raises: ApiException: API requests returns an error
208228
:raises: UnauthorizedException: credentials / grants invalids
209229
:return: a JSON Object or a list of JSON Objects.
210230
"""
211-
return self._do_request(rpath, verb='DELETE')
231+
return self._do_request(rpath, verb='DELETE', headers=headers)
212232

213233
def get_access_token(self):
214234
""" Returns the access token in use for this session.

tests/test_iland.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,29 @@ def test_with_default_base_url(self):
291291
status_code=200)
292292
req = self.api.get(rpath)
293293
self.assertEquals(user_data, req)
294+
295+
def test_get_with_extra_header(self):
296+
with requests_mock.mock() as m:
297+
m.post(iland.ACCESS_URL,
298+
text=json.dumps(VALID_TOKEN_PAYLOAD),
299+
status_code=200)
300+
rpath = '/user/jchirac'
301+
user_data = {'username': 'jchirac'}
302+
m.get(BASE_URL + rpath, text='XXXXX' + json.dumps(user_data),
303+
request_headers={'Host': 'api.ilandcloud.com'},
304+
status_code=200)
305+
req = self.api.get(rpath, headers={'Host': 'api.ilandcloud.com'})
306+
self.assertEquals(user_data, req)
307+
308+
def test_get_with_extra_disallowed_header(self):
309+
with requests_mock.mock() as m:
310+
m.post(iland.ACCESS_URL,
311+
text=json.dumps(VALID_TOKEN_PAYLOAD),
312+
status_code=200)
313+
rpath = '/user/jchirac'
314+
user_data = {'username': 'jchirac'}
315+
m.get(BASE_URL + rpath, text='XXXXX' + json.dumps(user_data),
316+
status_code=200)
317+
# Set Accept to text/csv but it's ignored by api, so we get json
318+
req = self.api.get(rpath, headers={'Accept': 'text/csv'})
319+
self.assertEquals(user_data, req)

tests/test_iland_int.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ def test_put_delete(self):
104104
updated_md = self._api.get('/vdc/' + vdc_uuid + '/metadata')
105105
self.assertEquals(len(updated_md), 0)
106106

107+
def test_get_with_host_header(self):
108+
user = self._api.get('/user/' + USERNAME,
109+
headers={'Host': 'api.ilandcloud.com'})
110+
self.assertEqual(USERNAME, user.get('name'))
111+
self.assertTrue(len(user.keys()) > 5)
112+
113+
def test_get_with_disallowed_header(self):
114+
user = self._api.get('/user/' + USERNAME,
115+
headers={'Accept': 'text/csv'})
116+
self.assertEqual(USERNAME, user.get('name'))
117+
self.assertTrue(len(user.keys()) > 5)
118+
107119
def test_refresh_token(self):
108120
self._api.login()
109121
self.assertIsNotNone(self._api.get_access_token())

0 commit comments

Comments
 (0)