use actix_web::{ client::ClientRequest, error::BlockingError, http::header::InvalidHeaderValue, web, }; use std::{fmt::Display, future::Future, pin::Pin}; use crate::{create::Signed, Config, PrepareSignError, Sign}; impl Sign for ClientRequest { fn authorization_signature( mut self, config: Config, key_id: K, f: F, ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From + From + From + std::fmt::Debug + Send + 'static, K: Display + 'static, Self: Sized, { Box::pin(async move { let signed = prepare(&self, &config, key_id, f).await?; signed.authorization_header(self.headers_mut())?; Ok(self) }) } fn signature( mut self, config: Config, key_id: K, f: F, ) -> Pin>>> where F: FnOnce(&str) -> Result + Send + 'static, E: From + From + From + std::fmt::Debug + Send + 'static, K: Display + 'static, Self: Sized, { Box::pin(async move { let signed = prepare(&self, &config, key_id, f).await?; signed.signature_header(self.headers_mut())?; Ok(self) }) } } async fn prepare( request: &ClientRequest, config: &Config, key_id: K, f: F, ) -> Result where F: FnOnce(&str) -> Result + Send + 'static, E: From + From + std::fmt::Debug + Send + 'static, K: Display, { let mut headers = request.headers().clone(); if config.set_host { let header_string = request .get_uri() .host() .ok_or_else(|| PrepareSignError::Host(request.get_uri().to_string()))? .to_string(); let header_string = match request.get_uri().port().map(|p| p.as_u16()) { None | Some(443) | Some(80) => header_string, Some(port) => format!("{}:{}", header_string, port), }; headers.insert( "Host".parse().unwrap(), header_string .parse() .map_err(|_| PrepareSignError::Host(request.get_uri().to_string()))?, ); } let unsigned = config.begin_sign( request.get_method(), request.get_uri().path_and_query(), headers, )?; let key_id = key_id.to_string(); let signed = web::block(move || unsigned.sign(key_id, f)).await??; Ok(signed) }