1use crate::util::{WebflowHeaders, compare_signatures, from_request_parts};
2use axum::http::Request;
3use axum::{
4 body::{self, Body},
5 response::Response,
6};
7use std::future::Future;
8use std::pin::Pin;
9use std::task::{Context, Poll};
10use tower::{BoxError, Service};
11
12const BODY_LIMIT: usize = 1_048_576;
13
14#[derive(Clone)]
16pub struct WebflowService<S, Secret> {
17 pub(crate) inner: S,
18 pub secret: Secret,
19}
20
21impl<S, Secret> Service<Request<Body>> for WebflowService<S, Secret>
22where
23 S: Service<Request<Body>, Response = Response> + Clone + Send + 'static,
24 S::Future: Send + 'static,
25 S::Error: Into<BoxError>,
26 Secret: AsRef<[u8]> + Clone + Send + 'static,
27{
28 type Response = Response;
29 type Error = BoxError;
30 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
31
32 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
33 self.inner.poll_ready(cx).map_err(Into::into)
34 }
35
36 fn call(&mut self, req: Request<Body>) -> Self::Future {
37 let mut inner = self.inner.clone();
38 let secret = self.secret.clone();
39 Box::pin(async move {
40 let (mut parts, body) = req.into_parts();
41
42 let body_bytes = body::to_bytes(body, BODY_LIMIT)
43 .await
44 .map_err(Into::<BoxError>::into)?;
45
46 let body_string =
47 String::from_utf8(body_bytes.to_vec()).map_err(Into::<BoxError>::into)?;
48
49 tracing::debug!(body_string, "webflow-body");
50
51 let WebflowHeaders(signature, timestamp) = from_request_parts(&mut parts)?;
52
53 tracing::debug!(signature, "webflow-header-signature");
54 tracing::debug!(timestamp, "webflow-header-timestamp");
55
56 let message_to_verify = format!("{timestamp}:{body_string}");
57
58 if compare_signatures(&message_to_verify, secret.as_ref(), &signature) {
59 let new_req = Request::from_parts(parts, Body::from(body_bytes));
60 inner.call(new_req).await.map_err(Into::into)
61 } else {
62 tracing::warn!("Webflow signature validation failed");
63 Err("Could not verify signature".into())
64 }
65 })
66 }
67}