in aws/rust-runtime/aws-sigv4/src/http_request/canonical_request.rs [179:239]
fn headers(
req: &SignableRequest<'_>,
params: &SigningParams<'_>,
payload_hash: &str,
date_time: &str,
) -> Result<(Vec<CanonicalHeaderName>, HeaderMap), Error> {
// Header computation:
// The canonical request will include headers not present in the input. We need to clone and
// normalize the headers from the original request and add:
// - host
// - x-amz-date
// - x-amz-security-token (if provided)
// - x-amz-content-sha256 (if requested by signing settings)
let mut canonical_headers = HeaderMap::with_capacity(req.headers().len());
for (name, value) in req.headers().iter() {
// Header names and values need to be normalized according to Step 4 of https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
// Using append instead of insert means this will not clobber headers that have the same lowercased name
canonical_headers.append(
HeaderName::from_str(&name.as_str().to_lowercase())?,
normalize_header_value(value),
);
}
Self::insert_host_header(&mut canonical_headers, req.uri());
if params.settings.signature_location == SignatureLocation::Headers {
Self::insert_date_header(&mut canonical_headers, date_time);
if let Some(security_token) = params.security_token {
let mut sec_header = HeaderValue::from_str(security_token)?;
sec_header.set_sensitive(true);
canonical_headers.insert(header::X_AMZ_SECURITY_TOKEN, sec_header);
}
if params.settings.payload_checksum_kind == PayloadChecksumKind::XAmzSha256 {
let header = HeaderValue::from_str(payload_hash)?;
canonical_headers.insert(header::X_AMZ_CONTENT_SHA_256, header);
}
}
let mut signed_headers = Vec::with_capacity(canonical_headers.len());
for (name, _) in &canonical_headers {
// The user agent header should not be signed because it may be altered by proxies
if name == USER_AGENT {
continue;
}
if params.settings.signature_location == SignatureLocation::QueryParams {
// Exclude content-length and content-type for query param signatures since the
// body is unsigned for these use-cases, and the size is not known up-front.
if name == CONTENT_LENGTH || name == CONTENT_TYPE {
continue;
}
// The X-Amz-User-Agent header should not be signed if this is for a presigned URL
if name == HeaderName::from_static(header::X_AMZ_USER_AGENT) {
continue;
}
}
signed_headers.push(CanonicalHeaderName(name.clone()));
}
Ok((signed_headers, canonical_headers))
}