summaryrefslogtreecommitdiff
path: root/keystoneclient/tests/unit/test_session.py
diff options
context:
space:
mode:
authorTobias Diaz <tobias.deb@gmail.com>2016-08-23 17:13:24 +0200
committerSamuel de Medeiros Queiroz <samueldmq@gmail.com>2017-01-05 10:19:25 -0300
commit3e56e0d7e5e1a76d806a3bc1f6d5ef9070f95771 (patch)
treecf73b3ba11fab18e8d64d220366282e969f3a062 /keystoneclient/tests/unit/test_session.py
parent39373aa40b085c3277fe393de0f638f12ac16d53 (diff)
downloadpython-keystoneclient-3e56e0d7e5e1a76d806a3bc1f6d5ef9070f95771.tar.gz
Prevent MemoryError when logging response bodies
Response bodies are loaded into memory prior to being logged. Loading huge response bodies may result in a MemoryError. This patch proposes that only JSON and TEXT responses be logged, i.e when the Content-Type header is application/json or application/text. Responses that do not include or have a different Content-Type header will have their body omitted. This is a sort of backport of the fix for keystoneauth sessions, see I93b6fff73368c4f58bdebf8566c4948b50980cee Co-Authored-By: Samuel de Medeiros Queiroz <samueldmq@gmail.com> Closes-bug: 1616105 Change-Id: I8f43eee3a0b35041c6cf672e476f8151cf2f8d14
Diffstat (limited to 'keystoneclient/tests/unit/test_session.py')
-rw-r--r--keystoneclient/tests/unit/test_session.py56
1 files changed, 51 insertions, 5 deletions
diff --git a/keystoneclient/tests/unit/test_session.py b/keystoneclient/tests/unit/test_session.py
index 8fb364a..168cbb7 100644
--- a/keystoneclient/tests/unit/test_session.py
+++ b/keystoneclient/tests/unit/test_session.py
@@ -149,7 +149,8 @@ class SessionTests(utils.TestCase):
in order to redact secure headers while debug is true.
"""
session = client_session.Session(verify=False)
- headers = {'HEADERA': 'HEADERVALB'}
+ headers = {'HEADERA': 'HEADERVALB',
+ 'Content-Type': 'application/json'}
security_headers = {'Authorization': uuid.uuid4().hex,
'X-Auth-Token': uuid.uuid4().hex,
'X-Subject-Token': uuid.uuid4().hex, }
@@ -183,12 +184,56 @@ class SessionTests(utils.TestCase):
session = client_session.Session()
body = uuid.uuid4().hex
- self.stub_url('GET', text=body, status_code=400)
+ self.stub_url('GET', text=body, status_code=400,
+ headers={'Content-Type': 'application/text'})
resp = session.get(self.TEST_URL, raise_exc=False)
self.assertEqual(resp.status_code, 400)
self.assertIn(body, self.logger.output)
+ def test_logging_body_only_for_text_and_json_content_types(self):
+ """Verify response body is only logged in specific content types.
+
+ Response bodies are logged only when the response's Content-Type header
+ is set to application/json or application/text. This prevents us to get
+ an unexpected MemoryError when reading arbitrary responses, such as
+ streams.
+ """
+ OMITTED_BODY = ('Omitted, Content-Type is set to %s. Only '
+ 'application/json and application/text responses '
+ 'have their bodies logged.')
+ session = client_session.Session(verify=False)
+
+ # Content-Type is not set
+ body = jsonutils.dumps({'token': {'id': '...'}})
+ self.stub_url('POST', text=body)
+ session.post(self.TEST_URL)
+ self.assertNotIn(body, self.logger.output)
+ self.assertIn(OMITTED_BODY % None, self.logger.output)
+
+ # Content-Type is set to text/xml
+ body = '<token><id>...</id></token>'
+ self.stub_url('POST', text=body, headers={'Content-Type': 'text/xml'})
+ session.post(self.TEST_URL)
+ self.assertNotIn(body, self.logger.output)
+ self.assertIn(OMITTED_BODY % 'text/xml', self.logger.output)
+
+ # Content-Type is set to application/json
+ body = jsonutils.dumps({'token': {'id': '...'}})
+ self.stub_url('POST', text=body,
+ headers={'Content-Type': 'application/json'})
+ session.post(self.TEST_URL)
+ self.assertIn(body, self.logger.output)
+ self.assertNotIn(OMITTED_BODY % 'application/json', self.logger.output)
+
+ # Content-Type is set to application/text
+ body = uuid.uuid4().hex
+ self.stub_url('POST', text=body,
+ headers={'Content-Type': 'application/text'})
+ session.post(self.TEST_URL)
+ self.assertIn(body, self.logger.output)
+ self.assertNotIn(OMITTED_BODY % 'application/text', self.logger.output)
+
def test_unicode_data_in_debug_output(self):
"""Verify that ascii-encodable data is logged without modification."""
session = client_session.Session(verify=False)
@@ -315,7 +360,8 @@ class SessionTests(utils.TestCase):
"auth_username": "verybadusername",
"auth_method": "CHAP"}}}
body_json = jsonutils.dumps(body)
- response = mock.Mock(text=body_json, status_code=200, headers={})
+ response = mock.Mock(text=body_json, status_code=200,
+ headers={'content-type': 'application/json'})
session._http_log_response(response, logger)
self.assertEqual(1, logger.debug.call_count)
@@ -772,7 +818,7 @@ class SessionAuthTests(utils.TestCase):
self.stub_url('GET',
text=response,
- headers={'Content-Type': 'text/html'})
+ headers={'Content-Type': 'application/json'})
resp = sess.get(self.TEST_URL, logger=logger)
@@ -968,7 +1014,7 @@ class AdapterTest(utils.TestCase):
response = uuid.uuid4().hex
self.stub_url('GET', text=response,
- headers={'Content-Type': 'text/html'})
+ headers={'Content-Type': 'application/json'})
resp = adpt.get(self.TEST_URL, logger=logger)