diff --git a/http-signature-normalization-reqwest/Cargo.toml b/http-signature-normalization-reqwest/Cargo.toml index d8eb073..de0684e 100644 --- a/http-signature-normalization-reqwest/Cargo.toml +++ b/http-signature-normalization-reqwest/Cargo.toml @@ -24,6 +24,7 @@ required-features = ["sha-2"] [dependencies] base64 = { version = "0.13", optional = true } http-signature-normalization = { version = "0.6.0", path = ".." } +httpdate = "1.0.2" reqwest = { version = "0.11", default-features = false, features = ["json"] } reqwest-middleware = { version = "0.2.0", optional = true } sha2 = { version = "0.10", optional = true } @@ -34,7 +35,6 @@ tokio = { version = "1", default-features = false, features = [ ], optional = true } [dev-dependencies] -httpdate = "1.0.2" pretty_env_logger = "0.4" tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", diff --git a/http-signature-normalization-reqwest/examples/client.rs b/http-signature-normalization-reqwest/examples/client.rs index 41d5db2..c75b9ff 100644 --- a/http-signature-normalization-reqwest/examples/client.rs +++ b/http-signature-normalization-reqwest/examples/client.rs @@ -1,11 +1,9 @@ use http_signature_normalization_reqwest::prelude::*; -use httpdate::HttpDate; use reqwest::{ - header::{ACCEPT, DATE, USER_AGENT}, + header::{ACCEPT, USER_AGENT}, Client, }; use sha2::{Digest, Sha256}; -use std::time::SystemTime; async fn request(config: Config) -> Result<(), Box> { let digest = Sha256::new(); @@ -16,7 +14,6 @@ async fn request(config: Config) -> Result<(), Box diff --git a/http-signature-normalization-reqwest/src/lib.rs b/http-signature-normalization-reqwest/src/lib.rs index 2279eeb..382ce08 100644 --- a/http-signature-normalization-reqwest/src/lib.rs +++ b/http-signature-normalization-reqwest/src/lib.rs @@ -1,9 +1,14 @@ use http_signature_normalization::create::Signed; +use httpdate::HttpDate; use reqwest::{ header::{InvalidHeaderValue, ToStrError}, Request, RequestBuilder, }; -use std::{fmt::Display, time::Duration}; +use std::{ + convert::TryInto, + fmt::Display, + time::{Duration, SystemTime}, +}; pub use http_signature_normalization::RequiredError; @@ -28,6 +33,9 @@ pub struct Config { /// Whether to set the Host header set_host: bool, + + /// Whether to set the Date header + set_date: bool, } /// A trait implemented by the reqwest RequestBuilder type to add an HTTP Signature to the request @@ -90,6 +98,7 @@ impl Config { Config { config: self.config, set_host: true, + set_date: self.set_date, } } @@ -101,6 +110,7 @@ impl Config { Config { config: self.config.mastodon_compat(), set_host: true, + set_date: true, } } @@ -111,6 +121,7 @@ impl Config { Config { config: self.config.require_digest(), set_host: self.set_host, + set_date: self.set_date, } } @@ -122,6 +133,7 @@ impl Config { Config { config: self.config.dont_use_created_field(), set_host: self.set_host, + set_date: self.set_date, } } @@ -130,6 +142,7 @@ impl Config { Config { config: self.config.set_expiration(expiries_after), set_host: self.set_host, + set_date: self.set_date, } } @@ -138,6 +151,7 @@ impl Config { Config { config: self.config.require_header(header), set_host: self.set_host, + set_date: self.set_date, } } } @@ -155,7 +169,7 @@ impl Sign for RequestBuilder { K: Display, { let mut request = self.build()?; - let signed = prepare(&request, config, key_id, f)?; + let signed = prepare(&mut request, config, key_id, f)?; let auth_header = signed.authorization_header(); request.headers_mut().insert( @@ -173,7 +187,7 @@ impl Sign for RequestBuilder { K: Display, { let mut request = self.build()?; - let signed = prepare(&request, config, key_id, f)?; + let signed = prepare(&mut request, config, key_id, f)?; let sig_header = signed.signature_header(); @@ -186,12 +200,23 @@ impl Sign for RequestBuilder { } } -fn prepare(req: &Request, config: &Config, key_id: K, f: F) -> Result +fn prepare(req: &mut Request, config: &Config, key_id: K, f: F) -> Result where F: FnOnce(&str) -> Result, E: From, K: Display, { + if config.set_date { + if !req.headers().contains_key("date") { + req.headers_mut().insert( + "date", + HttpDate::from(SystemTime::now()) + .to_string() + .try_into() + .map_err(SignError::from)?, + ); + } + } let mut bt = std::collections::BTreeMap::new(); for (k, v) in req.headers().iter() { bt.insert( @@ -247,7 +272,7 @@ mod middleware { K: Display, { let mut request = self.build()?; - let signed = prepare(&request, config, key_id, f)?; + let signed = prepare(&mut request, config, key_id, f)?; let auth_header = signed.authorization_header(); request.headers_mut().insert( @@ -265,7 +290,7 @@ mod middleware { K: Display, { let mut request = self.build()?; - let signed = prepare(&request, config, key_id, f)?; + let signed = prepare(&mut request, config, key_id, f)?; let sig_header = signed.signature_header();