From 227fcfaafbeca8a5c82215defcb8b8f8e42a0c07 Mon Sep 17 00:00:00 2001 From: qpismont Date: Sun, 31 May 2026 20:48:42 +0000 Subject: [PATCH] using state in extractor --- src/api.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/api.rs b/src/api.rs index 14ef828..61a968e 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,9 +1,11 @@ +use std::fmt::Debug; + use anyhow::anyhow; use axum::body::to_bytes; -use axum::extract::FromRequest; +use axum::extract::{FromRef, FromRequest, FromRequestParts, State}; use axum::response::{IntoResponse, Response}; use axum::routing::{get, post}; -use axum::{Json, Router}; +use axum::{Json, RequestExt, Router}; use hmac::{Hmac, KeyInit, Mac}; use serde_json::Value; use sha2::Sha256; @@ -19,9 +21,9 @@ pub async fn start(app_state: AppState) -> anyhow::Result<()> { let http_port = app_state.config.http_port; let app = Router::new() - .with_state(app_state) .route("/", get(root)) - .route("/webhook", post(webhook)); + .route("/webhook", post(webhook)) + .with_state(app_state); let listerner = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", http_port)).await?; axum::serve(listerner, app) @@ -45,11 +47,22 @@ pub struct WebhookExtract(pub WebhookType); impl FromRequest for WebhookExtract where + AppState: FromRef, S: Send + Sync, { type Rejection = AppError; - async fn from_request(req: axum::extract::Request, state: &S) -> Result { + async fn from_request( + mut req: axum::extract::Request, + state: &S, + ) -> Result { + let State(state) = req + .extract_parts_with_state::, _>(state) + .await + .unwrap(); + + let secret_key = state.config.webhook_secret.as_bytes(); + let headers = req.headers(); let sig_header = headers .get("x-gitea-signature") @@ -63,17 +76,17 @@ where .await .map_err(|err| anyhow!(err))?; + check_sig_header(secret_key, sig_header.as_bytes(), &body_bytes)?; + let Json(value) = Json::::from_bytes(&body_bytes).map_err(|_| AppError::MalformedJsonErr)?; let webhook = WebhookType::try_from(value)?; - check_sig_header(sig_header.as_bytes(), &body_bytes)?; - Ok(WebhookExtract(webhook)) } } -fn check_sig_header(sig_header: &[u8], body: &[u8]) -> Result<(), AppError> { +fn check_sig_header(secret_key: &[u8], sig_header: &[u8], body: &[u8]) -> Result<(), AppError> { let sig_header_decoded = hex::decode(sig_header).map_err(|err| anyhow!(err))?; let webhook_sig_header_secret =