use self::encoder::Encoder;
use super::{BuildStrategy, rest::RestRequest};
use crate::error::SocketError;
use hmac::Mac;
pub mod encoder;
#[allow(clippy::needless_lifetimes)]
pub trait Signer {
type Config<'a>
where
Self: 'a;
fn config<'a, Request>(
&'a self,
request: Request,
builder: &reqwest::RequestBuilder,
) -> Result<Self::Config<'a>, SocketError>
where
Request: RestRequest;
fn add_bytes_to_sign<M>(mac: &mut M, config: &Self::Config<'_>)
where
M: Mac;
fn build_signed_request<'a>(
config: Self::Config<'a>,
builder: reqwest::RequestBuilder,
signature: String,
) -> Result<reqwest::Request, SocketError>;
}
#[derive(Debug, Copy, Clone)]
pub struct RequestSigner<Sig, Hmac, SigEncoder> {
signer: Sig,
mac: Hmac,
encoder: SigEncoder,
}
impl<Sig, Hmac, SigEncoder> BuildStrategy for RequestSigner<Sig, Hmac, SigEncoder>
where
Sig: Signer,
Hmac: Mac + Clone,
SigEncoder: Encoder,
{
fn build<Request>(
&self,
request: Request,
builder: reqwest::RequestBuilder,
) -> Result<reqwest::Request, SocketError>
where
Request: RestRequest,
{
let config = self.signer.config(request, &builder)?;
let mut mac = self.mac.clone();
Sig::add_bytes_to_sign(&mut mac, &config);
let bytes_to_encode = mac.finalize().into_bytes();
let signature = self.encoder.encode(bytes_to_encode);
Sig::build_signed_request(config, builder, signature)
}
}
impl<Sig, Hmac, SigEncoder> RequestSigner<Sig, Hmac, SigEncoder> {
pub fn new(signer: Sig, mac: Hmac, encoder: SigEncoder) -> Self {
Self {
signer,
mac,
encoder,
}
}
}