in src/client/get.rs [148:258]
fn get_result<T: GetClient>(
location: &Path,
range: Option<GetRange>,
response: HttpResponse,
) -> Result<GetResult, GetResultError> {
let mut meta = header_meta(location, response.headers(), T::HEADER_CONFIG)?;
// ensure that we receive the range we asked for
let range = if let Some(expected) = range {
if response.status() != StatusCode::PARTIAL_CONTENT {
return Err(GetResultError::NotPartial);
}
let val = response
.headers()
.get(CONTENT_RANGE)
.ok_or(GetResultError::NoContentRange)?;
let value = val
.to_str()
.map_err(|source| GetResultError::InvalidContentRange { source })?;
let value = ContentRange::from_str(value).ok_or_else(|| {
let value = value.into();
GetResultError::ParseContentRange { value }
})?;
let actual = value.range;
// Update size to reflect full size of object (#5272)
meta.size = value.size;
let expected = expected.as_range(meta.size)?;
if actual != expected {
return Err(GetResultError::UnexpectedRange { expected, actual });
}
actual
} else {
0..meta.size
};
macro_rules! parse_attributes {
($headers:expr, $(($header:expr, $attr:expr, $map_err:expr)),*) => {{
let mut attributes = Attributes::new();
$(
if let Some(x) = $headers.get($header) {
let x = x.to_str().map_err($map_err)?;
attributes.insert($attr, x.to_string().into());
}
)*
attributes
}}
}
let mut attributes = parse_attributes!(
response.headers(),
(CACHE_CONTROL, Attribute::CacheControl, |source| {
GetResultError::InvalidCacheControl { source }
}),
(
CONTENT_DISPOSITION,
Attribute::ContentDisposition,
|source| GetResultError::InvalidContentDisposition { source }
),
(CONTENT_ENCODING, Attribute::ContentEncoding, |source| {
GetResultError::InvalidContentEncoding { source }
}),
(CONTENT_LANGUAGE, Attribute::ContentLanguage, |source| {
GetResultError::InvalidContentLanguage { source }
}),
(CONTENT_TYPE, Attribute::ContentType, |source| {
GetResultError::InvalidContentType { source }
})
);
// Add attributes that match the user-defined metadata prefix (e.g. x-amz-meta-)
if let Some(prefix) = T::HEADER_CONFIG.user_defined_metadata_prefix {
for (key, val) in response.headers() {
if let Some(suffix) = key.as_str().strip_prefix(prefix) {
if let Ok(val_str) = val.to_str() {
attributes.insert(
Attribute::Metadata(suffix.to_string().into()),
val_str.to_string().into(),
);
} else {
return Err(GetResultError::InvalidMetadata {
key: key.to_string(),
});
}
}
}
}
let stream = response
.into_body()
.bytes_stream()
.map_err(|source| crate::Error::Generic {
store: T::STORE,
source: Box::new(source),
})
.boxed();
Ok(GetResult {
range,
meta,
attributes,
payload: GetResultPayload::Stream(stream),
})
}