components/openstack/glance/patches/03-Partial_Content.patch
branchs11-update
changeset 4072 db0cec748ec0
child 5405 66fd59fecd68
equal deleted inserted replaced
4067:4be1f488dda8 4072:db0cec748ec0
       
     1 Provide for HTTP Range requests in Glance API, and return correct 206
       
     2 Partial Content.
       
     3 
       
     4 See community bugs:
       
     5  https://bugs.launchpad.net/glance/+bug/1399851
       
     6  https://bugs.launchpad.net/glance/+bug/1417069
       
     7 
       
     8 --- glance-2014.2.2/glance/api/v2/image_data.py.~1~	2015-02-05 07:19:44.000000000 -0800
       
     9 +++ glance-2014.2.2/glance/api/v2/image_data.py	2015-02-23 14:04:17.091921881 -0800
       
    10 @@ -199,6 +199,8 @@ class ResponseSerializer(wsgi.JSONRespon
       
    11  
       
    12      def download(self, response, image):
       
    13          offset, chunk_size = 0, None
       
    14 +
       
    15 +        # Initially attempt to get "Content-Range" request
       
    16          range_val = response.request.get_content_range()
       
    17  
       
    18          if range_val:
       
    19 @@ -210,6 +212,21 @@ class ResponseSerializer(wsgi.JSONRespon
       
    20              if range_val.stop is not None:
       
    21                  chunk_size = range_val.stop - offset
       
    22  
       
    23 +            # Return 206 Partial Content
       
    24 +            response.status_int = 206
       
    25 +        else:
       
    26 +            # Try for "Range" request header if ContentRange not present
       
    27 +            range_obj = response.request.get_range()
       
    28 +            if range_obj:
       
    29 +                if range_obj.start is not None:
       
    30 +                    offset = range_obj.start
       
    31 +
       
    32 +                if range_obj.end is not None:
       
    33 +                    chunk_size = range_obj.end - offset
       
    34 +
       
    35 +                # Return 206 Partial Content
       
    36 +                response.status_int = 206
       
    37 +
       
    38          response.headers['Content-Type'] = 'application/octet-stream'
       
    39  
       
    40          try:
       
    41 @@ -229,7 +246,9 @@ class ResponseSerializer(wsgi.JSONRespon
       
    42              response.headers['Content-MD5'] = image.checksum
       
    43          #NOTE(markwash): "response.app_iter = ..." also erroneously resets the
       
    44          # content-length
       
    45 -        response.headers['Content-Length'] = str(image.size)
       
    46 +        # NOTE(mattk): Should be set to chunk_size or image.size
       
    47 +        response.headers['Content-Length'] = \
       
    48 +            str(chunk_size) if chunk_size != 0 else str(image.size)
       
    49  
       
    50      def upload(self, response, result):
       
    51          response.status_int = 204
       
    52 --- glance-2014.2.2/glance/common/wsgi.py.~1~	2015-02-05 07:19:44.000000000 -0800
       
    53 +++ glance-2014.2.2/glance/common/wsgi.py	2015-02-23 14:04:17.092284573 -0800
       
    54 @@ -556,7 +556,7 @@ class Request(webob.Request):
       
    55          return self.accept_language.best_match(langs)
       
    56  
       
    57      def get_content_range(self):
       
    58 -        """Return the `Range` in a request."""
       
    59 +        """Return the `Content-Range` in a request."""
       
    60          range_str = self.headers.get('Content-Range')
       
    61          if range_str is not None:
       
    62              range_ = webob.byterange.ContentRange.parse(range_str)
       
    63 @@ -565,6 +565,16 @@ class Request(webob.Request):
       
    64                  raise webob.exc.HTTPBadRequest(explanation=msg)
       
    65              return range_
       
    66  
       
    67 +    def get_range(self):
       
    68 +        """Return the 'Range' in a reqyest."""
       
    69 +        range_str = self.headers.get('Range')
       
    70 +        if range_str is not None:
       
    71 +            range_ = webob.byterange.Range.parse(range_str)
       
    72 +            if range_ is None:
       
    73 +                msg = _('Malformed Range header: %s') % range_str
       
    74 +                raise webob.exc.HTTPBadRequest(explanation=msg)
       
    75 +            return range_
       
    76 +
       
    77  
       
    78  class JSONRequestDeserializer(object):
       
    79      def has_body(self, request):