fn headers()

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))
    }