pub(crate) fn header<'a>(headers: &'a BTreeMap<String, String>, name: &str) -> Option<&'a str> {
headers
.iter()
.find(|(key, _)| key.eq_ignore_ascii_case(name))
.map(|(_, value)| value.as_str())
}
pub(crate) fn remove_header(headers: &mut BTreeMap<String, String>, name: &str) {
if let Some(key) = headers.keys().find(|key| key.eq_ignore_ascii_case(name)).cloned() {
headers.remove(&key);
}
}
pub(crate) fn sigv4_request_from_http(
request: &S3HttpRequest,
presigned_url: bool,
) -> SigV4Request {
let mut sigv4_request = SigV4Request::new(&request.method, &request.path);
sigv4_request.query = request
.query
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect();
sigv4_request.headers = request
.headers
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect();
if let Some(payload_hash) = header(&request.headers, "x-amz-content-sha256") {
sigv4_request.payload_hash = payload_hash.to_string();
} else if !presigned_url {
sigv4_request.payload_hash = sha256_hex(&request.body);
}
sigv4_request
}
pub(crate) fn sigv4_query_access_key(
query: &BTreeMap<String, String>,
) -> Result<String, RuntimeError> {
query
.get("X-Amz-Credential")
.and_then(|credential| credential.split('/').next())
.filter(|access_key_id| !access_key_id.is_empty())
.map(percent_decode)
.ok_or_else(|| {
RuntimeError::AuthorizationQueryParametersError(
"missing presigned URL credential access key".to_string(),
)
})
}
pub(crate) fn sigv4_authorization_access_key(
authorization: &str,
) -> Result<String, RuntimeError> {
authorization
.split("Credential=")
.nth(1)
.and_then(|value| value.split(',').next())
.and_then(|credential| credential.split('/').next())
.filter(|access_key_id| !access_key_id.is_empty())
.map(str::to_string)
.ok_or_else(|| {
RuntimeError::AuthorizationHeaderMalformed(
"missing Authorization credential access key".to_string(),
)
})
}