Skip to content

Commit

Permalink
Add axum middleware example
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoniosBarotsis committed Nov 29, 2024
1 parent df81543 commit 02b4cde
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ serde_json = "1.0.120"
[dev-dependencies]
jiff = { version = "0.1.4", features = ["serde"] }
tokio = { version = "1.37.0", features = ["macros", "test-util", "rt-multi-thread"] }
# Used in examples
axum = "0.7.9"
svix = "1.42.0"
http-body-util = "0.1.2"
64 changes: 64 additions & 0 deletions examples/axum-verify-event-middleware.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// axum = "0.7.9"
// svix = "1.42.0"
// http-body-util = "0.1.2"

use axum::{
body::Body,
extract::Request,
http,
middleware::{self, Next},
response::{IntoResponse, Response},
routing::post,
Router,
};

use http::{HeaderMap, StatusCode};

use resend_rs::events::try_parse_event;
use svix::webhooks::Webhook;

#[allow(clippy::unwrap_used)]
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", post(handler))
.layer(middleware::from_fn(verify_middleware));

let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();

println!("listening on {}", listener.local_addr().unwrap());

axum::serve(listener, app).await.unwrap();
}

async fn handler(data: String) -> StatusCode {
// Put your normal endpoint code here
let event = try_parse_event(&data);
println!("{event:?}");

StatusCode::OK
}

async fn verify_middleware(
headers: HeaderMap,
request: Request,
next: Next,
) -> Result<impl IntoResponse, Response> {
let (parts, body) = request.into_parts();

let bytes = http_body_util::BodyExt::collect(body)
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response())?
.to_bytes();

let secret = "<YOUR RESEND SIGNING SECRET HERE>".to_string();
let wh = Webhook::new(&secret).expect("Invalid secret");
wh.verify(&bytes, &headers)
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response())?;

let request = Request::from_parts(parts, Body::from(bytes));

Ok(next.run(request).await)
}
3 changes: 3 additions & 0 deletions src/events.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! Parsing for Resend's Events.
//!
//! For an example on how to add (Axum) middleware that verifies incoming event signatures,
//! check out [this example](https://github.com/resend/resend-rust/examples/axum-verify-event-middleware.rs).
#![allow(dead_code)]

Expand Down

0 comments on commit 02b4cde

Please sign in to comment.