github_webhooks/axum/headers/
signature.rs

1use headers::{Header, HeaderName, HeaderValue};
2
3/// The `X-Hub-Signature-256` header.
4pub static X_HUB_SIGNATURE_256: HeaderName = HeaderName::from_static("x-hub-signature-256");
5
6/// An axum-style `TypedHeader` for the `X-Hub-Signature-256` header.
7/// Example:
8/// ```rs,no_run
9/// fn handle(
10///     TypedHeader(XHubSignature256(signature)): TypedHeader<XHubSignature256>,
11/// ) -> impl IntoResponse {
12///     // ...
13/// }
14/// ```
15pub struct XHubSignature256(pub String);
16
17impl Header for XHubSignature256 {
18	fn name() -> &'static HeaderName {
19		&X_HUB_SIGNATURE_256
20	}
21
22	fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
23	where
24		I: Iterator<Item = &'i HeaderValue>,
25	{
26		let value = values
27			.next()
28			.and_then(|h| HeaderValue::to_str(h).ok())
29			.and_then(|s| s.get(7..))
30			.and_then(|s| Some(s.to_string()))
31			.ok_or_else(headers::Error::invalid)?;
32
33		Ok(Self(value))
34	}
35
36	fn encode<E>(&self, _values: &mut E)
37	where
38		E: Extend<HeaderValue>,
39	{
40		// unnecessary, since we're only decoding
41		unreachable!()
42	}
43}
44
45// #[cfg(test)]
46// mod tests {
47//     use super::*;
48//     use axum::{response::IntoResponse, routing::get, Router, TypedHeader};
49//     use reqwest::Client;
50
51//     #[tokio::test]
52//     async fn typed_header() {
53//         async fn handle(
54//             TypedHeader(signature): TypedHeader<XHubSignature256>,
55//         ) -> impl IntoResponse {
56//             let signature = signature.0.as_str();
57//             format!("X-Hub-Signature-256={signature:?}")
58//         }
59
60//         let app = Router::new().route("/", get(handle));
61
62//         let handle = tokio::spawn(async move {
63//             axum::Server::bind(&"127.0.0.1:11632".parse().unwrap())
64//                 .serve(app.into_make_service())
65//                 .await
66//                 .unwrap();
67//         });
68//         let client = Client::new();
69
70//         let res = client
71//             .get("http://127.0.0.1:11632/")
72//             .header("x-hub-signature-256", "sha256=foobar")
73//             .send()
74//             .await.unwrap();
75//         let body = res.text().await.unwrap();
76//         assert_eq!(
77//             body,
78//             r#"X-Hub-Signature-256=sha256=foobar"#
79//         );
80
81//         handle.abort();
82//     }
83// }