yacme_schema/
lib.rs

1//! The request and response data structures for interacting with an ACME server.
2
3#![deny(unsafe_code)]
4#![deny(missing_docs)]
5
6pub mod account;
7pub mod authorizations;
8pub mod challenges;
9pub mod directory;
10pub mod identifier;
11pub mod orders;
12
13pub use account::Account;
14pub use identifier::Identifier;
15pub use orders::Order;
16
17#[cfg(test)]
18pub(crate) mod test {
19    use std::sync::Arc;
20
21    #[macro_export]
22    macro_rules! example {
23        ($name:tt) => {
24            include_str!(concat!(
25                env!("CARGO_MANIFEST_DIR"),
26                "/test-examples/",
27                $name
28            ))
29        };
30    }
31
32    #[macro_export]
33    macro_rules! response {
34        ($name:tt) => {
35            $crate::test::parse($crate::example!($name))
36        };
37    }
38
39    #[macro_export]
40    macro_rules! key {
41        ($name:tt) => {
42            $crate::test::key(include_str!(concat!(
43                env!("CARGO_MANIFEST_DIR"),
44                "/../reference-keys/",
45                $name,
46                ".pem"
47            )))
48        };
49    }
50
51    pub(crate) fn key(private: &str) -> Arc<yacme_key::SigningKey> {
52        let key = yacme_key::SigningKey::from_pkcs8_pem(
53            private,
54            yacme_key::SignatureKind::Ecdsa(yacme_key::EcdsaAlgorithm::P256),
55        )
56        .unwrap();
57
58        Arc::new(key)
59    }
60
61    pub(crate) fn parse(data: &str) -> http::Response<String> {
62        let mut lines = data.lines();
63
64        let status = {
65            let status_line = lines.next().unwrap().trim();
66            let (version, status) = status_line.split_once(' ').unwrap();
67
68            if !matches!(version, "HTTP/1.1") {
69                panic!("Expected HTTP/1.1, got {version}");
70            }
71
72            let (code, _reason) = status.split_once(' ').unwrap();
73            http::StatusCode::from_u16(code.parse().unwrap()).unwrap()
74        };
75
76        let mut headers = http::HeaderMap::new();
77
78        for line in lines.by_ref() {
79            if line.is_empty() {
80                break;
81            } else {
82                let (name, value) = line.trim().split_once(": ").unwrap();
83                headers.append(
84                    http::header::HeaderName::from_bytes(name.as_bytes()).unwrap(),
85                    value.parse().unwrap(),
86                );
87            }
88        }
89
90        let body: String = lines.collect();
91        let mut response = http::Response::new(body);
92        *response.headers_mut() = headers;
93        *response.status_mut() = status;
94        *response.version_mut() = http::Version::HTTP_11;
95        response
96    }
97}