From 8a1d53eb3ac19cabbb85e2bdfae418cd6fa84612 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Tue, 28 Aug 2012 12:51:01 +0800 Subject: [PATCH 1/4] Correct OAuth1 with query or data. --- requests/auth.py | 49 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index 0adfa0f5..05bff4b2 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -33,6 +33,7 @@ except ImportError as exc: log = logging.getLogger(__name__) CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' +CONTENT_TYPE_MULTI_PART = 'multipart/form-data' def _basic_auth_str(username, password): @@ -74,34 +75,34 @@ class OAuth1(AuthBase): Parameters may be included from the body if the content-type is urlencoded, if no content type is set an educated guess is made. """ - contenttype = r.headers.get('Content-Type', None) + # split(";") because Content-Type may be "multipart/form-data; boundary=xxxxx" + contenttype = r.headers.get('Content-Type', '').split(";")[0].lower() # extract_params will not give params unless the body is a properly # formatted string, a dictionary or a list of 2-tuples. decoded_body = extract_params(r.data) - _ct = (contenttype is None) - _ct = _ct or contenttype.lower() == CONTENT_TYPE_FORM_URLENCODED - - if _ct and decoded_body != None: - # extract_params can only check the present r.data and does not know - # of r.files, thus an extra check is performed. We know that - # if files are present the request will not have - # Content-type: x-www-form-urlencoded. We guess it will have - # a mimetype of multipart/form-encoded and if this is not the case - # we assume the correct header will be set later. - if r.files: - # Omit body data in the signing and since it will always - # be empty (cant add paras to body if multipart) and we wish - # to preserve body. - r.headers['Content-Type'] = 'multipart/form-encoded' - r.url, r.headers, _ = self.client.sign( - unicode(r.full_url), unicode(r.method), None, r.headers) - else: - # Normal signing - r.headers['Content-Type'] = 'application/x-www-form-urlencoded' - r.url, r.headers, r.data = self.client.sign( - unicode(r.full_url), unicode(r.method), r.data, r.headers) - + # extract_params can only check the present r.data and does not know + # of r.files, thus an extra check is performed. We know that + # if files are present the request will not have + # Content-type: x-www-form-urlencoded. We guess it will have + # a mimetype of multipart/form-encoded and if this is not the case + # we assume the correct header will be set later. + _cond = True + if r.files and contenttype == CONTENT_TYPE_MULTI_PART: + # Omit body data in the signing and since it will always + # be empty (cant add paras to body if multipart) and we wish + # to preserve body. + r.headers['Content-Type'] = CONTENT_TYPE_MULTI_PART + r.url, r.headers, _ = self.client.sign( + unicode(r.full_url), unicode(r.method), None, r.headers) + elif decoded_body != None and contenttype in (CONTENT_TYPE_FORM_URLENCODED, ''): + # Normal signing + r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED + r.url, r.headers, r.data = self.client.sign( + unicode(r.full_url), unicode(r.method), r.data, r.headers) + else: + _cond = False + if _cond: # Both flows add params to the URL by using r.full_url, # so this prevents adding it again later r.params = {} From 46ff4b386281f619506c13f8a6548ecd3e4d3559 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Tue, 28 Aug 2012 15:20:53 +0800 Subject: [PATCH 2/4] Fix the comment too. If content-type is multipart/form-data, keep the header. --- requests/auth.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index 05bff4b2..64d61ce4 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -85,14 +85,13 @@ class OAuth1(AuthBase): # of r.files, thus an extra check is performed. We know that # if files are present the request will not have # Content-type: x-www-form-urlencoded. We guess it will have - # a mimetype of multipart/form-encoded and if this is not the case + # a mimetype of multipart/form-data and if this is not the case # we assume the correct header will be set later. _cond = True if r.files and contenttype == CONTENT_TYPE_MULTI_PART: # Omit body data in the signing and since it will always # be empty (cant add paras to body if multipart) and we wish # to preserve body. - r.headers['Content-Type'] = CONTENT_TYPE_MULTI_PART r.url, r.headers, _ = self.client.sign( unicode(r.full_url), unicode(r.method), None, r.headers) elif decoded_body != None and contenttype in (CONTENT_TYPE_FORM_URLENCODED, ''): From aded42f23247e86495654ddd85ae9e000bbe9c1e Mon Sep 17 00:00:00 2001 From: ayanamist Date: Tue, 28 Aug 2012 15:24:09 +0800 Subject: [PATCH 3/4] Try to keep the header too if content-type is application/x-www-form-urlencoded --- requests/auth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requests/auth.py b/requests/auth.py index 64d61ce4..8b0aeb50 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -96,7 +96,8 @@ class OAuth1(AuthBase): unicode(r.full_url), unicode(r.method), None, r.headers) elif decoded_body != None and contenttype in (CONTENT_TYPE_FORM_URLENCODED, ''): # Normal signing - r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED + if not contenttype: + r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED r.url, r.headers, r.data = self.client.sign( unicode(r.full_url), unicode(r.method), r.data, r.headers) else: From babac7368b9aa34fd1f0e5d29d4f80c2006ad614 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Tue, 28 Aug 2012 15:38:13 +0800 Subject: [PATCH 4/4] Change variable name "_cond" -> "_oauth_signed". --- requests/auth.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index 8b0aeb50..6c5264e4 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -87,7 +87,7 @@ class OAuth1(AuthBase): # Content-type: x-www-form-urlencoded. We guess it will have # a mimetype of multipart/form-data and if this is not the case # we assume the correct header will be set later. - _cond = True + _oauth_signed = True if r.files and contenttype == CONTENT_TYPE_MULTI_PART: # Omit body data in the signing and since it will always # be empty (cant add paras to body if multipart) and we wish @@ -101,8 +101,8 @@ class OAuth1(AuthBase): r.url, r.headers, r.data = self.client.sign( unicode(r.full_url), unicode(r.method), r.data, r.headers) else: - _cond = False - if _cond: + _oauth_signed = False + if _oauth_signed: # Both flows add params to the URL by using r.full_url, # so this prevents adding it again later r.params = {}