in source/s3_auto_ranged_get.c [381:502]
static int s_discover_object_range_and_content_length(
struct aws_s3_meta_request *meta_request,
struct aws_s3_request *request,
int error_code,
uint64_t *out_total_content_length,
uint64_t *out_object_range_start,
uint64_t *out_object_range_end,
uint64_t *out_total_object_size) {
AWS_PRECONDITION(out_total_content_length);
AWS_PRECONDITION(out_object_range_start);
AWS_PRECONDITION(out_object_range_end);
AWS_PRECONDITION(out_total_object_size);
int result = AWS_OP_ERR;
uint64_t total_content_length = 0;
uint64_t object_range_start = 0;
uint64_t object_range_end = 0;
uint64_t total_object_size = 0;
AWS_ASSERT(request->discovers_object_size);
switch (request->request_tag) {
case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT:
if (error_code != AWS_ERROR_SUCCESS) {
/* If the head request failed, there's nothing we can do, so resurface the error code. */
aws_raise_error(error_code);
break;
}
/* There should be a Content-Length header that indicates the total size of the range.*/
if (aws_s3_parse_content_length_response_header(
meta_request->allocator, request->send_data.response_headers, &total_content_length)) {
AWS_LOGF_ERROR(
AWS_LS_S3_META_REQUEST,
"id=%p Could not find content-length header for request %p",
(void *)meta_request,
(void *)request);
break;
}
/* When doing a head object request, we currently assume that we did so with a message that had a Range
* header. This means that there should also be a Content-Range header that specifies the object range and
* total object size.*/
if (aws_s3_parse_content_range_response_header(
meta_request->allocator,
request->send_data.response_headers,
&object_range_start,
&object_range_end,
&total_object_size)) {
AWS_LOGF_ERROR(
AWS_LS_S3_META_REQUEST,
"id=%p Could not find content-range header for request %p",
(void *)meta_request,
(void *)request);
break;
}
result = AWS_OP_SUCCESS;
break;
case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART:
AWS_ASSERT(request->part_number == 1);
if (error_code != AWS_ERROR_SUCCESS) {
/* If we hit an empty file while trying to discover the object-size via part, then this request failure
* is as designed. */
if (s_check_empty_file_download_error(request)) {
AWS_LOGF_DEBUG(
AWS_LS_S3_META_REQUEST,
"id=%p Detected empty file with request %p. Sending new request without range header.",
(void *)meta_request,
(void *)request);
total_object_size = 0ULL;
total_content_length = 0ULL;
result = AWS_OP_SUCCESS;
} else {
/* Otherwise, resurface the error code. */
aws_raise_error(error_code);
}
break;
}
AWS_ASSERT(request->send_data.response_headers != NULL);
/* Parse the object size from the part response. */
if (aws_s3_parse_content_range_response_header(
meta_request->allocator, request->send_data.response_headers, NULL, NULL, &total_object_size)) {
AWS_LOGF_ERROR(
AWS_LS_S3_META_REQUEST,
"id=%p Could not find content-range header for request %p",
(void *)meta_request,
(void *)request);
break;
}
/* When discovering the object size via first-part, the object range is the entire object. */
object_range_start = 0;
object_range_end = total_object_size - 1;
total_content_length = total_object_size;
result = AWS_OP_SUCCESS;
break;
default:
AWS_ASSERT(false);
break;
}
if (result == AWS_OP_SUCCESS) {
*out_total_content_length = total_content_length;
*out_object_range_start = object_range_start;
*out_object_range_end = object_range_end;
*out_total_object_size = total_object_size;
}
return result;
}