* Store Authorization header inside HttpApi connection plugin (#45598)
(cherry picked from commit b7263eab1d
)
* Add changelog entry
This commit is contained in:
parent
d9bd76dc8a
commit
d2c72040b5
3 changed files with 19 additions and 26 deletions
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- Fix the issue with refreshing the token by storing Authorization header inside HttpApi connection plugin.
|
|
@ -109,6 +109,7 @@ class HttpApi(HttpApiBase):
|
|||
try:
|
||||
self.refresh_token = response['refresh_token']
|
||||
self.access_token = response['access_token']
|
||||
self.connection._auth = {'Authorization': 'Bearer %s' % self.access_token}
|
||||
except KeyError:
|
||||
raise ConnectionError(
|
||||
'Server returned response without token info during connection authentication: %s' % response)
|
||||
|
@ -121,7 +122,7 @@ class HttpApi(HttpApiBase):
|
|||
}
|
||||
self.connection.send(
|
||||
self._get_api_token_path(), json.dumps(auth_payload), method=HTTPMethod.POST,
|
||||
headers=self._authorized_headers()
|
||||
headers=BASE_HEADERS
|
||||
)
|
||||
self.refresh_token = None
|
||||
self.access_token = None
|
||||
|
@ -134,10 +135,7 @@ class HttpApi(HttpApiBase):
|
|||
url = construct_url_path(url_path, path_params, query_params)
|
||||
data = json.dumps(body_params) if body_params else None
|
||||
try:
|
||||
response, response_data = self.connection.send(
|
||||
url, data, method=http_method,
|
||||
headers=self._authorized_headers()
|
||||
)
|
||||
response, response_data = self.connection.send(url, data, method=http_method, headers=BASE_HEADERS)
|
||||
return {
|
||||
ResponseParams.SUCCESS: True,
|
||||
ResponseParams.STATUS_CODE: response.getcode(),
|
||||
|
@ -159,7 +157,7 @@ class HttpApi(HttpApiBase):
|
|||
rf.make_multipart()
|
||||
body, content_type = encode_multipart_formdata([rf])
|
||||
|
||||
headers = self._authorized_headers()
|
||||
headers = dict(BASE_HEADERS)
|
||||
headers['Content-Type'] = content_type
|
||||
headers['Content-Length'] = len(body)
|
||||
|
||||
|
@ -168,10 +166,7 @@ class HttpApi(HttpApiBase):
|
|||
|
||||
def download_file(self, from_url, to_path, path_params=None):
|
||||
url = construct_url_path(from_url, path_params=path_params)
|
||||
response, response_data = self.connection.send(
|
||||
url, data=None, method=HTTPMethod.GET,
|
||||
headers=self._authorized_headers()
|
||||
)
|
||||
response, response_data = self.connection.send(url, data=None, method=HTTPMethod.GET, headers=BASE_HEADERS)
|
||||
|
||||
if os.path.isdir(to_path):
|
||||
filename = extract_filename_from_headers(response.info())
|
||||
|
@ -188,11 +183,6 @@ class HttpApi(HttpApiBase):
|
|||
# None means that the exception will be passed further to the caller
|
||||
return None
|
||||
|
||||
def _authorized_headers(self):
|
||||
headers = dict(BASE_HEADERS)
|
||||
headers['Authorization'] = 'Bearer %s' % self.access_token
|
||||
return headers
|
||||
|
||||
def _get_api_spec_path(self):
|
||||
return self.get_option('spec_path')
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ if PY3:
|
|||
else:
|
||||
BUILTINS_NAME = '__builtin__'
|
||||
|
||||
EXPECTED_BASE_HEADERS = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
|
||||
class FakeFtdHttpApiPlugin(HttpApi):
|
||||
def __init__(self, conn):
|
||||
|
@ -66,6 +71,7 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
|
||||
assert 'ACCESS_TOKEN' == self.ftd_plugin.access_token
|
||||
assert 'REFRESH_TOKEN' == self.ftd_plugin.refresh_token
|
||||
assert {'Authorization': 'Bearer ACCESS_TOKEN'} == self.ftd_plugin.connection._auth
|
||||
expected_body = json.dumps({'grant_type': 'password', 'username': 'foo', 'password': 'bar'})
|
||||
self.connection_mock.send.assert_called_once_with(mock.ANY, expected_body, headers=mock.ANY, method=mock.ANY)
|
||||
|
||||
|
@ -79,6 +85,7 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
|
||||
assert 'NEW_ACCESS_TOKEN' == self.ftd_plugin.access_token
|
||||
assert 'NEW_REFRESH_TOKEN' == self.ftd_plugin.refresh_token
|
||||
assert {'Authorization': 'Bearer NEW_ACCESS_TOKEN'} == self.ftd_plugin.connection._auth
|
||||
expected_body = json.dumps({'grant_type': 'refresh_token', 'refresh_token': 'REFRESH_TOKEN'})
|
||||
self.connection_mock.send.assert_called_once_with(mock.ANY, expected_body, headers=mock.ANY, method=mock.ANY)
|
||||
|
||||
|
@ -91,7 +98,8 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
|
||||
self.ftd_plugin.login('foo', 'bar')
|
||||
|
||||
self.connection_mock.send.assert_called_once_with('/testFakeLoginUrl', mock.ANY, headers=mock.ANY, method=mock.ANY)
|
||||
self.connection_mock.send.assert_called_once_with('/testFakeLoginUrl', mock.ANY, headers=mock.ANY,
|
||||
method=mock.ANY)
|
||||
self.ftd_plugin.hostvars['token_path'] = temp_token_path
|
||||
|
||||
def test_login_raises_exception_when_no_refresh_token_and_no_credentials(self):
|
||||
|
@ -134,7 +142,7 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
assert {ResponseParams.SUCCESS: True, ResponseParams.STATUS_CODE: 200,
|
||||
ResponseParams.RESPONSE: exp_resp} == resp
|
||||
self.connection_mock.send.assert_called_once_with('/test/123?at=0', '{"name": "foo"}', method=HTTPMethod.PUT,
|
||||
headers=self._expected_headers())
|
||||
headers=EXPECTED_BASE_HEADERS)
|
||||
|
||||
def test_send_request_should_return_empty_dict_when_no_response_data(self):
|
||||
self.connection_mock.send.return_value = self._connection_response(None)
|
||||
|
@ -143,7 +151,7 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
|
||||
assert {ResponseParams.SUCCESS: True, ResponseParams.STATUS_CODE: 200, ResponseParams.RESPONSE: {}} == resp
|
||||
self.connection_mock.send.assert_called_once_with('/test', None, method=HTTPMethod.GET,
|
||||
headers=self._expected_headers())
|
||||
headers=EXPECTED_BASE_HEADERS)
|
||||
|
||||
def test_send_request_should_return_error_info_when_http_error_raises(self):
|
||||
self.connection_mock.send.side_effect = HTTPError('http://testhost.com', 500, '', {},
|
||||
|
@ -214,7 +222,7 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
resp = self.ftd_plugin.upload_file('/tmp/test.txt', '/files')
|
||||
|
||||
assert {'id': '123'} == resp
|
||||
exp_headers = self._expected_headers()
|
||||
exp_headers = dict(EXPECTED_BASE_HEADERS)
|
||||
exp_headers['Content-Length'] = len('--Encoded data--')
|
||||
exp_headers['Content-Type'] = 'multipart/form-data'
|
||||
self.connection_mock.send.assert_called_once_with('/files', data='--Encoded data--',
|
||||
|
@ -261,10 +269,3 @@ class TestFtdHttpApi(unittest.TestCase):
|
|||
response_text = json.dumps(response) if type(response) is dict else response
|
||||
response_data = BytesIO(response_text.encode() if response_text else ''.encode())
|
||||
return response_mock, response_data
|
||||
|
||||
def _expected_headers(self):
|
||||
return {
|
||||
'Accept': 'application/json',
|
||||
'Authorization': 'Bearer %s' % self.ftd_plugin.access_token,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue