-
Bug ReportVersion
Platform
DescriptionFollowing this example code and these docs, I have written the following: use axum::async_trait;
use axum::body::Body;
use axum::extract::FromRef;
use axum::extract::FromRequest;
use axum::extract::Request;
use axum::response::Response;
use axum::routing::post;
use axum::Extension;
use axum::Router;
use std::sync::Arc;
// Clone results in an auto-impl FromRef<AppState> due to https://docs.rs/axum/latest/axum/extract/trait.FromRef.html#impl-FromRef%3CT%3E-for-T.
#[derive(Clone)]
struct AppState {
stripe_webhook_secret: String,
}
// See https://github.com/arlyon/async-stripe/blob/master/examples/webhook-axum.rs
struct StripeEvent(stripe::Event);
#[async_trait]
impl<S> FromRequest<S> for StripeEvent
where
String: FromRequest<S>,
AppState: FromRef<S>,
S: Send + Sync,
{
type Rejection = Response;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
let whsec = AppState::from_ref(state).stripe_webhook_secret;
todo!()
}
}
async fn stripe_webhook(Extension(_): Extension<Arc<AppState>>, StripeEvent(_): StripeEvent) -> &'static str {
todo!()
}
#[tokio::main]
async fn main() {
let state = {
let stripe_webhook_secret = std::env::var("STRIPE_WEBHOOK_SECRET").expect("expected STRIPE_WEBHOOK_SECRET");
Arc::new(AppState { stripe_webhook_secret })
};
let app = Router::new()
.route("/stripe_webhook", post(stripe_webhook))
.layer(Extension(state));
let listener = tokio::net::TcpListener::bind("127.0.0.1:8000").await.unwrap();
axum::serve(listener, app).await.unwrap();
} However adding
It is not at all clear how this error message relates to the actual code written. Am I doing something wrong here? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
Replacing the #[async_trait]
impl FromRequest<AppState> for StripeEvent
where
String: FromRequest<AppState>,
{
type Rejection = Response;
async fn from_request(req: Request<Body>, state: &AppState) -> Result<Self, Self::Rejection> {
let whsec = state.stripe_webhook_secret;
todo!()
}
} still results in the same compile error. |
Beta Was this translation helpful? Give feedback.
-
Ok I think this is the smallest repro i can cook up: use axum::async_trait;
use axum::body::Body;
use axum::extract::FromRequest;
use axum::extract::Request;
use axum::response::Response;
use axum::routing::post;
use axum::Extension;
use axum::Router;
use std::sync::Arc;
// Clone results in an auto-impl FromRef<AppState> due to https://docs.rs/axum/latest/axum/extract/trait.FromRef.html#impl-FromRef%3CT%3E-for-T.
#[derive(Clone)]
struct AppState {}
// See https://github.com/arlyon/async-stripe/blob/master/examples/webhook-axum.rs
struct StripeEvent(());
#[async_trait]
impl FromRequest<AppState> for StripeEvent {
type Rejection = Response;
async fn from_request(req: Request<Body>, state: &AppState) -> Result<Self, Self::Rejection> {
Ok(StripeEvent(()))
}
}
async fn stripe_webhook(StripeEvent(_): StripeEvent) -> &'static str {
"ok"
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/stripe_webhook", post(stripe_webhook))
.layer(Extension(Arc::new(AppState {})));
let listener = tokio::net::TcpListener::bind("127.0.0.1:8000").await.unwrap();
axum::serve(listener, app).await.unwrap();
} |
Beta Was this translation helpful? Give feedback.
-
Extensions and state are two entirely separate mechanisms. To make |
Beta Was this translation helpful? Give feedback.
Extensions and state are two entirely separate mechanisms. To make
AppState
available as state, use.with_state(AppState {})
, not.layer(Extension(...))
. For some examples, see Sharing state with handlers.