From 045702915c4b63d232b99d86a1ee0b16642098c8 Mon Sep 17 00:00:00 2001 From: Per Larsson Date: Wed, 19 Apr 2023 08:44:34 +0200 Subject: Support for HTTP range header (#245) * Support for HTTP range header. * Implement http range for HTTP sys. * Validate range parameters. --------- Co-authored-by: Stefan Boberg --- zenserver/objectstore/objectstore.cpp | 53 +++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'zenserver/objectstore/objectstore.cpp') diff --git a/zenserver/objectstore/objectstore.cpp b/zenserver/objectstore/objectstore.cpp index 950505bcb..e5739418e 100644 --- a/zenserver/objectstore/objectstore.cpp +++ b/zenserver/objectstore/objectstore.cpp @@ -8,6 +8,7 @@ #include #include "zencore/compactbinarybuilder.h" #include "zenhttp/httpcommon.h" +#include "zenhttp/httpserver.h" #include @@ -130,6 +131,13 @@ HttpObjectStoreService::GetBlob(zen::HttpRouterRequest& Request) return Request.ServerRequest().WriteResponse(HttpResponseCode::NotFound); } + zen::HttpRanges Ranges; + if (Request.ServerRequest().TryGetRanges(Ranges); Ranges.size() > 1) + { + // Only a single range is supported + return Request.ServerRequest().WriteResponse(HttpResponseCode::BadRequest); + } + FileContents File = ReadFile(FilePath); if (File.ErrorCode) { @@ -144,16 +152,45 @@ HttpObjectStoreService::GetBlob(zen::HttpRouterRequest& Request) } const IoBuffer& FileBuf = File.Data[0]; - const uint64_t Total = TotalBytesServed.fetch_add(FileBuf.Size()) + FileBuf.Size(); - ZEN_LOG_DEBUG(LogObj, - "GET - '{}/{}' ({}) [OK] (Total: {})", - BucketName, - RelativeBucketPath, - NiceBytes(FileBuf.Size()), - NiceBytes(Total)); + if (Ranges.empty()) + { + const uint64_t TotalServed = TotalBytesServed.fetch_add(FileBuf.Size()) + FileBuf.Size(); - Request.ServerRequest().WriteResponse(HttpResponseCode::OK, HttpContentType::kUnknownContentType, FileBuf); + ZEN_LOG_DEBUG(LogObj, + "GET - '{}/{}' ({}) [OK] (Served: {})", + BucketName, + RelativeBucketPath, + NiceBytes(FileBuf.Size()), + NiceBytes(TotalServed)); + + Request.ServerRequest().WriteResponse(HttpResponseCode::OK, HttpContentType::kBinary, FileBuf); + } + else + { + const auto Range = Ranges[0]; + const uint64_t RangeSize = Range.End - Range.Start; + const uint64_t TotalServed = TotalBytesServed.fetch_add(RangeSize) + RangeSize; + + ZEN_LOG_DEBUG(LogObj, + "GET - '{}/{}' (Range: {}-{}) ({}/{}) [OK] (Served: {})", + BucketName, + RelativeBucketPath, + Range.Start, + Range.End, + NiceBytes(RangeSize), + NiceBytes(FileBuf.Size()), + NiceBytes(TotalServed)); + + MemoryView RangeView = FileBuf.GetView().Mid(Range.Start, RangeSize); + if (RangeView.GetSize() != RangeSize) + { + return Request.ServerRequest().WriteResponse(HttpResponseCode::BadRequest); + } + + IoBuffer RangeBuf = IoBuffer(IoBuffer::Wrap, RangeView.GetData(), RangeView.GetSize()); + Request.ServerRequest().WriteResponse(HttpResponseCode::PartialContent, HttpContentType::kBinary, RangeBuf); + } } void -- cgit v1.2.3