OPTION(rgw_lc_debug_interval, OPT_INT) // Debug run interval, in seconds
OPTION(rgw_script_uri, OPT_STR) // alternative value for SCRIPT_URI if not set in request
OPTION(rgw_request_uri, OPT_STR) // alternative value for REQUEST_URI if not set in request
+OPTION(rgw_ignore_get_invalid_range, OPT_BOOL) // treat invalid (e.g., negative) range requests as full
OPTION(rgw_swift_url, OPT_STR) // the swift url, being published by the internal swift auth
OPTION(rgw_swift_url_prefix, OPT_STR) // entry point for which a url is considered a swift url
OPTION(rgw_swift_auth_url, OPT_STR) // default URL to go and verify tokens for v1 auth (if not using internal swift auth)
// at some point
static constexpr auto S3_EXISTING_OBJTAG = "s3:ExistingObjectTag";
-static int parse_range(const char *range, off_t& ofs, off_t& end, bool *partial_content)
+int RGWGetObj::parse_range(void)
{
int r = -ERANGE;
- string s(range);
+ string rs(range_str);
string ofs_str;
string end_str;
- *partial_content = false;
+ ignore_invalid_range = s->cct->_conf->rgw_ignore_get_invalid_range;
+ partial_content = false;
- size_t pos = s.find("bytes=");
+ size_t pos = rs.find("bytes=");
if (pos == string::npos) {
pos = 0;
- while (isspace(s[pos]))
+ while (isspace(rs[pos]))
pos++;
int end = pos;
- while (isalpha(s[end]))
+ while (isalpha(rs[end]))
end++;
- if (strncasecmp(s.c_str(), "bytes", end - pos) != 0)
+ if (strncasecmp(rs.c_str(), "bytes", end - pos) != 0)
return 0;
- while (isspace(s[end]))
+ while (isspace(rs[end]))
end++;
- if (s[end] != '=')
+ if (rs[end] != '=')
return 0;
- s = s.substr(end + 1);
+ rs = rs.substr(end + 1);
} else {
- s = s.substr(pos + 6); /* size of("bytes=") */
+ rs = rs.substr(pos + 6); /* size of("bytes=") */
}
- pos = s.find('-');
+ pos = rs.find('-');
if (pos == string::npos)
goto done;
- *partial_content = true;
+ partial_content = true;
- ofs_str = s.substr(0, pos);
- end_str = s.substr(pos + 1);
+ ofs_str = rs.substr(0, pos);
+ end_str = rs.substr(pos + 1);
if (end_str.length()) {
end = atoll(end_str.c_str());
if (end < 0)
if (end >= 0 && end < ofs)
goto done;
- r = 0;
+ range_parsed = true;
+ return 0;
+
done:
+ if (ignore_invalid_range) {
+ partial_content = false;
+ ofs = 0;
+ end = -1;
+ range_parsed = false; // allow retry
+ r = 0;
+ }
+
return r;
}
bool prefetch_first_chunk = true;
range_str = s->info.env->get("HTTP_RANGE");
- if(range_str) {
- int r = parse_range(range_str, ofs, end, &partial_content);
- /* error on parsing the range, stop prefetch and will fail in execte() */
+ if (range_str) {
+ int r = parse_range();
+ /* error on parsing the range, stop prefetch and will fail in execute() */
if (r < 0) {
- range_parsed = false;
- return false;
- } else {
- range_parsed = true;
+ return false; /* range_parsed==false */
}
- /* range get goes to shadown objects, stop prefetch */
+ /* range get goes to shadow objects, stop prefetch */
if (ofs >= s->cct->_conf->rgw_max_chunk_size) {
prefetch_first_chunk = false;
}
return get_data && prefetch_first_chunk;
}
+
void RGWGetObj::pre_exec()
{
rgw_bucket_object_pre_exec(s);
int RGWGetObj::init_common()
{
if (range_str) {
- /* range parsed error when prefetch*/
+ /* range parsed error when prefetch */
if (!range_parsed) {
- int r = parse_range(range_str, ofs, end, &partial_content);
+ int r = parse_range();
if (r < 0)
return r;
}