diff --git a/src/server/byte_range.h b/src/server/byte_range.h index eb61dde45..b9719d8b9 100644 --- a/src/server/byte_range.h +++ b/src/server/byte_range.h @@ -25,15 +25,37 @@ namespace kiwix { class ByteRange { - public: // functions - ByteRange() : ByteRange(0, -1) {} - ByteRange(int64_t first, int64_t last) : first_(first), last_(last) {} + public: // types + enum Kind { + // 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 last() const { return last_; } int64_t length() const { return last_ + 1 - first_; } private: // data + Kind kind_; int64_t first_; int64_t last_; }; diff --git a/src/server/request_context.cpp b/src/server/request_context.cpp index 963f75c34..caa985b5b 100644 --- a/src/server/request_context.cpp +++ b/src/server/request_context.cpp @@ -64,7 +64,7 @@ fullURL2LocalURL(const std::string& full_url, const std::string& rootLocation) ByteRange parse_byte_range(std::string range) { - ByteRange byteRange{0, -1}; + ByteRange byteRange; const std::string byteUnitSpec("bytes="); if ( kiwix::startsWith(range, byteUnitSpec) ) { range.erase(0, byteUnitSpec.size()); @@ -81,7 +81,7 @@ ByteRange parse_byte_range(std::string range) end = -1; } 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 { - return byteRange_.first() <= byteRange_.last(); + return byteRange_.kind() == ByteRange::PARSED; } ByteRange RequestContext::get_range() const { diff --git a/src/server/response.cpp b/src/server/response.cpp index 011e8a902..637559bb2 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -42,10 +42,14 @@ bool is_compressible_mime_type(const std::string& mimeType) ByteRange resolve_byte_range(const kiwix::Entry& entry, ByteRange range) { 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 ? entrySize - 1 : std::min(entrySize-1, range.last()); - return ByteRange(range.first(), resolved_last); + return ByteRange(ByteRange::RESOLVED_PARTIAL_CONTENT, range.first(), resolved_last); } } // unnamed namespace @@ -288,7 +292,7 @@ int Response::send(const RequestContext& request, MHD_Connection* connection) if ( ! etag.empty() ) 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; if (m_verbose) @@ -322,6 +326,8 @@ void Response::set_entry(const Entry& entry, const RequestContext& request) { set_mimeType(mimeType); 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) ) { zim::Blob raw_content = entry.getBlob(); const std::string content = string(raw_content.data(), raw_content.size());