From 73635df1b2680e8b4ac7babc0ab0bc004fbb21b7 Mon Sep 17 00:00:00 2001 From: Ian Ross and Ian Cordasco Date: Fri, 19 Jul 2013 15:13:28 -0500 Subject: [PATCH 1/4] Start work on sending cookies back On 401's the cookies received aren't sent back to the server. See: #1336 --- requests/auth.py | 11 +++++++++-- test_requests.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index fab05cf3..665b1db3 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -18,7 +18,6 @@ from base64 import b64encode from .compat import urlparse, str from .utils import parse_dict_header - log = logging.getLogger(__name__) CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' @@ -146,6 +145,7 @@ class HTTPDigestAuth(AuthBase): def handle_401(self, r, **kwargs): """Takes the given response and tries digest-auth, if needed.""" + from .models import PreparedRequest num_401_calls = getattr(self, 'num_401_calls', 1) s_auth = r.headers.get('www-authenticate', '') @@ -159,10 +159,17 @@ class HTTPDigestAuth(AuthBase): # to allow our new request to reuse the same one. r.content r.raw.release_conn() + prepared_request = PreparedRequest() + prepared_request.url = r.request.url + prepared_request.body = r.request.body + prepared_request.headers = r.request.headers.copy() + prepared_request.hooks = r.request.hooks + prepared_request.prepare_cookies(r.cookies) r.request.headers['Authorization'] = self.build_digest_header(r.request.method, r.request.url) - _r = r.connection.send(r.request, **kwargs) + _r = r.connection.send(prepared_request, **kwargs) _r.history.append(r) + _r.request = prepared_request return _r diff --git a/test_requests.py b/test_requests.py index 27d5e676..756bc879 100755 --- a/test_requests.py +++ b/test_requests.py @@ -289,6 +289,22 @@ class RequestsTestCase(unittest.TestCase): r = s.get(url) self.assertEqual(r.status_code, 200) + def test_DIGEST_AUTH_RETURNS_COOKIE(self): + url = httpbin('digest-auth', 'auth', 'user', 'pass') + auth = HTTPDigestAuth('user', 'pass') + r = requests.get(url) + assert r.cookies['fake'] == 'fake_value' + + r = requests.get(url, auth=auth) + assert r.status_code == 200 + + def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self): + url = httpbin('digest-auth', 'auth', 'user', 'pass') + auth = HTTPDigestAuth('user', 'pass') + s = requests.Session() + s.get(url, auth=auth) + assert s.cookies['fake'] == 'fake_value' + def test_DIGEST_STREAM(self): auth = HTTPDigestAuth('user', 'pass') From c25a72ea248358641dd9048f0062d83625cc703b Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Fri, 19 Jul 2013 15:55:02 -0500 Subject: [PATCH 2/4] Make the regular tests pass I broke Digest Auth completely --- requests/auth.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index 665b1db3..43b3beca 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -159,17 +159,19 @@ class HTTPDigestAuth(AuthBase): # to allow our new request to reuse the same one. r.content r.raw.release_conn() - prepared_request = PreparedRequest() - prepared_request.url = r.request.url - prepared_request.body = r.request.body - prepared_request.headers = r.request.headers.copy() - prepared_request.hooks = r.request.hooks - prepared_request.prepare_cookies(r.cookies) + prep = PreparedRequest() + prep.method = r.request.method + prep.url = r.request.url + prep.body = r.request.body + prep.headers = r.request.headers.copy() + prep.hooks = r.request.hooks + prep.prepare_cookies(r.cookies) - r.request.headers['Authorization'] = self.build_digest_header(r.request.method, r.request.url) - _r = r.connection.send(prepared_request, **kwargs) + prep.headers['Authorization'] = self.build_digest_header( + prep.method, prep.url) + _r = r.connection.send(prep, **kwargs) _r.history.append(r) - _r.request = prepared_request + _r.request = prep return _r From 972089826e830670cdaec774bb4eb8a3f349b661 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Fri, 26 Jul 2013 10:50:19 -0500 Subject: [PATCH 3/4] Fixed finally. Also requires updated httpbin.org --- requests/sessions.py | 4 ++++ test_requests.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/requests/sessions.py b/requests/sessions.py index 664465d8..ca7e2170 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -449,6 +449,10 @@ class Session(SessionRedirectMixin): r = dispatch_hook('response', hooks, r, **kwargs) # Persist cookies + if r.history: + # If the hooks create history then we want those cookies too + for resp in r.history: + extract_cookies_to_jar(self.cookies, resp.request, resp.raw) extract_cookies_to_jar(self.cookies, request, r.raw) # Redirect resolving generator. diff --git a/test_requests.py b/test_requests.py index 756bc879..1c581066 100755 --- a/test_requests.py +++ b/test_requests.py @@ -285,7 +285,7 @@ class RequestsTestCase(unittest.TestCase): self.assertEqual(r.status_code, 401) s = requests.session() - s.auth = auth + s.auth = HTTPDigestAuth('user', 'pass') r = s.get(url) self.assertEqual(r.status_code, 200) From 286ddb672d3ff39b1807402a7d9ca569a86516d6 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sat, 27 Jul 2013 23:08:46 -0400 Subject: [PATCH 4/4] Take advantage of the new copy method --- requests/auth.py | 8 +------- requests/sessions.py | 5 +---- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index 43b3beca..81a3d937 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -145,7 +145,6 @@ class HTTPDigestAuth(AuthBase): def handle_401(self, r, **kwargs): """Takes the given response and tries digest-auth, if needed.""" - from .models import PreparedRequest num_401_calls = getattr(self, 'num_401_calls', 1) s_auth = r.headers.get('www-authenticate', '') @@ -159,12 +158,7 @@ class HTTPDigestAuth(AuthBase): # to allow our new request to reuse the same one. r.content r.raw.release_conn() - prep = PreparedRequest() - prep.method = r.request.method - prep.url = r.request.url - prep.body = r.request.body - prep.headers = r.request.headers.copy() - prep.hooks = r.request.hooks + prep = r.request.copy() prep.prepare_cookies(r.cookies) prep.headers['Authorization'] = self.build_digest_header( diff --git a/requests/sessions.py b/requests/sessions.py index ca7e2170..11a90f23 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -74,10 +74,7 @@ class SessionRedirectMixin(object): # ((resp.status_code is codes.see_other)) while (('location' in resp.headers and resp.status_code in REDIRECT_STATI)): - prepared_request = PreparedRequest() - prepared_request.body = req.body - prepared_request.headers = req.headers.copy() - prepared_request.hooks = req.hooks + prepared_request = req.copy() resp.content # Consume socket so it can be released