http-signature-normalization-http 0.1.0

An HTTP Signatures library that leaves the signing to you
Documentation
#![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<Unsigned, ToStrError> {
        let headers = headers
            .iter()
            .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
            .collect::<Result<BTreeMap<_, _>, 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<Unverified, PrepareVerifyError> {
        let headers = headers
            .iter()
            .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
            .collect::<Result<BTreeMap<_, _>, 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<http_signature_normalization::PrepareVerifyError> for PrepareVerifyError {
    fn from(e: http_signature_normalization::PrepareVerifyError) -> Self {
        PrepareVerifyError::Sig(e)
    }
}

impl From<ToStrError> for PrepareVerifyError {
    fn from(e: ToStrError) -> Self {
        PrepareVerifyError::Header(e)
    }
}