feat(axum): add concise interaction request dispatch

Wrap extracted interaction forms in an InteractionRequest with a concise dispatch path, add a handlers() helper, and move canonical examples off direct HandlerRegistry/InteractionForm plumbing.

req: axum_integration/003

req: ceremony/001

req: dx/003

req: examples/003
This commit is contained in:
slhx agent
2026-06-02 00:19:38 +02:00
parent 7b7cb7da15
commit 42ede63361
6 changed files with 96 additions and 19 deletions
+52
View File
@@ -136,6 +136,15 @@ pub struct InteractionForm {
files: Vec<InteractionFile>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InteractionRequest {
form: InteractionForm,
}
pub trait DispatchRegistry {
fn dispatch_form(self, form: InteractionForm) -> Result<EffectResponse, DispatchRejection>;
}
pub struct HandlerRegistry {
fingerprint: BuildFingerprint,
handlers: BTreeMap<u32, Box<dyn Fn(InteractionForm) -> EffectBatch + Send + Sync>>,
@@ -253,6 +262,29 @@ impl InteractionForm {
}
}
pub const fn handlers(fingerprint: BuildFingerprint) -> HandlerRegistry {
HandlerRegistry::new(fingerprint)
}
impl InteractionRequest {
pub fn dispatch(
self,
registry: impl DispatchRegistry,
) -> Result<EffectResponse, DispatchRejection> {
registry.dispatch_form(self.form)
}
pub fn form(&self) -> &InteractionForm {
&self.form
}
}
impl From<InteractionForm> for InteractionRequest {
fn from(form: InteractionForm) -> Self {
Self { form }
}
}
impl HandlerRegistry {
pub const fn new(fingerprint: BuildFingerprint) -> Self {
Self {
@@ -303,6 +335,12 @@ impl HandlerRegistry {
}
}
impl DispatchRegistry for HandlerRegistry {
fn dispatch_form(self, form: InteractionForm) -> Result<EffectResponse, DispatchRejection> {
self.dispatch(form)
}
}
impl IntoResponse for InteractionFormRejection {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
@@ -314,6 +352,20 @@ impl IntoResponse for InteractionFormRejection {
}
}
#[async_trait]
impl<S> FromRequest<S> for InteractionRequest
where
S: Send + Sync,
{
type Rejection = InteractionFormRejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
InteractionForm::from_request(req, state)
.await
.map(|form| Self { form })
}
}
#[async_trait]
impl<S> FromRequest<S> for InteractionForm
where