From aa68be645f80dde5a52dc5a32d74304921e97288 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 10 Feb 2022 13:47:56 -0500 Subject: [PATCH] Return Content-Range in responses. --- src/allmydata/storage/http_server.py | 12 +++++------ src/allmydata/test/test_storage_http.py | 27 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/allmydata/storage/http_server.py b/src/allmydata/storage/http_server.py index 88de18f12..bb4ef6c00 100644 --- a/src/allmydata/storage/http_server.py +++ b/src/allmydata/storage/http_server.py @@ -24,6 +24,7 @@ from twisted.web import http import attr from werkzeug.http import parse_range_header, parse_content_range_header from werkzeug.routing import BaseConverter +from werkzeug.datastructures import ContentRange # TODO Make sure to use pure Python versions? from cbor2 import dumps, loads @@ -323,11 +324,10 @@ class HTTPServer(object): # TODO limit memory usage data = bucket.read(offset, end - offset) + request.setResponseCode(http.PARTIAL_CONTENT) - # TODO set content-range on response. We we need to expand the - # BucketReader interface to return share's length. - # - # request.setHeader( - # "content-range", range_header.make_content_range(share_length).to_header() - # ) + request.setHeader( + "content-range", + ContentRange("bytes", offset, offset + len(data)).to_header(), + ) return data diff --git a/src/allmydata/test/test_storage_http.py b/src/allmydata/test/test_storage_http.py index bbda00bf6..c864f923c 100644 --- a/src/allmydata/test/test_storage_http.py +++ b/src/allmydata/test/test_storage_http.py @@ -760,3 +760,30 @@ class ImmutableHTTPAPITests(SyncTestCase): ) self.assertEqual(response.code, http.OK) self.assertEqual(result_of(response.content()), uploaded_data) + + def test_validate_content_range_response_to_read(self): + """ + The server responds to ranged reads with an appropriate Content-Range + header. + """ + storage_index, _ = self.upload(1, 26) + + def check_range(requested_range, expected_response): + headers = Headers() + headers.setRawHeaders("range", [requested_range]) + response = result_of( + self.http.client.request( + "GET", + self.http.client.relative_url( + "/v1/immutable/{}/1".format(_encode_si(storage_index)) + ), + headers=headers, + ) + ) + self.assertEqual( + response.headers.getRawHeaders("content-range"), [expected_response] + ) + + check_range("bytes=0-10", "bytes 0-10/*") + # Can't go beyond the end of the immutable! + check_range("bytes=10-100", "bytes 10-25/*")