mirror of https://github.com/kiwix/libkiwix.git
Support for single-ended byte ranges
This commit is contained in:
parent
67294217a8
commit
52f207eaa6
|
@ -26,6 +26,7 @@
|
|||
#include <sstream>
|
||||
#include <cstdio>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
|
||||
namespace kiwix {
|
||||
|
||||
|
@ -64,6 +65,8 @@ fullURL2LocalURL(const std::string& full_url, const std::string& rootLocation)
|
|||
|
||||
ByteRange parse_byte_range(std::string range)
|
||||
{
|
||||
const int64_t int64_max = std::numeric_limits<int64_t>::max();
|
||||
|
||||
ByteRange byteRange;
|
||||
const std::string byteUnitSpec("bytes=");
|
||||
if ( kiwix::startsWith(range, byteUnitSpec) ) {
|
||||
|
@ -73,15 +76,21 @@ ByteRange parse_byte_range(std::string range)
|
|||
std::istringstream iss(range);
|
||||
char c;
|
||||
|
||||
iss >> start >> c;
|
||||
if (iss.good() && c=='-') {
|
||||
iss >> end;
|
||||
if (iss.fail()) {
|
||||
// Something went wrong while extracting
|
||||
end = -1;
|
||||
}
|
||||
if (iss.eof()) {
|
||||
byteRange = ByteRange(ByteRange::PARSED, start, end);
|
||||
iss >> start;
|
||||
if ( start < 0 ) {
|
||||
if ( iss.eof() )
|
||||
byteRange = ByteRange(ByteRange::PARSED, start, int64_max);
|
||||
} else {
|
||||
iss >> c;
|
||||
if (iss.good() && c=='-') {
|
||||
iss >> end;
|
||||
if (iss.fail()) {
|
||||
// Something went wrong while extracting
|
||||
end = -1;
|
||||
}
|
||||
if (iss.eof()) {
|
||||
byteRange = ByteRange(ByteRange::PARSED, start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,10 +46,15 @@ ByteRange resolve_byte_range(const kiwix::Entry& entry, ByteRange range)
|
|||
if ( range.kind() == ByteRange::NONE )
|
||||
return ByteRange(ByteRange::RESOLVED_FULL_CONTENT, 0, entrySize-1);
|
||||
|
||||
const int64_t resolved_first = range.first() < 0
|
||||
? std::max(int64_t(0), entrySize + range.first())
|
||||
: range.first();
|
||||
|
||||
const int64_t resolved_last = range.last() < 0
|
||||
? entrySize - 1
|
||||
: std::min(entrySize-1, range.last());
|
||||
return ByteRange(ByteRange::RESOLVED_PARTIAL_CONTENT, range.first(), resolved_last);
|
||||
|
||||
return ByteRange(ByteRange::RESOLVED_PARTIAL_CONTENT, resolved_first, resolved_last);
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -436,4 +436,18 @@ TEST_F(ServerTest, ValidSingleRangeByteRangeRequestsAreHandledProperly)
|
|||
EXPECT_EQ(334, p->body.size());
|
||||
EXPECT_EQ(full->body.substr(123, 334), p->body);
|
||||
}
|
||||
|
||||
{
|
||||
const auto p = zfs1_->GET(url, { {"Range", "bytes=20000-"} } );
|
||||
EXPECT_EQ(206, p->status);
|
||||
EXPECT_EQ(full->body.substr(20000), p->body);
|
||||
EXPECT_EQ("bytes 20000-20076/20077", p->get_header_value("Content-Range"));
|
||||
}
|
||||
|
||||
{
|
||||
const auto p = zfs1_->GET(url, { {"Range", "bytes=-100"} } );
|
||||
EXPECT_EQ(206, p->status);
|
||||
EXPECT_EQ(full->body.substr(19977), p->body);
|
||||
EXPECT_EQ("bytes 19977-20076/20077", p->get_header_value("Content-Range"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue