diff --git a/http-signature-normalization-actix/examples/client.rs b/http-signature-normalization-actix/examples/client.rs index ba887a2..46cc204 100644 --- a/http-signature-normalization-actix/examples/client.rs +++ b/http-signature-normalization-actix/examples/client.rs @@ -2,7 +2,6 @@ use actix_rt::task::JoinError; use awc::Client; use http_signature_normalization_actix::prelude::*; use sha2::{Digest, Sha256}; -use std::time::SystemTime; use tracing::{error, info}; use tracing_error::ErrorLayer; use tracing_subscriber::{layer::SubscriberExt, EnvFilter}; @@ -14,7 +13,6 @@ async fn request(config: Config) -> Result<(), Box> { .post("http://127.0.0.1:8010/") .append_header(("User-Agent", "Actix Web")) .append_header(("Accept", "text/plain")) - .insert_header(actix_web::http::header::Date(SystemTime::now().into())) .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { info!("Signing String\n{}", s); Ok(base64::encode(s)) as Result<_, MyError> diff --git a/http-signature-normalization-actix/src/digest/sign.rs b/http-signature-normalization-actix/src/digest/sign.rs index a028cb0..67acbea 100644 --- a/http-signature-normalization-actix/src/digest/sign.rs +++ b/http-signature-normalization-actix/src/digest/sign.rs @@ -1,4 +1,4 @@ -use actix_http::{header::InvalidHeaderValue}; +use actix_http::header::InvalidHeaderValue; use actix_rt::task::JoinError; use awc::ClientRequest; use std::{fmt::Display, future::Future, pin::Pin}; diff --git a/http-signature-normalization-actix/src/lib.rs b/http-signature-normalization-actix/src/lib.rs index 05c9dd2..b63946e 100644 --- a/http-signature-normalization-actix/src/lib.rs +++ b/http-signature-normalization-actix/src/lib.rs @@ -273,6 +273,9 @@ pub struct Config { /// Whether to set the Host header set_host: bool, + + /// Whether to set the Date header + set_date: bool, } #[cfg(feature = "client")] @@ -324,17 +327,21 @@ mod client { #[derive(Debug, thiserror::Error)] /// An error when preparing to sign a request pub enum PrepareSignError { - #[error("Failed to read header, {0}")] + #[error("Failed to read header")] /// An error occurred when reading the request's headers Header(#[from] ToStrError), - #[error("{0}")] + #[error("Missing required header")] /// Some headers were marked as required, but are missing RequiredError(#[from] RequiredError), #[error("No host provided for URL, {0}")] /// Missing host Host(String), + + #[error("Failed to set header")] + /// Invalid Date header + InvalidHeader(#[from] actix_http::header::InvalidHeaderValue), } } @@ -421,6 +428,7 @@ impl Config { Config { config: self.config, set_host: true, + set_date: self.set_date, } } @@ -432,6 +440,7 @@ impl Config { Config { config: self.config.mastodon_compat(), set_host: true, + set_date: true, } } @@ -442,6 +451,7 @@ impl Config { Config { config: self.config.require_digest(), set_host: self.set_host, + set_date: self.set_date, } } @@ -453,6 +463,7 @@ impl Config { Config { config: self.config.dont_use_created_field(), set_host: self.set_host, + set_date: self.set_date, } } @@ -461,6 +472,7 @@ impl Config { Config { config: self.config.set_expiration(expires_after), set_host: self.set_host, + set_date: self.set_date, } } @@ -469,6 +481,7 @@ impl Config { Config { config: self.config.require_header(header), set_host: self.set_host, + set_date: self.set_date, } } diff --git a/http-signature-normalization-actix/src/sign.rs b/http-signature-normalization-actix/src/sign.rs index 165c087..261062e 100644 --- a/http-signature-normalization-actix/src/sign.rs +++ b/http-signature-normalization-actix/src/sign.rs @@ -1,9 +1,10 @@ -use actix_http::{header::InvalidHeaderValue}; -use awc::ClientRequest; -use actix_rt::task::JoinError; -use std::{fmt::Display, future::Future, pin::Pin}; - use crate::{create::Signed, Config, PrepareSignError, Sign}; +use actix_rt::task::JoinError; +use awc::{ + http::header::{HttpDate, InvalidHeaderValue, TryIntoHeaderValue}, + ClientRequest, +}; +use std::{fmt::Display, future::Future, pin::Pin, time::SystemTime}; impl Sign for ClientRequest { fn authorization_signature( @@ -24,7 +25,7 @@ impl Sign for ClientRequest { Self: Sized, { Box::pin(async move { - let signed = prepare(&self, &config, key_id, f).await?; + let signed = prepare(&mut self, &config, key_id, f).await?; signed.authorization_header(self.headers_mut())?; Ok(self) }) @@ -48,7 +49,7 @@ impl Sign for ClientRequest { Self: Sized, { Box::pin(async move { - let signed = prepare(&self, &config, key_id, f).await?; + let signed = prepare(&mut self, &config, key_id, f).await?; signed.signature_header(self.headers_mut())?; Ok(self) }) @@ -56,7 +57,7 @@ impl Sign for ClientRequest { } async fn prepare( - request: &ClientRequest, + request: &mut ClientRequest, config: &Config, key_id: K, f: F, @@ -66,6 +67,17 @@ where E: From + From + std::fmt::Debug + Send + 'static, K: Display, { + if config.set_date { + if !request.headers().contains_key("date") { + request.headers_mut().insert( + actix_http::header::DATE, + HttpDate::from(SystemTime::now()) + .try_into_value() + .expect("Date is valid"), + ); + } + } + let mut headers = request.headers().clone(); if config.set_host { let header_string = request