github_webhooks/axum/mod.rs
1// use self::headers::{XGithubEvent, XHubSignature256};
2// use crate::error::{Result, ToEventError};
3// use axum::TypedHeader;
4// use axum::{
5// body::Bytes,
6// extract::FromRequest,
7// http::Request,
8// response::{IntoResponse, Response},
9// };
10// use github::{Event, EventType};
11// use ring::hmac::{self, Key};
12
13pub mod headers;
14
15// TODO: make public when funcitonal
16// struct GithubWebhook {
17// pub payload: Bytes,
18// pub signature: String,
19// pub event_type: String,
20// }
21
22// impl GithubWebhook {
23// /// Verify the signature and parse the payload into an `Event`.
24// pub fn to_event(&self, key: &Key) -> Result<Event> {
25// let sha = hex::decode(&self.signature)?;
26
27// if hmac::verify(key, &self.payload, &sha).is_ok() {
28// let event_type = self.event_type.parse::<EventType>().map_err(|_| {
29// ToEventError::InvalidEventType {
30// r#type: self.event_type.clone(),
31// }
32// })?;
33
34// Ok(Event::from_json(event_type, &self.payload)
35// .map_err(|_| ToEventError::ParseFailed)?)
36// } else {
37// Err(ToEventError::VerifySignatureFailed)
38// }
39// }
40// }
41
42// #[async_trait::async_trait]
43// impl<S, B> FromRequest<S, B> for GithubWebhook
44// where
45// S: Send + Sync,
46// B: Send + 'static,
47// Bytes: FromRequest<S, B>,
48// {
49// type Rejection = Response;
50
51// async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
52// let TypedHeader(XHubSignature256(signature)) =
53// TypedHeader::<XHubSignature256>::from_request(req, state)
54// .await
55// .map_err(|err| err.into_response())?;
56
57// let TypedHeader(XGithubEvent(event_type)) =
58// TypedHeader::<XGithubEvent>::from_request(req, state)
59// .await
60// .map_err(|err| err.into_response())?;
61
62// let payload = Bytes::from_request(req, state)
63// .await
64// .map_err(IntoResponse::into_response)?;
65
66// Ok(Self {
67// payload,
68// signature,
69// event_type,
70// })
71// }
72// }