pub fn generate_presigned_url(
        &mut self,
        creds: &AwsCredentials,
        expires_in: &Duration,
        should_sha256_sign_payload: bool,
    ) -> String {
        debug!("Presigning request URL");

        self.sign(creds);
        let hostname = self.hostname();

        let current_time = Utc::now();
        let current_time_fmted = current_time.format("%Y%m%dT%H%M%SZ");
        let current_date = current_time.format("%Y%m%d");

        self.remove_header("X-Amz-Content-Sha256");

        self.remove_header("X-Amz-Date");

        self.remove_header("Content-Type");

        if let Some(ref token) = *creds.token() {
            self.remove_header("X-Amz-Security-Token");
            self.params
                .insert("X-Amz-Security-Token".into(), Some(token.to_string()));
        }

        self.remove_header("X-Amz-Algorithm");
        self.params
            .insert("X-Amz-Algorithm".into(), Some("AWS4-HMAC-SHA256".into()));

        self.remove_header("X-Amz-Credential");
        self.params.insert(
            "X-Amz-Credential".into(),
            format!(
                "{}/{}/{}/{}/aws4_request",
                &creds.aws_access_key_id(),
                &current_date,
                self.region.name(),
                self.service
            )
            .into(),
        );

        self.remove_header("X-Amz-Expires");
        let expiration_time = format!("{}", expires_in.as_secs());
        self.params
            .insert("X-Amz-Expires".into(), expiration_time.into());

        self.canonical_uri = canonical_uri(&self.path, &self.region);
        let canonical_headers = canonical_headers(&self.headers);

        let signed_headers = signed_headers(&self.headers);
        self.params
            .insert("X-Amz-SignedHeaders".into(), Some(signed_headers.clone()));

        self.params
            .insert("X-Amz-Date".into(), Some(current_time_fmted.to_string()));

        self.canonical_query_string = build_canonical_query_string(&self.params);

        debug!("canonical_uri: {:?}", self.canonical_uri);
        debug!("canonical_headers: {:?}", canonical_headers);
        debug!("signed_headers: {:?}", signed_headers);
        debug!("canonical_query_string: {:?}", self.canonical_query_string);

        let payload = if should_sha256_sign_payload {
            match self.payload {
                None => Cow::Borrowed(EMPTY_SHA256_HASH),
                Some(SignedRequestPayload::Buffer(ref payload)) => {
                    let (digest, _len) = digest_payload(&payload);
                    Cow::Owned(digest)
                }
                Some(SignedRequestPayload::Stream(ref _stream)) => Cow::Borrowed(UNSIGNED_PAYLOAD),
            }
        } else {
            Cow::Borrowed(UNSIGNED_PAYLOAD)
        };

        let canonical_request = format!(
            "{}\n{}\n{}\n{}\n{}\n{}",
            &self.method,
            self.canonical_uri,
            self.canonical_query_string,
            canonical_headers,
            &signed_headers,
            payload
        );

        debug!("canonical_request: {:?}", canonical_request);

        // use the hashed canonical request to build the string to sign
        let hashed_canonical_request = to_hexdigest(&canonical_request);

        debug!("hashed_canonical_request: {:?}", hashed_canonical_request);

        let scope = format!(
            "{}/{}/{}/aws4_request",
            current_date,
            self.region.name(),
            &self.service
        );

        debug!("scope: {}", scope);

        let string_to_sign = string_to_sign(current_time, &hashed_canonical_request, &scope);

        debug!("string_to_sign: {}", string_to_sign);

        let signature = sign_string(
            &string_to_sign,
            creds.aws_secret_access_key(),
            current_time.date().naive_utc(),
            &self.region.name(),
            &self.service,
        );
        self.params
            .insert("X-Amz-Signature".into(), signature.into());

        format!(
            "{}://{}{}?{}",
            self.scheme(),
            hostname,
            self.canonical_uri,
            build_canonical_query_string(&self.params)
        )
    }
Generate a Presigned URL for AWS

See the [documentation](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html)
for more information.
rusoto/signature/src/signature.rs