diff options
| author | Tim Burke <tim.burke@gmail.com> | 2015-12-30 11:15:02 -0800 |
|---|---|---|
| committer | Tim Burke <tim.burke@gmail.com> | 2015-12-30 11:56:36 -0800 |
| commit | 39b1a31d8a187534f54e32e9aec2cb2bb839a390 (patch) | |
| tree | 7f751227c62507e686582ab54e1a20cbab434e9f /swiftclient/client.py | |
| parent | ab65eef4ce4096410bdfec9ea7d8780f800321df (diff) | |
| download | python-swiftclient-39b1a31d8a187534f54e32e9aec2cb2bb839a390.tar.gz | |
Wrap raw iterators to ensure we send entire contents to server
Currently, if you attempt to stream an upload from an iterator, as in
def data():
yield 'foo'
yield ''
yield 'bar'
conn.put_object('c', 'o', data())
... requests will faithfully emit a zero-length chunk, ending the
transfer. Swift will then close the connection, possibly (if Connection:
keep-alive was set) after attempting to parse the next chunk as a new
request.
Now, Swift will receive all of the bytes from the iterable, and any
zero-byte chunks will be ignored.
This will be fixed in requests [1], but not until an eventual 3.0.0
release.
[1] https://github.com/kennethreitz/requests/pull/2631
Change-Id: I19579ed7a0181ac3f488433e7c1839f7f7a040b8
Diffstat (limited to 'swiftclient/client.py')
| -rw-r--r-- | swiftclient/client.py | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/swiftclient/client.py b/swiftclient/client.py index 925b396..ae723a3 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -32,7 +32,7 @@ import six from swiftclient import version as swiftclient_version from swiftclient.exceptions import ClientException from swiftclient.utils import ( - LengthWrapper, ReadableToIterable, parse_api_response) + iter_wrapper, LengthWrapper, ReadableToIterable, parse_api_response) # Defautl is 100, increase to 256 http_client._MAXHEADERS = 256 @@ -1126,6 +1126,10 @@ def put_object(url, token=None, container=None, name=None, contents=None, warn_msg = ('%s object has no "read" method, ignoring chunk_size' % type(contents).__name__) warnings.warn(warn_msg, stacklevel=2) + # Match requests's is_stream test + if hasattr(contents, '__iter__') and not isinstance(contents, ( + six.text_type, six.binary_type, list, tuple, dict)): + contents = iter_wrapper(contents) conn.request('PUT', path, contents, headers) resp = conn.getresponse() |
