Example #1
0
 def handle_request_range(self, file):
     # check if we have a range in the request
     ranges = None
     header_range = self.request.getHeader('Range', None)
     if_range = self.request.getHeader('If-Range', None)
     if header_range is not None:
         ranges = parseRange(header_range)
         if if_range is not None:
             # We delete the ranges, which causes us to skip to the 200
             # response.
             return {}
         # XXX: multipart ranges not implemented
         if ranges and len(ranges) == 1:
             try:
                 length = file.getSize()
                 [(start, end)] = expandRanges(ranges, length)
                 size = end - start
                 self.request.response.setHeader('Content-Length', size)
                 self.request.response.setHeader(
                     'Content-Range',
                     'bytes {0}-{1}/{2}'.format(start, end - 1, length))
                 self.request.response.setStatus(206)  # Partial content
                 return dict(start=start, end=end)
             except ValueError:
                 return {}
     return {}
Example #2
0
    def index_html(self, REQUEST, RESPONSE=None):
        """Default view for VirtualBinary file"""
        ranges = None
        if RESPONSE is None:
            RESPONSE = REQUEST.RESPONSE

        if self.__content_class__ is None:
            # Build your own headers
            RESPONSE.setHeader('Content-Type', self.content_type)
            RESPONSE.setHeader('Content-Length', self.size)

        else:
            # Call index_html method of content class with a fake
            # self.data attribute which will return empty value
            # Use this artifice to make sure content class is not loading
            # all data in memory since it is better to return a stream iterator
            # There is an exception with multiple range
            if REQUEST.environ.has_key('HTTP_RANGE'):
                ranges = parseRange(REQUEST.environ.get('HTTP_RANGE'))
            ## in case of mutiple range we don't know do with an iterator
            if ranges is not None and len(ranges) > 1:
                ## call normally OFS.image with data
                return self.__content_class__.index_html(
                    self, REQUEST, RESPONSE)
            else:
                ### now we deal correctly with 304 header
                if self._if_modified_since_request_handler(REQUEST, RESPONSE):
                    self.ZCacheable_set(None)
                    return ''
                ### set correctly header
                RESPONSE.setHeader('Last-Modified',
                                   rfc1123_date(self._p_mtime))
                RESPONSE.setHeader('Content-Type', self.content_type)
                RESPONSE.setHeader('Content-Length', self.size)
                RESPONSE.setHeader('Accept-Ranges', 'bytes')
                self.ZCacheable_set(None)

            # This is a default header that can be bypassed by other products
            # such as attachment field.
            if RESPONSE.getHeader('content-disposition') is None:
                # headers are in lower case in HTTPResponse
                RESPONSE.setHeader('Content-Disposition',
                                   'inline; filename="%s"' % self.filename)
        if ranges and len(ranges) == 1:
            ## is an range request with one range ,
            ## return an iterator with this range
            [(start, end)] = ranges

            if end is None:
                end = self.size

            iterator = range_filestream_iterator(self.path,
                                                 start,
                                                 end,
                                                 mode='rb')
            return iterator
        else:
            return filestream_iterator(self.path, mode='rb')
Example #3
0
    def index_html(self, REQUEST, RESPONSE=None):
        """Default view for VirtualBinary file"""
        ranges = None
        if RESPONSE is None:
            RESPONSE = REQUEST.RESPONSE

        if self.__content_class__ is None:
            # Build your own headers
            RESPONSE.setHeader('Content-Type', self.content_type)
            RESPONSE.setHeader('Content-Length', self.size)

        else:
            # Call index_html method of content class with a fake
            # self.data attribute which will return empty value
            # Use this artifice to make sure content class is not loading
            # all data in memory since it is better to return a stream iterator
            # There is an exception with multiple range
            if REQUEST.environ.has_key('HTTP_RANGE'):
                ranges = parseRange(REQUEST.environ.get('HTTP_RANGE'))
             ## in case of mutiple range we don't know do with an iterator
            if ranges is not None and len(ranges) > 1:
                ## call normally OFS.image with data
                return self.__content_class__.index_html(self, REQUEST, RESPONSE)
            else:
                ### now we deal correctly with 304 header
                if self._if_modified_since_request_handler(REQUEST, RESPONSE):
                    self.ZCacheable_set(None)
                    return ''
                ### set correctly header
                RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
                RESPONSE.setHeader('Content-Type', self.content_type)
                RESPONSE.setHeader('Content-Length', self.size)
                RESPONSE.setHeader('Accept-Ranges', 'bytes')
                self.ZCacheable_set(None)

            # This is a default header that can be bypassed by other products
            # such as attachment field.
            if RESPONSE.getHeader('content-disposition') is None:
                # headers are in lower case in HTTPResponse
                RESPONSE.setHeader(
                    'Content-Disposition',
                    'inline; filename="%s"' % self.filename
                    )
        if ranges and len(ranges) == 1:
            ## is an range request with one range ,
            ## return an iterator with this range
            [(start,end)] = ranges

            if end is None:
                end = self.size

            iterator = range_filestream_iterator(self.path, start, end, mode='rb')
            return iterator
        else:
            return filestream_iterator(self.path, mode='rb')
Example #4
0
def handleRequestRange(instance, length, REQUEST, RESPONSE):
    # check if we have a range in the request
    ranges = None
    range = REQUEST.get_header('Range', None)
    request_range = REQUEST.get_header('Request-Range', None)
    if request_range is not None:
        # Netscape 2 through 4 and MSIE 3 implement a draft version
        # Later on, we need to serve a different mime-type as well.
        range = request_range
    if_range = REQUEST.get_header('If-Range', None)
    if range is not None:
        ranges = parseRange(range)
        if if_range is not None:
            # Only send ranges if the data isn't modified, otherwise send
            # the whole object. Support both ETags and Last-Modified dates!
            if len(if_range) > 1 and if_range[:2] == 'ts':
                # ETag:
                if if_range != instance.http__etag():
                    # Modified, so send a normal response. We delete
                    # the ranges, which causes us to skip to the 200
                    # response.
                    ranges = None
            else:
                # Date
                date = if_range.split(';')[0]
                try:
                    mod_since = long(DateTime(date).timeTime())
                except Exception:
                    mod_since = None
                if mod_since is not None:
                    if instance._p_mtime:
                        last_mod = long(instance._p_mtime)
                    else:
                        last_mod = long(0)
                    if last_mod > mod_since:
                        # Modified, so send a normal response. We delete
                        # the ranges, which causes us to skip to the 200
                        # response.
                        ranges = None
            RESPONSE.setHeader('Accept-Ranges', 'bytes')
        if ranges and len(ranges) == 1:
            try:
                [(start, end)] = expandRanges(ranges, length)
                size = end - start
                RESPONSE.setHeader('Content-Length', size)
                RESPONSE.setHeader(
                    'Content-Range',
                    'bytes {0}-{1}/{2}'.format(start, end - 1, length))
                RESPONSE.setStatus(206)  # Partial content
                return dict(start=start, end=end)
            except ValueError:
                return {}
    return {}
Example #5
0
def handleRequestRange(instance, length, REQUEST, RESPONSE):
    # check if we have a range in the request
    ranges = None
    range = REQUEST.get_header('Range', None)
    request_range = REQUEST.get_header('Request-Range', None)
    if request_range is not None:
        # Netscape 2 through 4 and MSIE 3 implement a draft version
        # Later on, we need to serve a different mime-type as well.
        range = request_range
    if_range = REQUEST.get_header('If-Range', None)
    if range is not None:
        ranges = parseRange(range)
        if if_range is not None:
            # Only send ranges if the data isn't modified, otherwise send
            # the whole object. Support both ETags and Last-Modified dates!
            if len(if_range) > 1 and if_range[:2] == 'ts':
                # ETag:
                if if_range != instance.http__etag():
                    # Modified, so send a normal response. We delete
                    # the ranges, which causes us to skip to the 200
                    # response.
                    ranges = None
            else:
                # Date
                date = if_range.split(';')[0]
                try:
                    mod_since = long(DateTime(date).timeTime())
                except Exception:
                    mod_since = None
                if mod_since is not None:
                    if instance._p_mtime:
                        last_mod = long(instance._p_mtime)
                    else:
                        last_mod = 0
                    if last_mod > mod_since:
                        # Modified, so send a normal response. We delete
                        # the ranges, which causes us to skip to the 200
                        # response.
                        ranges = None
            RESPONSE.setHeader('Accept-Ranges', 'bytes')
        if ranges and len(ranges) == 1:
            try:
                [(start, end)] = expandRanges(ranges, length)
                size = end - start
                RESPONSE.setHeader('Content-Length', size)
                RESPONSE.setHeader(
                    'Content-Range',
                    'bytes {0}-{1}/{2}'.format(start, end - 1, length))
                RESPONSE.setStatus(206)  # Partial content
                return dict(start=start, end=end)
            except ValueError:
                return {}
    return {}
Example #6
0
 def have_ranges(self):
     """Return range information if partial content was requested.
     """
     range_header = self.request.environ.get('HTTP_RANGE', None)
     if range_header is not None:
         range_if_header = self.request.environ.get('HTTP_IF_RANGE', None)
         if range_if_header:
             # If there is an If-Range header, with a date
             # prior to the modification, return all the file.
             if_date = parse_datetime(range_if_header)
             if (if_date and self._modification_datetime
                     and self._modification_datetime > if_date):
                 return (None, None, None)
         ranges = parseRange(range_header)
         if len(ranges) == 1:
             size = self.context.get_file_size()
             satisfiable = expandRanges(ranges, size)
             if len(satisfiable) == 1:
                 return (satisfiable[0][0], satisfiable[0][1] - 1, size)
             return (None, None, size)
     return (None, None, None)
Example #7
0
 def have_ranges(self):
     """Return range information if partial content was requested.
     """
     range_header = self.request.environ.get('HTTP_RANGE', None)
     if range_header is not None:
         range_if_header = self.request.environ.get('HTTP_IF_RANGE', None)
         if range_if_header:
             # If there is an If-Range header, with a date
             # prior to the modification, return all the file.
             if_date = parse_datetime(range_if_header)
             if (if_date and self._modification_datetime and
                 self._modification_datetime > if_date):
                 return (None, None, None)
         ranges = parseRange(range_header)
         if len(ranges) == 1:
             size = self.context.get_file_size()
             satisfiable = expandRanges(ranges, size)
             if len(satisfiable) == 1:
                 return (satisfiable[0][0], satisfiable[0][1] - 1, size)
             return (None, None, size)
     return (None, None, None)
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.assertTrue(
         result == sets,
         'Expected %r, got %r' % (sets, result))
 def expectNone(self, header):
     result = parseRange(header)
     self.assertTrue(result is None, 'Expected None, got %r' % result)
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.assertTrue(result == sets,
                     'Expected %s, got %s' % ( ` sets `, ` result `))
 def expectNone(self, header):
     result = parseRange(header)
     self.assertTrue(result is None, 'Expected None, got %s' % ` result `)
Example #12
0
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.failUnless(result == sets,
         'Expected %s, got %s' % (`sets`, `result`))
Example #13
0
 def expectNone(self, header):
     result = parseRange(header)
     self.failUnless(result is None, 'Expected None, got %s' % `result`)
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.assertTrue(result == sets,
         'Expected %s, got %s' % (`sets`, `result`))
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.assertTrue(result == sets, 'Expected %r, got %r' % (sets, result))
Example #16
0
 def expectSets(self, header, sets):
     result = parseRange(header)
     self.assertTrue(result == sets, f'Expected {sets!r}, got {result!r}')