Skip to content

Commit

Permalink
Lazily encode data, params, files
Browse files Browse the repository at this point in the history
Previously, data, params, and files were encoded and stored in
Request.__init__, and subsequently put into service during
Request.send. The problem with this approach is that hooks and auth
callables need to be aware of the eager encoding, and if they touch the
originals, make sure to update the encoded versions.

A better approach is to only encode late in the sending process. This
way, hooks and auth callables can safely make changes without fear of
the old, encoded variant overriding it.
  • Loading branch information
idan committed May 2, 2012
1 parent d240b1f commit 324336e
Showing 1 changed file with 15 additions and 21 deletions.
36 changes: 15 additions & 21 deletions requests/models.py
Expand Up @@ -114,9 +114,9 @@ def __init__(self,
if 'HTTPS_PROXY' in os.environ:
self.proxies['https'] = os.environ['HTTPS_PROXY']

self.data, self._enc_data = self._encode_params(data)
self.params, self._enc_params = self._encode_params(params)
self.files, self._enc_files = self._encode_files(files)
self.data = data
self.params = params
self.files = files

#: :class:`Response <Response>` instance, containing
#: content and metadata of HTTP Response, once :attr:`sent <send>`.
Expand Down Expand Up @@ -314,19 +314,12 @@ def _encode_params(data):
Will successfully encode parameters when passed as a dict or a list of
2-tuples. Order is retained if data is a list of 2-tuples but abritrary
if parameters are supplied as a dict.
If the data supplied contains parameters, encodes each parameter in it,
and returns a list of tuples containing the encoded parameters, and a
urlencoded version of that.
Otherwise, assumes the data is already encoded appropriately, and
returns it twice.
"""

if isinstance(data, bytes):
return data, data
return data
if isinstance(data, str):
return data, data
return data
elif hasattr(data, '__iter__'):
try:
dict(data)
Expand All @@ -340,14 +333,14 @@ def _encode_params(data):
result.append(
(k.encode('utf-8') if isinstance(k, str) else k,
v.encode('utf-8') if isinstance(v, str) else v))
return result, urlencode(result, doseq=True)
return urlencode(result, doseq=True)
else:
return data, data
return data

def _encode_files(self, files):

if (not files) or isinstance(self.data, str):
return None, None
return None

try:
fields = self.data.copy()
Expand All @@ -365,7 +358,7 @@ def _encode_files(self, files):

(body, content_type) = encode_multipart_formdata(fields)

return files, (body, content_type)
return (body, content_type)

@property
def full_url(self):
Expand Down Expand Up @@ -406,11 +399,12 @@ def full_url(self):

url = (urlunparse([scheme, netloc, path, params, query, fragment]))

if self._enc_params:
enc_params = self._encode_params(self.params)
if enc_params:
if urlparse(url).query:
url = '%s&%s' % (url, self._enc_params)
url = '%s&%s' % (url, enc_params)
else:
url = '%s?%s' % (url, self._enc_params)
url = '%s?%s' % (url, enc_params)

if self.config.get('encode_uri', True):
url = requote_uri(url)
Expand Down Expand Up @@ -499,11 +493,11 @@ def send(self, anyway=False, prefetch=False):

# Multi-part file uploads.
if self.files:
(body, content_type) = self._enc_files
(body, content_type) = self._encode_files(self.files)
else:
if self.data:

body = self._enc_data
body = self._encode_params(self.data)
if isinstance(self.data, str):
content_type = None
else:
Expand Down

0 comments on commit 324336e

Please sign in to comment.