#![deny(missing_docs)] //! Integration of Http Signature Normalization with the HTTP crate //! //! This provides a thin wrapper around transforming HTTP's `HeaderMap`, `PathAndQuery`, and //! `Method` types into BTreeMaps and Strings for signing and verifying requests use http::{ header::{HeaderMap, ToStrError}, method::Method, uri::PathAndQuery, }; use std::{collections::BTreeMap, error::Error, fmt}; use self::{create::Unsigned, verify::Unverified}; /// Export useful types signing and verifying requests pub mod prelude { pub use http::{ header::{HeaderMap, InvalidHeaderValue, ToStrError}, method::Method, uri::PathAndQuery, }; pub use crate::create::{Signed, Unsigned}; pub use crate::verify::{ Algorithm, DeprecatedAlgorithm, ParseSignatureError, ParsedHeader, Unvalidated, Unverified, ValidateError, }; pub use crate::{Config, PrepareVerifyError}; } pub mod create; /// Export types used for signature verification pub mod verify { pub use http_signature_normalization::verify::{ Algorithm, DeprecatedAlgorithm, ParseSignatureError, ParsedHeader, Unvalidated, Unverified, ValidateError, }; } #[derive(Clone, Default)] /// Thinly wrap Http Signature Normalization's config type pub struct Config { /// Expose the inner Config pub config: http_signature_normalization::Config, } #[derive(Debug)] /// Errors produced when preparing to verify an Http Signature pub enum PrepareVerifyError { /// There was an error in the underlying library Sig(http_signature_normalization::PrepareVerifyError), /// There was an error producing a String from the HeaderValue Header(ToStrError), } impl Config { /// Begin the process of signing a request /// /// The types required from this function can be produced from http's Request and URI types. pub fn begin_sign( &self, method: &Method, path_and_query: Option<&PathAndQuery>, headers: HeaderMap, ) -> Result { let headers = headers .iter() .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string()))) .collect::, ToStrError>>()?; let path_and_query = path_and_query .map(|p| p.to_string()) .unwrap_or(String::from("/")); let unsigned = self .config .begin_sign(&method.to_string(), &path_and_query, headers); Ok(Unsigned { unsigned }) } /// Begin the process of verifying a request /// /// The types required from this function can be produced from http's Request and URI types. pub fn begin_verify( &self, method: &Method, path_and_query: Option<&PathAndQuery>, headers: HeaderMap, ) -> Result { let headers = headers .iter() .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string()))) .collect::, ToStrError>>()?; let path_and_query = path_and_query .map(|p| p.to_string()) .unwrap_or(String::from("/")); let unverified = self .config .begin_verify(&method.to_string(), &path_and_query, headers)?; Ok(unverified) } } impl fmt::Display for PrepareVerifyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { PrepareVerifyError::Sig(ref e) => write!(f, "Sig error, {}", e), PrepareVerifyError::Header(ref e) => write!(f, "Header error, {}", e), } } } impl Error for PrepareVerifyError { fn description(&self) -> &str { match *self { PrepareVerifyError::Sig(ref e) => e.description(), PrepareVerifyError::Header(ref e) => e.description(), } } fn source(&self) -> Option<&(dyn Error + 'static)> { match *self { PrepareVerifyError::Sig(ref e) => Some(e), PrepareVerifyError::Header(ref e) => Some(e), } } } impl From for PrepareVerifyError { fn from(e: http_signature_normalization::PrepareVerifyError) -> Self { PrepareVerifyError::Sig(e) } } impl From for PrepareVerifyError { fn from(e: ToStrError) -> Self { PrepareVerifyError::Header(e) } }