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 --- zenhttp/httpserver.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'zenhttp/httpserver.cpp') diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp index 840b90931..952857f2c 100644 --- a/zenhttp/httpserver.cpp +++ b/zenhttp/httpserver.cpp @@ -185,6 +185,70 @@ ParseContentTypeInit(const std::string_view& ContentTypeString) HttpContentType (*ParseContentType)(const std::string_view& ContentTypeString) = &ParseContentTypeInit; +bool +TryParseHttpRangeHeader(std::string_view RangeHeader, HttpRanges& Ranges) +{ + if (RangeHeader.empty()) + { + return false; + } + + const size_t Count = Ranges.size(); + + std::size_t UnitDelim = RangeHeader.find_first_of('='); + if (UnitDelim == std::string_view::npos) + { + return false; + } + + // only bytes for now + std::string_view Unit = RangeHeader.substr(0, UnitDelim); + if (Unit != "bytes"sv) + { + return false; + } + + std::string_view Tokens = RangeHeader.substr(UnitDelim); + while (!Tokens.empty()) + { + // Skip =, + Tokens = Tokens.substr(1); + + size_t Delim = Tokens.find_first_of(','); + if (Delim == std::string_view::npos) + { + Delim = Tokens.length(); + } + + std::string_view Token = Tokens.substr(0, Delim); + Tokens = Tokens.substr(Delim); + + Delim = Token.find_first_of('-'); + if (Delim == std::string_view::npos) + { + return false; + } + + const auto Start = ParseInt(Token.substr(0, Delim)); + const auto End = ParseInt(Token.substr(Delim + 1)); + + if (Start.has_value() && End.has_value() && End.value() > Start.value()) + { + Ranges.push_back({.Start = Start.value(), .End = End.value()}); + } + else if (Start) + { + Ranges.push_back({.Start = Start.value()}); + } + else if (End) + { + Ranges.push_back({.End = End.value()}); + } + } + + return Count != Ranges.size(); +} + ////////////////////////////////////////////////////////////////////////// const std::string_view -- cgit v1.2.3