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 <cassert>
namespace kiwix {
namespace {
@ -34,7 +36,7 @@ ByteRange parseByteRange(const std::string& rangeStr)
if (iss >> start) {
if ( start < 0 ) {
if ( iss.eof() )
return ByteRange(ByteRange::PARSED, start, end);
return ByteRange(-start);
} else {
char c;
if (iss >> c && c=='-') {
@ -60,7 +62,37 @@ ByteRange::ByteRange(Kind kind, int64_t first, int64_t last)
: kind_(kind)
, first_(first)
, 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)
{
@ -77,16 +109,16 @@ ByteRange ByteRange::resolve(int64_t contentSize) const
return ByteRange(RESOLVED_FULL_CONTENT, 0, contentSize-1);
if ( kind() == INVALID )
return ByteRange(INVALID, 0, contentSize-1);
return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
const int64_t resolved_first = first() < 0
? std::max(int64_t(0), contentSize + first())
: first();
const int64_t resolved_first = first_ < 0
? std::max(int64_t(0), contentSize + 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 )
return ByteRange(INVALID, 0, contentSize-1);
return ByteRange(RESOLVED_UNSATISFIABLE, 0, contentSize-1);
return ByteRange(RESOLVED_PARTIAL_CONTENT, resolved_first, resolved_last);
}

View File

@ -29,33 +29,49 @@ namespace kiwix {
class ByteRange
{
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 {
// No byte-range was present in the request
// The request is not a range request (no Range header)
NONE,
// The value of the Range header is not a valid continuous range.
// Note that a valid (according to RFC7233) sequence of byte ranges is
// considered invalid in this context.
// The value of the Range header is not a valid continuous
// range. Note that a valid (according to RFC7233) sequence of multiple
// byte ranges is considered invalid in the current implementation
// (i.e. only single-range partial requests are supported).
INVALID,
// This byte-range has been parsed from request
// This byte-range has been successfully parsed from the request
PARSED,
// This is a response to a regular request
// This is a response to a regular (non-range) request
RESOLVED_FULL_CONTENT,
// This is a response to a range request
RESOLVED_PARTIAL_CONTENT
// The range request is valid but unsatisfiable
RESOLVED_UNSATISFIABLE,
// This is a response to a (satisfiable) range request
RESOLVED_PARTIAL_CONTENT,
};
public: // functions
// Constructs a ByteRange object of NONE kind
ByteRange();
// Constructs a ByteRange object of the given kind (except NONE)
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_; }
int64_t first() const { return first_; }
int64_t last() const { return last_; }
int64_t length() const { return last_ + 1 - first_; }
int64_t first() const;
int64_t last() const;
int64_t length() const;
static ByteRange parse(const std::string& rangeStr);
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_compress(true);
} else if ( m_byteRange.kind() == ByteRange::INVALID ) {
} else if ( m_byteRange.kind() == ByteRange::RESOLVED_UNSATISFIABLE ) {
set_code(416);
set_content("");
m_mode = ResponseMode::ERROR_RESPONSE;