components/openstack/glance/patches/03-Partial_Content.patch
changeset 3998 5bd484384122
child 5405 66fd59fecd68
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/glance/patches/03-Partial_Content.patch	Thu Mar 19 14:41:20 2015 -0700
@@ -0,0 +1,79 @@
+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-2014.2.2/glance/api/v2/image_data.py.~1~	2015-02-05 07:19:44.000000000 -0800
++++ glance-2014.2.2/glance/api/v2/image_data.py	2015-02-23 14:04:17.091921881 -0800
+@@ -199,6 +199,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:
+@@ -210,6 +212,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:
+@@ -229,7 +246,9 @@ 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 != 0 else str(image.size)
+ 
+     def upload(self, response, result):
+         response.status_int = 204
+--- glance-2014.2.2/glance/common/wsgi.py.~1~	2015-02-05 07:19:44.000000000 -0800
++++ glance-2014.2.2/glance/common/wsgi.py	2015-02-23 14:04:17.092284573 -0800
+@@ -556,7 +556,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)
+@@ -565,6 +565,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):
+     def has_body(self, request):