http_signature_normalization_http/
lib.rs

1#![deny(missing_docs)]
2//! Integration of Http Signature Normalization with the HTTP crate
3//!
4//! This provides a thin wrapper around transforming HTTP's `HeaderMap`, `PathAndQuery`, and
5//! `Method` types into BTreeMaps and Strings for signing and verifying requests
6
7use http::{
8    header::{HeaderMap, ToStrError},
9    method::Method,
10    uri::PathAndQuery,
11};
12use std::{collections::BTreeMap, error::Error, fmt};
13
14use self::{create::Unsigned, verify::Unverified};
15
16/// Export useful types signing and verifying requests
17pub mod prelude {
18    pub use http::{
19        header::{HeaderMap, InvalidHeaderValue, ToStrError},
20        method::Method,
21        uri::PathAndQuery,
22    };
23
24    pub use crate::create::{Signed, Unsigned};
25
26    pub use crate::verify::{
27        Algorithm, DeprecatedAlgorithm, ParseSignatureError, ParsedHeader, Unvalidated, Unverified,
28        ValidateError,
29    };
30
31    pub use crate::{Config, PrepareVerifyError};
32}
33
34pub mod create;
35
36/// Export types used for signature verification
37pub mod verify {
38    pub use http_signature_normalization::verify::{
39        Algorithm, DeprecatedAlgorithm, ParseSignatureError, ParsedHeader, Unvalidated, Unverified,
40        ValidateError,
41    };
42}
43
44#[derive(Clone, Default)]
45/// Thinly wrap Http Signature Normalization's config type
46pub struct Config {
47    /// Expose the inner Config
48    pub config: http_signature_normalization::Config,
49}
50
51#[derive(Debug)]
52/// Errors produced when preparing to verify an Http Signature
53pub enum PrepareVerifyError {
54    /// There was an error in the underlying library
55    Sig(http_signature_normalization::PrepareVerifyError),
56    /// There was an error producing a String from the HeaderValue
57    Header(ToStrError),
58}
59
60#[derive(Debug)]
61/// Errors produced when preparing to sign an Http Signature
62pub enum PrepareSignError {
63    /// There was an error in the underlying library
64    Required(http_signature_normalization::RequiredError),
65    /// There was an error producing a String from the HeaderValue
66    Header(ToStrError),
67}
68
69impl Config {
70    /// Begin the process of signing a request
71    ///
72    /// The types required from this function can be produced from http's Request and URI types.
73    pub fn begin_sign(
74        &self,
75        method: &Method,
76        path_and_query: Option<&PathAndQuery>,
77        headers: HeaderMap,
78    ) -> Result<Unsigned, PrepareSignError> {
79        let headers = headers
80            .iter()
81            .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
82            .collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
83
84        let path_and_query = path_and_query
85            .map(|p| p.to_string())
86            .unwrap_or_else(|| String::from("/"));
87
88        let unsigned = self
89            .config
90            .begin_sign(method.as_ref(), &path_and_query, headers)?;
91
92        Ok(Unsigned { unsigned })
93    }
94
95    /// Begin the process of verifying a request
96    ///
97    /// The types required from this function can be produced from http's Request and URI types.
98    pub fn begin_verify(
99        &self,
100        method: &Method,
101        path_and_query: Option<&PathAndQuery>,
102        headers: HeaderMap,
103    ) -> Result<Unverified, PrepareVerifyError> {
104        let headers = headers
105            .iter()
106            .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
107            .collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
108
109        let path_and_query = path_and_query
110            .map(|p| p.to_string())
111            .unwrap_or_else(|| String::from("/"));
112
113        let unverified = self
114            .config
115            .begin_verify(method.as_ref(), &path_and_query, headers)?;
116
117        Ok(unverified)
118    }
119}
120
121impl fmt::Display for PrepareVerifyError {
122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123        match *self {
124            PrepareVerifyError::Sig(ref e) => write!(f, "Sig error, {}", e),
125            PrepareVerifyError::Header(ref e) => write!(f, "Header error, {}", e),
126        }
127    }
128}
129
130impl fmt::Display for PrepareSignError {
131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132        match *self {
133            PrepareSignError::Required(ref e) => write!(f, "Required error, {}", e),
134            PrepareSignError::Header(ref e) => write!(f, "Header error, {}", e),
135        }
136    }
137}
138
139impl Error for PrepareVerifyError {
140    fn source(&self) -> Option<&(dyn Error + 'static)> {
141        match *self {
142            PrepareVerifyError::Sig(ref e) => Some(e),
143            PrepareVerifyError::Header(ref e) => Some(e),
144        }
145    }
146}
147
148impl Error for PrepareSignError {
149    fn source(&self) -> Option<&(dyn Error + 'static)> {
150        match *self {
151            PrepareSignError::Required(ref e) => Some(e),
152            PrepareSignError::Header(ref e) => Some(e),
153        }
154    }
155}
156
157impl From<http_signature_normalization::PrepareVerifyError> for PrepareVerifyError {
158    fn from(e: http_signature_normalization::PrepareVerifyError) -> Self {
159        PrepareVerifyError::Sig(e)
160    }
161}
162
163impl From<ToStrError> for PrepareVerifyError {
164    fn from(e: ToStrError) -> Self {
165        PrepareVerifyError::Header(e)
166    }
167}
168
169impl From<http_signature_normalization::RequiredError> for PrepareSignError {
170    fn from(e: http_signature_normalization::RequiredError) -> Self {
171        PrepareSignError::Required(e)
172    }
173}
174
175impl From<ToStrError> for PrepareSignError {
176    fn from(e: ToStrError) -> Self {
177        PrepareSignError::Header(e)
178    }
179}