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 <sstream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace kiwix {
|
namespace kiwix {
|
||||||
|
|
||||||
|
@ -64,6 +65,8 @@ fullURL2LocalURL(const std::string& full_url, const std::string& rootLocation)
|
||||||
|
|
||||||
ByteRange parse_byte_range(std::string range)
|
ByteRange parse_byte_range(std::string range)
|
||||||
{
|
{
|
||||||
|
const int64_t int64_max = std::numeric_limits<int64_t>::max();
|
||||||
|
|
||||||
ByteRange byteRange;
|
ByteRange byteRange;
|
||||||
const std::string byteUnitSpec("bytes=");
|
const std::string byteUnitSpec("bytes=");
|
||||||
if ( kiwix::startsWith(range, byteUnitSpec) ) {
|
if ( kiwix::startsWith(range, byteUnitSpec) ) {
|
||||||
|
@ -73,7 +76,12 @@ ByteRange parse_byte_range(std::string range)
|
||||||
std::istringstream iss(range);
|
std::istringstream iss(range);
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
iss >> start >> c;
|
iss >> start;
|
||||||
|
if ( start < 0 ) {
|
||||||
|
if ( iss.eof() )
|
||||||
|
byteRange = ByteRange(ByteRange::PARSED, start, int64_max);
|
||||||
|
} else {
|
||||||
|
iss >> c;
|
||||||
if (iss.good() && c=='-') {
|
if (iss.good() && c=='-') {
|
||||||
iss >> end;
|
iss >> end;
|
||||||
if (iss.fail()) {
|
if (iss.fail()) {
|
||||||
|
@ -85,6 +93,7 @@ ByteRange parse_byte_range(std::string range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return byteRange;
|
return byteRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,10 +46,15 @@ ByteRange resolve_byte_range(const kiwix::Entry& entry, ByteRange range)
|
||||||
if ( range.kind() == ByteRange::NONE )
|
if ( range.kind() == ByteRange::NONE )
|
||||||
return ByteRange(ByteRange::RESOLVED_FULL_CONTENT, 0, entrySize-1);
|
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
|
const int64_t resolved_last = range.last() < 0
|
||||||
? entrySize - 1
|
? entrySize - 1
|
||||||
: std::min(entrySize-1, range.last());
|
: 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
|
} // unnamed namespace
|
||||||
|
|
|
@ -436,4 +436,18 @@ TEST_F(ServerTest, ValidSingleRangeByteRangeRequestsAreHandledProperly)
|
||||||
EXPECT_EQ(334, p->body.size());
|
EXPECT_EQ(334, p->body.size());
|
||||||
EXPECT_EQ(full->body.substr(123, 334), p->body);
|
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