use axum::async_trait; use axum::extract::FromRequest; use axum::extract::Request; use axum::http::HeaderMap; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::response::Response; use axum::Json; use axum::RequestExt; use serde::Serialize; use tracing::debug; use crate::hook_push::HookPush; pub(crate) async fn hook( _headers: HeaderMap, payload: HookRequest, ) -> (StatusCode, Json) { debug!("REQ: {:?}", payload); match payload { HookRequest::Push(_payload) => ( StatusCode::OK, Json(HookResponse { ok: true, message: None, }), ), HookRequest::Unrecognized(payload) => ( StatusCode::BAD_REQUEST, Json(HookResponse { ok: false, message: Some(format!("unrecognized event type: {payload}")), }), ), } } #[derive(Debug)] pub(crate) enum HookRequest { Push(HookPush), Unrecognized(String), } #[async_trait] impl FromRequest for HookRequest where S: Send + Sync, { type Rejection = Response; async fn from_request(req: Request, _state: &S) -> Result { let event_type = req .headers() .get("X-Gitea-Event-Type") .ok_or(StatusCode::UNSUPPORTED_MEDIA_TYPE.into_response())?; let event_type = event_type .to_str() .map_err(|_| StatusCode::UNSUPPORTED_MEDIA_TYPE.into_response())?; match event_type { "push" => { let Json(payload): Json = req.extract().await.map_err(IntoResponse::into_response)?; Ok(HookRequest::Push(payload)) } _ => Ok(HookRequest::Unrecognized(event_type.to_owned())), } } } #[derive(Debug, Serialize)] pub(crate) struct HookResponse { ok: bool, message: Option, }