diff --git a/src/web/routes/event.rs b/src/web/routes/event.rs index f773cad..7fa3b47 100644 --- a/src/web/routes/event.rs +++ b/src/web/routes/event.rs @@ -11,7 +11,6 @@ use crate::web::webext::{ApiResult, AxumErrExt, ClientIp, empty_response}; use aide::axum::routing::post; use aide::axum::{ApiRouter, IntoApiResponse}; use anyhow::{Context, Result}; -use axum::Json; use axum::extract::State; use axum_extra::TypedHeader; use chrono::Utc; @@ -340,6 +339,40 @@ fn resolve_visitor_group_id( } } +/// Based on [`axum::Json`], but does not check `Content-Type` so it can be used +/// with no-cors requests. +pub struct Json(pub T); + +impl axum::extract::FromRequest for Json +where + T: serde::de::DeserializeOwned, + S: Send + Sync, +{ + type Rejection = axum::extract::rejection::JsonRejection; + + async fn from_request(req: axum::extract::Request, state: &S) -> Result { + let bytes = axum::body::Bytes::from_request(req, state).await?; + let axum::Json(value) = axum::Json::::from_bytes(&bytes)?; + Ok(Self(value)) + } +} + +impl aide::OperationInput for Json +where + T: schemars::JsonSchema, +{ + fn operation_input(ctx: &mut aide::generate::GenContext, operation: &mut aide::openapi::Operation) { + axum::Json::::operation_input(ctx, operation); + } + + fn inferred_early_responses( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) -> Vec<(Option, aide::openapi::Response)> { + axum::Json::::inferred_early_responses(ctx, operation) + } +} + #[cfg(test)] mod test { use super::*;