From c24665b59352006120ef33624ae8177ff68990bd Mon Sep 17 00:00:00 2001 From: Ib Lundgren Date: Tue, 15 May 2012 17:20:01 +0200 Subject: [PATCH] Better content-type detection and unicode fix --- requests/auth.py | 49 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index a20c545..c9a1a02 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -60,14 +60,51 @@ class OAuth1(AuthBase): signature_type, rsa_key, verifier) def __call__(self, r): + """Add OAuth parameters to the request. + + 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) - decoded_body = extract_params(r.data) + # 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) if contenttype == None and decoded_body != None: - r.headers['Content-Type'] = 'application/x-www-form-urlencoded' - - r.url, r.headers, r.data = self.client.sign( - unicode(r.url), unicode(r.method), r.data, r.headers) - return r + # 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.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.url), unicode(r.method), r.data, r.headers) + + # Having the authorization header, key or value, in unicode will + # result in UnicodeDecodeErrors when the request is concatenated + # by httplib. This can easily be seen when attaching files. + # Note that simply encoding the value is not enough since Python + # saves the type of first key set. Thus we remove and re-add. + # >>> d = {u'a':u'foo'} + # >>> d['a'] = 'foo' + # >>> d + # { u'a' : 'foo' } + if u'Authorization' in r.headers: + auth_header = r.headers[u'Authorization'].encode('utf-8') + del r.headers[u'Authorization'] + r.headers['Authorization'] = auth_header + print r.headers + + return r class HTTPBasicAuth(AuthBase): -- 2.34.1