From 503146ae39c1c050abf39d2fd5a43595e621cdf7 Mon Sep 17 00:00:00 2001 From: Ib Lundgren Date: Mon, 1 Sep 2014 18:02:36 +0100 Subject: [PATCH] Allow headers to be overriden on oauth2.fetch_token Twitters application-only client credentials flow struggle when provided with an accept header. This allow users to omit it. Also include a new default encoding and charset content type header. --- requests_oauthlib/oauth2_session.py | 13 ++++++++++--- tests/test_compliance_fixes.py | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/requests_oauthlib/oauth2_session.py b/requests_oauthlib/oauth2_session.py index 4ca81fd3..aabc6334 100644 --- a/requests_oauthlib/oauth2_session.py +++ b/requests_oauthlib/oauth2_session.py @@ -112,7 +112,7 @@ def authorization_url(self, url, state=None, **kwargs): def fetch_token(self, token_url, code=None, authorization_response=None, body='', auth=None, username=None, password=None, method='POST', - verify=True, **kwargs): + headers=None, verify=True, **kwargs): """Generic method for fetching an access token from the token endpoint. If you are using the MobileApplicationClient you will want to use @@ -131,6 +131,7 @@ def fetch_token(self, token_url, code=None, authorization_response=None, :param method: The HTTP method used to make the request. Defaults to POST, but may also be GET. Other methods should be added as needed. + :param headers: Dict to default request headers with. :param verify: Verify SSL certificate. :param kwargs: Extra parameters to include in the token request. :return: A token dict @@ -153,15 +154,19 @@ def fetch_token(self, token_url, code=None, authorization_response=None, redirect_uri=self.redirect_uri, username=username, password=password, **kwargs) + headers = headers or { + 'Accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', + } if method.upper() == 'POST': r = self.post(token_url, data=dict(urldecode(body)), - headers={'Accept': 'application/json'}, auth=auth, + headers=headers, auth=auth, verify=verify) log.debug('Prepared fetch token request body %s', body) elif method.upper() == 'GET': # if method is not 'POST', switch body to querystring and GET r = self.get(token_url, params=dict(urldecode(body)), - headers={'Accept': 'application/json'}, auth=auth, + headers=headers, auth=auth, verify=verify) log.debug('Prepared fetch token request querystring %s', body) else: @@ -169,6 +174,8 @@ def fetch_token(self, token_url, code=None, authorization_response=None, log.debug('Request to fetch token completed with status %s.', r.status_code) + log.debug('Request headers were %s', r.request.headers) + log.debug('Request body was %s', r.request.body) log.debug('Response headers were %s and content %s.', r.headers, r.text) log.debug('Invoking %d token response hooks.', diff --git a/tests/test_compliance_fixes.py b/tests/test_compliance_fixes.py index 59686f87..93074a0d 100644 --- a/tests/test_compliance_fixes.py +++ b/tests/test_compliance_fixes.py @@ -19,6 +19,7 @@ def test_fetch_access_token(self): facebook.post = mock.MagicMock() response = requests.Response() response.status_code = 200 + response.request = mock.MagicMock() response._content = 'access_token=urlencoded'.encode('UTF-8') response.headers['Content-Type'] = 'text/plain' facebook.post.return_value = response @@ -38,6 +39,7 @@ def test_fetch_access_token(self): linkedin.post = mock.MagicMock() response = requests.Response() response.status_code = 200 + response.request = mock.MagicMock() response._content = '{"access_token":"linkedin"}'.encode('UTF-8') linkedin.post.return_value = response @@ -56,6 +58,7 @@ def test_fetch_access_token(self): weibo.post = mock.MagicMock() response = requests.Response() response.status_code = 200 + response.request = mock.MagicMock() response._content = '{"access_token":"weibo"}'.encode('UTF-8') weibo.post.return_value = response