components/openstack/glance/patches/03-Partial_Content.patch
author Rich Burridge <rich.burridge@oracle.com>
Tue, 02 May 2017 17:33:26 -0700
changeset 7964 d9801318ed3d
parent 6883 beebcb25bedf
permissions -rw-r--r--
25981468 Build ilmbase and openexr with the GNU compilers

Provide for HTTP Range requests in Glance API, and return correct 206
Partial Content.

See community bugs:
 https://bugs.launchpad.net/glance/+bug/1399851
 https://bugs.launchpad.net/glance/+bug/1417069

--- glance-12.0.0/glance/api/v2/image_data.py.~1~	2016-04-07 00:37:11.000000000 -0700
+++ glance-12.0.0/glance/api/v2/image_data.py	2016-06-27 18:46:02.584760065 -0700
@@ -281,6 +281,8 @@ class ResponseSerializer(wsgi.JSONRespon
 
     def download(self, response, image):
         offset, chunk_size = 0, None
+
+        # Initially attempt to get "Content-Range" request
         range_val = response.request.get_content_range()
 
         if range_val:
@@ -292,6 +294,21 @@ class ResponseSerializer(wsgi.JSONRespon
             if range_val.stop is not None:
                 chunk_size = range_val.stop - offset
 
+            # Return 206 Partial Content
+            response.status_int = 206
+        else:
+            # Try for "Range" request header if ContentRange not present
+            range_obj = response.request.get_range()
+            if range_obj:
+                if range_obj.start is not None:
+                    offset = range_obj.start
+
+                if range_obj.end is not None:
+                    chunk_size = range_obj.end - offset
+
+                # Return 206 Partial Content
+                response.status_int = 206
+
         response.headers['Content-Type'] = 'application/octet-stream'
 
         try:
@@ -317,7 +334,10 @@ class ResponseSerializer(wsgi.JSONRespon
             response.headers['Content-MD5'] = image.checksum
         # NOTE(markwash): "response.app_iter = ..." also erroneously resets the
         # content-length
-        response.headers['Content-Length'] = str(image.size)
+        # NOTE(mattk): Should be set to chunk_size or image.size
+        response.headers['Content-Length'] = \
+            str(chunk_size) if (chunk_size is not None and chunk_size != 0) \
+            else str(image.size)
 
     def upload(self, response, result):
         response.status_int = 204
--- glance-12.0.0/glance/common/wsgi.py.~1~	2016-04-07 00:37:13.000000000 -0700
+++ glance-12.0.0/glance/common/wsgi.py	2016-06-27 18:46:02.583921325 -0700
@@ -762,7 +762,7 @@ class Request(webob.Request):
         return self.accept_language.best_match(langs)
 
     def get_content_range(self):
-        """Return the `Range` in a request."""
+        """Return the `Content-Range` in a request."""
         range_str = self.headers.get('Content-Range')
         if range_str is not None:
             range_ = webob.byterange.ContentRange.parse(range_str)
@@ -771,6 +771,16 @@ class Request(webob.Request):
                 raise webob.exc.HTTPBadRequest(explanation=msg)
             return range_
 
+    def get_range(self):
+        """Return the 'Range' in a reqyest."""
+        range_str = self.headers.get('Range')
+        if range_str is not None:
+            range_ = webob.byterange.Range.parse(range_str)
+            if range_ is None:
+                msg = _('Malformed Range header: %s') % range_str
+                raise webob.exc.HTTPBadRequest(explanation=msg)
+            return range_
+
 
 class JSONRequestDeserializer(object):
     valid_transfer_encoding = frozenset(['chunked', 'compress', 'deflate',