Merge "Add additional_headers to session and adapter"
This commit is contained in:
@@ -45,13 +45,18 @@ class Adapter(object):
|
|||||||
:type logger: logging.Logger
|
:type logger: logging.Logger
|
||||||
:param dict allow: Extra filters to pass when discovering API versions.
|
:param dict allow: Extra filters to pass when discovering API versions.
|
||||||
(optional)
|
(optional)
|
||||||
|
:param dict additional_headers: Additional headers that should be attached
|
||||||
|
to every request passing through the
|
||||||
|
adapter. Headers of the same name specified
|
||||||
|
per request will take priority.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@positional()
|
@positional()
|
||||||
def __init__(self, session, service_type=None, service_name=None,
|
def __init__(self, session, service_type=None, service_name=None,
|
||||||
interface=None, region_name=None, endpoint_override=None,
|
interface=None, region_name=None, endpoint_override=None,
|
||||||
version=None, auth=None, user_agent=None,
|
version=None, auth=None, user_agent=None,
|
||||||
connect_retries=None, logger=None, allow={}):
|
connect_retries=None, logger=None, allow={},
|
||||||
|
additional_headers=None):
|
||||||
# NOTE(jamielennox): when adding new parameters to adapter please also
|
# NOTE(jamielennox): when adding new parameters to adapter please also
|
||||||
# add them to the adapter call in httpclient.HTTPClient.__init__ as
|
# add them to the adapter call in httpclient.HTTPClient.__init__ as
|
||||||
# well as to load_adapter_from_argparse below if the argument is
|
# well as to load_adapter_from_argparse below if the argument is
|
||||||
@@ -69,6 +74,7 @@ class Adapter(object):
|
|||||||
self.connect_retries = connect_retries
|
self.connect_retries = connect_retries
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.allow = allow
|
self.allow = allow
|
||||||
|
self.additional_headers = additional_headers or {}
|
||||||
|
|
||||||
def _set_endpoint_filter_kwargs(self, kwargs):
|
def _set_endpoint_filter_kwargs(self, kwargs):
|
||||||
if self.service_type:
|
if self.service_type:
|
||||||
@@ -100,6 +106,9 @@ class Adapter(object):
|
|||||||
if self.allow:
|
if self.allow:
|
||||||
kwargs.setdefault('allow', self.allow)
|
kwargs.setdefault('allow', self.allow)
|
||||||
|
|
||||||
|
for k, v in self.additional_headers.items():
|
||||||
|
kwargs.setdefault('headers', {}).setdefault(k, v)
|
||||||
|
|
||||||
return self.session.request(url, method, **kwargs)
|
return self.session.request(url, method, **kwargs)
|
||||||
|
|
||||||
def get_token(self, auth=None):
|
def get_token(self, auth=None):
|
||||||
|
|||||||
@@ -200,6 +200,10 @@ class Session(object):
|
|||||||
can be followed by a request. Either an integer
|
can be followed by a request. Either an integer
|
||||||
for a specific count or True/False for
|
for a specific count or True/False for
|
||||||
forever/never. (optional, default to 30)
|
forever/never. (optional, default to 30)
|
||||||
|
:param dict additional_headers: Additional headers that should be attached
|
||||||
|
to every request passing through the
|
||||||
|
session. Headers of the same name specified
|
||||||
|
per request will take priority.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
user_agent = None
|
user_agent = None
|
||||||
@@ -211,7 +215,7 @@ class Session(object):
|
|||||||
@positional(2)
|
@positional(2)
|
||||||
def __init__(self, auth=None, session=None, original_ip=None, verify=True,
|
def __init__(self, auth=None, session=None, original_ip=None, verify=True,
|
||||||
cert=None, timeout=None, user_agent=None,
|
cert=None, timeout=None, user_agent=None,
|
||||||
redirect=_DEFAULT_REDIRECT_LIMIT):
|
redirect=_DEFAULT_REDIRECT_LIMIT, additional_headers=None):
|
||||||
|
|
||||||
self.auth = auth
|
self.auth = auth
|
||||||
self.session = _construct_session(session)
|
self.session = _construct_session(session)
|
||||||
@@ -220,6 +224,7 @@ class Session(object):
|
|||||||
self.cert = cert
|
self.cert = cert
|
||||||
self.timeout = None
|
self.timeout = None
|
||||||
self.redirect = redirect
|
self.redirect = redirect
|
||||||
|
self.additional_headers = additional_headers or {}
|
||||||
|
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
self.timeout = float(timeout)
|
self.timeout = float(timeout)
|
||||||
@@ -501,6 +506,9 @@ class Session(object):
|
|||||||
headers['Content-Type'] = 'application/json'
|
headers['Content-Type'] = 'application/json'
|
||||||
kwargs['data'] = self._json.encode(json)
|
kwargs['data'] = self._json.encode(json)
|
||||||
|
|
||||||
|
for k, v in self.additional_headers.items():
|
||||||
|
headers.setdefault(k, v)
|
||||||
|
|
||||||
kwargs.setdefault('verify', self.verify)
|
kwargs.setdefault('verify', self.verify)
|
||||||
|
|
||||||
if requests_auth:
|
if requests_auth:
|
||||||
|
|||||||
@@ -930,6 +930,56 @@ class AdapterTest(utils.TestCase):
|
|||||||
self.TEST_URL,
|
self.TEST_URL,
|
||||||
'GET')
|
'GET')
|
||||||
|
|
||||||
|
def test_additional_headers(self):
|
||||||
|
session_key = uuid.uuid4().hex
|
||||||
|
session_val = uuid.uuid4().hex
|
||||||
|
adapter_key = uuid.uuid4().hex
|
||||||
|
adapter_val = uuid.uuid4().hex
|
||||||
|
request_key = uuid.uuid4().hex
|
||||||
|
request_val = uuid.uuid4().hex
|
||||||
|
text = uuid.uuid4().hex
|
||||||
|
|
||||||
|
url = 'http://keystone.test.com'
|
||||||
|
self.requests_mock.get(url, text=text)
|
||||||
|
|
||||||
|
sess = client_session.Session(
|
||||||
|
additional_headers={session_key: session_val})
|
||||||
|
adap = adapter.Adapter(session=sess,
|
||||||
|
additional_headers={adapter_key: adapter_val})
|
||||||
|
resp = adap.get(url, headers={request_key: request_val})
|
||||||
|
|
||||||
|
request = self.requests_mock.last_request
|
||||||
|
|
||||||
|
self.assertEqual(resp.text, text)
|
||||||
|
self.assertEqual(session_val, request.headers[session_key])
|
||||||
|
self.assertEqual(adapter_val, request.headers[adapter_key])
|
||||||
|
self.assertEqual(request_val, request.headers[request_key])
|
||||||
|
|
||||||
|
def test_additional_headers_overrides(self):
|
||||||
|
header = uuid.uuid4().hex
|
||||||
|
session_val = uuid.uuid4().hex
|
||||||
|
adapter_val = uuid.uuid4().hex
|
||||||
|
request_val = uuid.uuid4().hex
|
||||||
|
|
||||||
|
url = 'http://keystone.test.com'
|
||||||
|
self.requests_mock.get(url)
|
||||||
|
|
||||||
|
sess = client_session.Session(additional_headers={header: session_val})
|
||||||
|
adap = adapter.Adapter(session=sess)
|
||||||
|
|
||||||
|
adap.get(url)
|
||||||
|
self.assertEqual(session_val,
|
||||||
|
self.requests_mock.last_request.headers[header])
|
||||||
|
|
||||||
|
adap.additional_headers[header] = adapter_val
|
||||||
|
adap.get(url)
|
||||||
|
self.assertEqual(adapter_val,
|
||||||
|
self.requests_mock.last_request.headers[header])
|
||||||
|
|
||||||
|
adap.get(url, headers={header: request_val})
|
||||||
|
self.assertEqual(request_val,
|
||||||
|
self.requests_mock.last_request.headers[header])
|
||||||
|
|
||||||
|
|
||||||
class TCPKeepAliveAdapterTest(utils.TestCase):
|
class TCPKeepAliveAdapterTest(utils.TestCase):
|
||||||
|
|
||||||
|
|||||||
10
releasenotes/notes/additional-headers-f2d16f85f5abe942.yaml
Normal file
10
releasenotes/notes/additional-headers-f2d16f85f5abe942.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
prelude: >
|
||||||
|
Allow specifying additional_headers to the session and the adapter to add
|
||||||
|
headers to all requests that pass through these objects.
|
||||||
|
features:
|
||||||
|
- Add the ability to provide additional_headers to the session and adapter
|
||||||
|
object. This will allow clients particularly to provide additional ways to
|
||||||
|
identify their requests. It will also hopefully provide an intermediate way
|
||||||
|
to handle setting microversions until we support them directly with
|
||||||
|
keystoneauth.
|
||||||
Reference in New Issue
Block a user