ByteRange::Kind

This commit is contained in:
Veloman Yunkan 2020-05-25 16:23:44 +04:00
parent d111a40ce8
commit 67294217a8
3 changed files with 36 additions and 8 deletions

View File

@ -25,15 +25,37 @@ namespace kiwix {
class ByteRange class ByteRange
{ {
public: // functions public: // types
ByteRange() : ByteRange(0, -1) {} enum Kind {
ByteRange(int64_t first, int64_t last) : first_(first), last_(last) {} // No byte-range was present in the request
NONE,
// This byte-range has been parsed from request
PARSED,
// This is a response to a regular request
RESOLVED_FULL_CONTENT,
// This is a response to a range request
RESOLVED_PARTIAL_CONTENT
};
public: // functions
ByteRange() : kind_(NONE), first_(0), last_(-1) {}
ByteRange(Kind kind, int64_t first, int64_t last)
: kind_(kind)
, first_(first)
, last_(last)
{}
Kind kind() const { return kind_; }
int64_t first() const { return first_; } int64_t first() const { return first_; }
int64_t last() const { return last_; } int64_t last() const { return last_; }
int64_t length() const { return last_ + 1 - first_; } int64_t length() const { return last_ + 1 - first_; }
private: // data private: // data
Kind kind_;
int64_t first_; int64_t first_;
int64_t last_; int64_t last_;
}; };

View File

@ -64,7 +64,7 @@ fullURL2LocalURL(const std::string& full_url, const std::string& rootLocation)
ByteRange parse_byte_range(std::string range) ByteRange parse_byte_range(std::string range)
{ {
ByteRange byteRange{0, -1}; ByteRange byteRange;
const std::string byteUnitSpec("bytes="); const std::string byteUnitSpec("bytes=");
if ( kiwix::startsWith(range, byteUnitSpec) ) { if ( kiwix::startsWith(range, byteUnitSpec) ) {
range.erase(0, byteUnitSpec.size()); range.erase(0, byteUnitSpec.size());
@ -81,7 +81,7 @@ ByteRange parse_byte_range(std::string range)
end = -1; end = -1;
} }
if (iss.eof()) { if (iss.eof()) {
byteRange = ByteRange(start, end); byteRange = ByteRange(ByteRange::PARSED, start, end);
} }
} }
} }
@ -197,7 +197,7 @@ bool RequestContext::is_valid_url() const {
} }
bool RequestContext::has_range() const { bool RequestContext::has_range() const {
return byteRange_.first() <= byteRange_.last(); return byteRange_.kind() == ByteRange::PARSED;
} }
ByteRange RequestContext::get_range() const { ByteRange RequestContext::get_range() const {

View File

@ -42,10 +42,14 @@ bool is_compressible_mime_type(const std::string& mimeType)
ByteRange resolve_byte_range(const kiwix::Entry& entry, ByteRange range) ByteRange resolve_byte_range(const kiwix::Entry& entry, ByteRange range)
{ {
const int64_t entrySize = entry.getSize(); const int64_t entrySize = entry.getSize();
if ( range.kind() == ByteRange::NONE )
return ByteRange(ByteRange::RESOLVED_FULL_CONTENT, 0, entrySize-1);
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(range.first(), resolved_last); return ByteRange(ByteRange::RESOLVED_PARTIAL_CONTENT, range.first(), resolved_last);
} }
} // unnamed namespace } // unnamed namespace
@ -288,7 +292,7 @@ int Response::send(const RequestContext& request, MHD_Connection* connection)
if ( ! etag.empty() ) if ( ! etag.empty() )
MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag.c_str()); MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag.c_str());
if (m_returnCode == MHD_HTTP_OK && request.has_range()) if (m_returnCode == MHD_HTTP_OK && m_byteRange.kind() == ByteRange::RESOLVED_PARTIAL_CONTENT)
m_returnCode = MHD_HTTP_PARTIAL_CONTENT; m_returnCode = MHD_HTTP_PARTIAL_CONTENT;
if (m_verbose) if (m_verbose)
@ -322,6 +326,8 @@ void Response::set_entry(const Entry& entry, const RequestContext& request) {
set_mimeType(mimeType); set_mimeType(mimeType);
set_cacheable(); set_cacheable();
// XXX: Which of the Accept-Encoding and Range headers has precedence if both
// XXX: are present? Can partial content be compressed?
if ( is_compressible_mime_type(mimeType) ) { if ( is_compressible_mime_type(mimeType) ) {
zim::Blob raw_content = entry.getBlob(); zim::Blob raw_content = entry.getBlob();
const std::string content = string(raw_content.data(), raw_content.size()); const std::string content = string(raw_content.data(), raw_content.size());