aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2026-04-08 15:51:42 +0200
committerGitHub Enterprise <[email protected]>2026-04-08 15:51:42 +0200
commit9fc1337ba1b9c8198c030a57cb5c5942bbb2b725 (patch)
tree3f214196abb46d99b07eabfb4da1dddd7d10cb2c /src
parentdon't hard fail if .pending folder is not empty on oplog export (#926) (diff)
downloadzen-9fc1337ba1b9c8198c030a57cb5c5942bbb2b725.tar.xz
zen-9fc1337ba1b9c8198c030a57cb5c5942bbb2b725.zip
use correct return code for unsupported multirange requests in objectstore (#927)
Diffstat (limited to 'src')
-rw-r--r--src/zenserver-test/objectstore-tests.cpp62
-rw-r--r--src/zenserver/storage/objectstore/objectstore.cpp4
2 files changed, 64 insertions, 2 deletions
diff --git a/src/zenserver-test/objectstore-tests.cpp b/src/zenserver-test/objectstore-tests.cpp
index 1f6a7675c..ff2314089 100644
--- a/src/zenserver-test/objectstore-tests.cpp
+++ b/src/zenserver-test/objectstore-tests.cpp
@@ -158,6 +158,68 @@ TEST_CASE("objectstore.s3client")
CHECK(EmptyList.Objects.empty());
}
+TEST_CASE("objectstore.range-requests")
+{
+ ZenServerInstance Instance(TestEnv);
+ const uint16_t Port = Instance.SpawnServerAndWaitUntilReady("--objectstore-enabled");
+ REQUIRE(Port != 0);
+
+ HttpClient Client(Instance.GetBaseUri() + "/obj/");
+
+ IoBuffer Blob = CreateRandomBlob(1024);
+ MemoryView BlobView = Blob.GetView();
+ std::string ObjectPath = "bucket/bkt/range-test/data.bin";
+
+ HttpClient::Response PutResult = Client.Put(ObjectPath, IoBuffer(Blob));
+ REQUIRE(PutResult);
+
+ // Full GET without Range header
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath);
+ CHECK(Result.StatusCode == HttpResponseCode::OK);
+ CHECK_EQ(Result.ResponsePayload.GetSize(), 1024u);
+ CHECK(Result.ResponsePayload.GetView().EqualBytes(BlobView));
+ }
+
+ // Single range: bytes 100-199
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath, {{"Range", "bytes=100-199"}});
+ CHECK(Result.StatusCode == HttpResponseCode::PartialContent);
+ CHECK_EQ(Result.ResponsePayload.GetSize(), 100u);
+ CHECK(Result.ResponsePayload.GetView().EqualBytes(BlobView.Mid(100, 100)));
+ }
+
+ // Range starting at zero: bytes 0-49
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath, {{"Range", "bytes=0-49"}});
+ CHECK(Result.StatusCode == HttpResponseCode::PartialContent);
+ CHECK_EQ(Result.ResponsePayload.GetSize(), 50u);
+ CHECK(Result.ResponsePayload.GetView().EqualBytes(BlobView.Mid(0, 50)));
+ }
+
+ // Range at end of file: bytes 1000-1023
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath, {{"Range", "bytes=1000-1023"}});
+ CHECK(Result.StatusCode == HttpResponseCode::PartialContent);
+ CHECK_EQ(Result.ResponsePayload.GetSize(), 24u);
+ CHECK(Result.ResponsePayload.GetView().EqualBytes(BlobView.Mid(1000, 24)));
+ }
+
+ // Multiple ranges: not supported, falls back to 200 with full body per RFC 7233
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath, {{"Range", "bytes=0-49,100-149"}});
+ CHECK(Result.StatusCode == HttpResponseCode::OK);
+ CHECK_EQ(Result.ResponsePayload.GetSize(), 1024u);
+ CHECK(Result.ResponsePayload.GetView().EqualBytes(BlobView));
+ }
+
+ // Out-of-bounds range: should return 400
+ {
+ HttpClient::Response Result = Client.Get(ObjectPath, {{"Range", "bytes=2000-2099"}});
+ CHECK(Result.StatusCode == HttpResponseCode::BadRequest);
+ }
+}
+
TEST_SUITE_END();
} // namespace zen::tests
diff --git a/src/zenserver/storage/objectstore/objectstore.cpp b/src/zenserver/storage/objectstore/objectstore.cpp
index d6516fa1a..e34cd0445 100644
--- a/src/zenserver/storage/objectstore/objectstore.cpp
+++ b/src/zenserver/storage/objectstore/objectstore.cpp
@@ -639,8 +639,8 @@ HttpObjectStoreService::GetObject(HttpRouterRequest& Request, const std::string_
HttpRanges Ranges;
if (Request.ServerRequest().TryGetRanges(Ranges); Ranges.size() > 1)
{
- // Only a single range is supported
- return Request.ServerRequest().WriteResponse(HttpResponseCode::BadRequest);
+ // Multi-range is not supported, fall back to full response per RFC 7233
+ Ranges.clear();
}
FileContents File;