Final clean-up of byte_range.{h,cpp}

This commit is contained in:
Veloman Yunkan 2020-05-26 12:50:08 +04:00
parent c2ebdefe8d
commit 16bd79fa1b
3 changed files with 68 additions and 20 deletions

View File

@ -22,6 +22,8 @@
#include "tools/stringTools.h" #include "tools/stringTools.h"
#include <cassert>
namespace kiwix { namespace kiwix {
namespace { namespace {
@ -34,7 +36,7 @@ ByteRange parseByteRange(const std::string& rangeStr)
if (iss >> start) { if (iss >> start) {
if ( start < 0 ) { if ( start < 0 ) {
if ( iss.eof() ) if ( iss.eof() )
return ByteRange(ByteRange::PARSED, start, end); return ByteRange(-start);
} else { } else {
char c; char c;
if (iss >> c && c=='-') { if (iss >> c && c=='-') {
@ -60,7 +62,37 @@ ByteRange::ByteRange(Kind kind, int64_t first, int64_t last)
: kind_(kind) : kind_(kind)
, first_(first) , first_(first)
, last_(last) , last_(last)
{} {
assert(kind != NONE);
assert(first >= 0);
assert(last >= first);
}
ByteRange::ByteRange(int64_t suffix_length)
: kind_(PARSED)
, first_(-suffix_length)
, last_(INT64_MAX)
{
assert(suffix_length > 0);
}
int64_t ByteRange::first() const
{
assert(kind_ > PARSED);
return first_;
}
int64_t ByteRange::last() const
{
assert(kind_ > PARSED);
return last_;
}
int64_t ByteRange::length() const
{
assert(kind_ > PARSED);
return last_ + 1 - first_;
}
ByteRange ByteRange::parse(const std::string& rangeStr) ByteRange ByteRange::parse(const std::string& rangeStr)
{ {
@ -77,16 +109,16 @@ ByteRange ByteRange::resolve(int64_t contentSize) const
return ByteRange(RESOLVED_FULL_CONTENT, 0, contentSize-1); return ByteRange(RESOLVED_FULL_CONTENT, 0, contentSize-1);
if ( kind() == INVALID ) if ( kind() == INVALID )
return ByteRange(INVALID, 0, contentSize-1); return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
const int64_t resolved_first = first() < 0 const int64_t resolved_first = first_ < 0
? std::max(int64_t(0), contentSize + first()) ? std::max(int64_t(0), contentSize + first_)
: first(); : first_;
const int64_t resolved_last = std::min(contentSize-1, last()); const int64_t resolved_last = std::min(contentSize-1, last_);
if ( resolved_first > resolved_last ) if ( resolved_first > resolved_last )
return ByteRange(INVALID, 0, contentSize-1); return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
return ByteRange(RESOLVED_PARTIAL_CONTENT, resolved_first, resolved_last); return ByteRange(RESOLVED_PARTIAL_CONTENT, resolved_first, resolved_last);
} }

View File

@ -29,33 +29,49 @@ namespace kiwix {
class ByteRange class ByteRange
{ {
public: // types public: // types
// ByteRange is parsed in a request, then it must be resolved (taking
// into account the actual size of the requested resource) before
// being applied in the response.
// The Kind enum represents possible states in such a lifecycle.
enum Kind { enum Kind {
// No byte-range was present in the request // The request is not a range request (no Range header)
NONE, NONE,
// The value of the Range header is not a valid continuous range. // The value of the Range header is not a valid continuous
// Note that a valid (according to RFC7233) sequence of byte ranges is // range. Note that a valid (according to RFC7233) sequence of multiple
// considered invalid in this context. // byte ranges is considered invalid in the current implementation
// (i.e. only single-range partial requests are supported).
INVALID, INVALID,
// This byte-range has been parsed from request // This byte-range has been successfully parsed from the request
PARSED, PARSED,
// This is a response to a regular request // This is a response to a regular (non-range) request
RESOLVED_FULL_CONTENT, RESOLVED_FULL_CONTENT,
// This is a response to a range request // The range request is valid but unsatisfiable
RESOLVED_PARTIAL_CONTENT RESOLVED_UNSATISFIABLE,
// This is a response to a (satisfiable) range request
RESOLVED_PARTIAL_CONTENT,
}; };
public: // functions public: // functions
// Constructs a ByteRange object of NONE kind
ByteRange(); ByteRange();
// Constructs a ByteRange object of the given kind (except NONE)
ByteRange(Kind kind, int64_t first, int64_t last); ByteRange(Kind kind, int64_t first, int64_t last);
// Constructs a ByteRange object of PARSED kind corresponding to a
// range request of the form "Range: bytes=-suffix_length"
explicit ByteRange(int64_t suffix_length);
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
int64_t first() const { return first_; } int64_t first() const;
int64_t last() const { return last_; } int64_t last() const;
int64_t length() const { return last_ + 1 - first_; } int64_t length() const;
static ByteRange parse(const std::string& rangeStr); static ByteRange parse(const std::string& rangeStr);
ByteRange resolve(int64_t contentSize) const; ByteRange resolve(int64_t contentSize) const;

View File

@ -342,7 +342,7 @@ void Response::set_entry(const Entry& entry, const RequestContext& request) {
set_content(content); set_content(content);
set_compress(true); set_compress(true);
} else if ( m_byteRange.kind() == ByteRange::INVALID ) { } else if ( m_byteRange.kind() == ByteRange::RESOLVED_UNSATISFIABLE ) {
set_code(416); set_code(416);
set_content(""); set_content("");
m_mode = ResponseMode::ERROR_RESPONSE; m_mode = ResponseMode::ERROR_RESPONSE;