Handle create/update of images with unknown size

It may not be possible to know in advance the total
size of image data which is to be uploaded, for example
if the data is being piped to stdin.

To handle this we use HTTP Transfer-Encoding: chunked
and do not set any image size headers.

Various subtly different cases needed to be handled for
both image-create and image-update, including:

 * input from named pipe
 * piped input of zero size
 * regular file of zero length

Fix for bug 1056220.

Change-Id: I0c7f0a64d883e058993b954a1c465c5b057f2bcf
This commit is contained in:
Stuart McLaren
2012-09-26 12:56:51 +00:00
parent cdc06d9fdb
commit 727aadbc25
4 changed files with 44 additions and 15 deletions
+19 -1
View File
@@ -146,7 +146,19 @@ class HTTPClient(object):
try:
conn_url = os.path.normpath('%s/%s' % (self.endpoint_path, url))
conn.request(method, conn_url, **kwargs)
if kwargs['headers'].get('Transfer-Encoding') == 'chunked':
conn.putrequest(method, conn_url)
for header, value in kwargs['headers'].items():
conn.putheader(header, value)
conn.endheaders()
chunk = kwargs['body'].read(CHUNKSIZE)
# Chunk it, baby...
while chunk:
conn.send('%x\r\n%s\r\n' % (len(chunk), chunk))
chunk = kwargs['body'].read(CHUNKSIZE)
conn.send('0\r\n\r\n')
else:
conn.request(method, conn_url, **kwargs)
resp = conn.getresponse()
except socket.gaierror as e:
message = "Error finding address for %(url)s: %(e)s" % locals()
@@ -201,6 +213,12 @@ class HTTPClient(object):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
'application/octet-stream')
if 'body' in kwargs:
if (hasattr(kwargs['body'], 'read')
and method.lower() in ('post', 'put')):
# We use 'Transfer-Encoding: chunked' because
# body size may not always be known in advance.
kwargs['headers']['Transfer-Encoding'] = 'chunked'
return self._http_request(url, method, **kwargs)