Permalink
Browse files

Merge pull request #614 from ib-lundgren/multipart_fix

Better content-type detection and unicode fix
  • Loading branch information...
2 parents 2f50cb9 + 6a9d59e commit 355003b400e18be508e530400c2c232f9ce0041c @kennethreitz committed May 15, 2012
Showing with 43 additions and 6 deletions.
  1. +43 −6 requests/auth.py
View
@@ -60,14 +60,51 @@ def __init__(self, client_key,
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' }
+ u_header = unicode('Authorization')
+ if u_header in r.headers:
+ auth_header = r.headers[u_header].encode('utf-8')
+ del r.headers[u_header]
+ r.headers['Authorization'] = auth_header
+
+ return r
class HTTPBasicAuth(AuthBase):

0 comments on commit 355003b

Please sign in to comment.