def conditional_response_app(self, environ, start_response): """ Like the normal __call__ interface, but checks conditional headers: * If-Modified-Since (304 Not Modified; only on GET, HEAD) * If-None-Match (304 Not Modified; only on GET, HEAD) * Range (406 Partial Content; only on GET, HEAD) """ req = BaseRequest(environ) headerlist = self._abs_headerlist(environ) method = environ.get('REQUEST_METHOD', 'GET') if method in self._safe_methods: status304 = False if req.if_none_match and self.etag: status304 = self.etag in req.if_none_match elif req.if_modified_since and self.last_modified: status304 = self.last_modified <= req.if_modified_since if status304: start_response('304 Not Modified', filter_headers(headerlist)) return EmptyResponse(self._app_iter) if (req.range and self in req.if_range and self.content_range is None and method in ('HEAD', 'GET') and self.status_code == 200 and self.content_length is not None): content_range = req.range.content_range(self.content_length) if content_range is None: iter_close(self._app_iter) body = bytes_("Requested range not satisfiable: %s" % req.range) headerlist = [ ('Content-Length', str(len(body))), ('Content-Range', str(ContentRange(None, None, self.content_length))), ('Content-Type', 'text/plain'), ] + filter_headers(headerlist) start_response('416 Requested Range Not Satisfiable', headerlist) if method == 'HEAD': return () return [body] else: app_iter = self.app_iter_range(content_range.start, content_range.stop) if app_iter is not None: # the following should be guaranteed by # Range.range_for_length(length) assert content_range.start is not None headerlist = [ ('Content-Length', str(content_range.stop - content_range.start)), ('Content-Range', str(content_range)), ] + filter_headers(headerlist, ('content-length', )) start_response('206 Partial Content', headerlist) if method == 'HEAD': return EmptyResponse(app_iter) return app_iter start_response(self.status, headerlist) if method == 'HEAD': return EmptyResponse(self._app_iter) return self._app_iter
def test_contentrange_iter(): contentrange = ContentRange(0, 99, 100) assert_true(type(contentrange.__iter__()), iter) assert_true(ContentRange.parse('bytes 0-99/100').__class__, ContentRange) eq_(ContentRange.parse(None), None) eq_(ContentRange.parse('0-99 100'), None) eq_(ContentRange.parse('bytes 0-99 100'), None) eq_(ContentRange.parse('bytes 0-99/xxx'), None) eq_(ContentRange.parse('bytes 0 99/100'), None) eq_(ContentRange.parse('bytes */100').__class__, ContentRange) eq_(ContentRange.parse('bytes A-99/100'), None) eq_(ContentRange.parse('bytes 0-B/100'), None) eq_(ContentRange.parse('bytes 99-0/100'), None) eq_(ContentRange.parse('bytes 0 99/*'), None)
def test_contentrange_iter(): contentrange = ContentRange(0, 99, 100) assert isinstance(contentrange, Iterable) assert ContentRange.parse("bytes 0-99/100").__class__ == ContentRange assert ContentRange.parse(None) is None assert ContentRange.parse("0-99 100") is None assert ContentRange.parse("bytes 0-99 100") is None assert ContentRange.parse("bytes 0-99/xxx") is None assert ContentRange.parse("bytes 0 99/100") is None assert ContentRange.parse("bytes */100").__class__ == ContentRange assert ContentRange.parse("bytes A-99/100") is None assert ContentRange.parse("bytes 0-B/100") is None assert ContentRange.parse("bytes 99-0/100") is None assert ContentRange.parse("bytes 0 99/*") is None
def serialize_content_range(value): if isinstance(value, (tuple, list)): if len(value) not in (2, 3): raise ValueError( "When setting content_range to a list/tuple, it must " "be length 2 or 3 (not %r)" % value) if len(value) == 2: begin, end = value length = None else: begin, end, length = value value = ContentRange(begin, end, length) value = str(value).strip() if not value: return None return value
def test_is_content_range_valid_stop_greater_than_length_response(): contentrange = ContentRange(0, 99, 100) assert_equal(_is_content_range_valid(0, 99, 90, response=True), False)
def test_is_content_range_valid_start_none(): contentrange = ContentRange(0, 99, 100) assert_equal(_is_content_range_valid(None, 99, 90), False)
def test_is_content_range_valid_length_none(): contentrange = ContentRange(0, 99, 100) assert_equal(_is_content_range_valid(0, 99, None), True)
def test_contentrange_str_start_none(): contentrange = ContentRange(0, 99, 100) contentrange.start = None contentrange.stop = None assert_equal(str(contentrange), 'bytes */100')
def test_contentrange_str_length_start(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 0 99/*'), None)
def test_contentrange_repr(): contentrange = ContentRange(0, 99, 100) assert repr(contentrange) == "<ContentRange bytes 0-98/100>"
def test_contentrange_repr(): contentrange = ContentRange(0, 99, 100) assert_true(contentrange.__repr__(), '<ContentRange bytes 0-98/100>')
def test_cr_parse_invalid_length(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 0-99/xxx'), None)
def test_cr_parse_no_range(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 0 99/100'), None)
def test_cr_parse_no_bytes(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('0-99 100'), None)
def test_cr_parse_missing_slash(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 0-99 100'), None)
def test_cr_parse_none(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse(None), None)
def test_cr_parse_ok(): contentrange = ContentRange(0, 99, 100) assert_true(contentrange.parse('bytes 0-99/100').__class__, ContentRange)
def test_contentrange_iter(): contentrange = ContentRange(0, 99, 100) assert_true(type(contentrange.__iter__()), iter)
def test_is_content_range_valid_stop_greater_than_length(): contentrange = ContentRange(0, 99, 100) assert_equal(_is_content_range_valid(0, 99, 90), True)
def test_contentrange_str(): contentrange = ContentRange(0, 99, None) eq_(str(contentrange), 'bytes 0-98/*') contentrange = ContentRange(None, None, 100) eq_(str(contentrange), 'bytes */100')
def test_contentrange_bad_input(): with pytest.raises(ValueError): ContentRange(None, 99, None)
def test_cr_parse_parse_problem_2(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 0-B/100'), None)
def test_contentrange_str(): contentrange = ContentRange(0, 99, None) assert str(contentrange) == "bytes 0-98/*" contentrange = ContentRange(None, None, 100) assert str(contentrange) == "bytes */100"
def test_cr_parse_content_invalid(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes 99-0/100'), None)
def test_cr_parse_range_star(): contentrange = ContentRange(0, 99, 100) assert_equal(contentrange.parse('bytes */100').__class__, ContentRange)
def test_contentrange_str_length_none(): contentrange = ContentRange(0, 99, 100) contentrange.length = None assert_equal(str(contentrange), 'bytes 0-98/*')