Skip to content

Commit 2079ab5

Browse files
authored
fix: avoid leaking sub-session created for '_auth_request' (#789)
Closes #658.
1 parent 6de903b commit 2079ab5

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

google/auth/transport/requests.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -340,17 +340,19 @@ def __init__(
340340
self._default_host = default_host
341341

342342
if auth_request is None:
343-
auth_request_session = requests.Session()
343+
self._auth_request_session = requests.Session()
344344

345345
# Using an adapter to make HTTP requests robust to network errors.
346346
# This adapter retrys HTTP requests when network errors occur
347347
# and the requests seems safely retryable.
348348
retry_adapter = requests.adapters.HTTPAdapter(max_retries=3)
349-
auth_request_session.mount("https://", retry_adapter)
349+
self._auth_request_session.mount("https://", retry_adapter)
350350

351351
# Do not pass `self` as the session here, as it can lead to
352352
# infinite recursion.
353-
auth_request = Request(auth_request_session)
353+
auth_request = Request(self._auth_request_session)
354+
else:
355+
self._auth_request_session = None
354356

355357
# Request instance used by internal methods (for example,
356358
# credentials.refresh).
@@ -533,3 +535,8 @@ def request(
533535
def is_mtls(self):
534536
"""Indicates if the created SSL channel is mutual TLS."""
535537
return self._is_mtls
538+
539+
def close(self):
540+
if self._auth_request_session is not None:
541+
self._auth_request_session.close()
542+
super(AuthorizedSession, self).close()

system_tests/system_tests_sync/test_requests.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ def test_authorized_session_with_service_account_and_self_signed_jwt():
3232

3333
# List Pub/Sub Topics through the REST API
3434
# https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/list
35-
response = session.get("https://pubsub.googleapis.com/v1/projects/{}/topics".format(project_id))
36-
response.raise_for_status()
35+
url = "https://pubsub.googleapis.com/v1/projects/{}/topics".format(project_id)
36+
with session:
37+
response = session.get(url)
38+
response.raise_for_status()
3739

3840
# Check that self-signed JWT was created and is being used
3941
assert credentials._jwt_credentials is not None

tests/transport/test_requests.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def test_constructor_with_auth_request(self):
213213
mock.sentinel.credentials, auth_request=auth_request
214214
)
215215

216-
assert authed_session._auth_request == auth_request
216+
assert authed_session._auth_request is auth_request
217217

218218
def test_request_default_timeout(self):
219219
credentials = mock.Mock(wraps=CredentialsStub())
@@ -504,3 +504,22 @@ def test_configure_mtls_channel_without_client_cert_env(
504504
auth_session.configure_mtls_channel(mock_callback)
505505
assert not auth_session.is_mtls
506506
mock_callback.assert_not_called()
507+
508+
def test_close_wo_passed_in_auth_request(self):
509+
authed_session = google.auth.transport.requests.AuthorizedSession(
510+
mock.sentinel.credentials
511+
)
512+
authed_session._auth_request_session = mock.Mock(spec=["close"])
513+
514+
authed_session.close()
515+
516+
authed_session._auth_request_session.close.assert_called_once_with()
517+
518+
def test_close_w_passed_in_auth_request(self):
519+
http = mock.create_autospec(requests.Session)
520+
auth_request = google.auth.transport.requests.Request(http)
521+
authed_session = google.auth.transport.requests.AuthorizedSession(
522+
mock.sentinel.credentials, auth_request=auth_request
523+
)
524+
525+
authed_session.close() # no raise

0 commit comments

Comments
 (0)