axum_routing_htmx/
lib.rs

1//!
2//! ## Basic usage
3//! The following example demonstrates the basic usage of the library.
4//! On top of any regular handler, you can add the [`route`] macro to create a typed route.
5//! Any path- or query-parameters in the url will be type-checked at compile-time, and properly
6//! extracted into the handler.
7//!
8//! ```
9#![doc = include_str!("../examples/basic.rs")]
10//! ```
11//!
12//! Some valid url's as get-methods are:
13//! - `/item/1?amount=2&offset=3`
14//! - `/item/1?amount=2`
15//! - `/item/1?offset=3`
16//! - `/item/500`
17//!
18
19use std::fmt::Display;
20
21use axum::routing::MethodRouter;
22
23/// The trait expected by the Router to add HTMX routes.
24pub trait HtmxHandler<S> {
25    fn axum_router(self) -> (&'static str, MethodRouter<S>);
26}
27
28#[non_exhaustive]
29#[derive(Debug, PartialEq, Eq)]
30/// The HTTP verbs supported by HTMX.
31pub enum HtmxMethod {
32    Get,
33    Post,
34    Delete,
35    Patch,
36    Put,
37}
38
39impl Display for HtmxMethod {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        f.write_str(match self {
42            HtmxMethod::Get => "hx-get",
43            HtmxMethod::Post => "hx-post",
44            HtmxMethod::Delete => "hx-delete",
45            HtmxMethod::Patch => "hx-patch",
46            HtmxMethod::Put => "hx-put",
47        })
48    }
49}
50
51pub use axum_routing_htmx_macros::{hx_delete, hx_get, hx_patch, hx_post, hx_put};
52
53/// A trait that allows typed routes, created with the `hx_` macros to
54/// be added to an axum router.
55pub trait HtmxRouter: Sized {
56    /// The state type of the router.
57    type State: Send + Sync + Clone + 'static;
58
59    /// Add an HTMX route to the router.
60    ///
61    /// Typed handlers are functions that return [`HtmxHandler`].
62    fn htmx_route(self, handler: impl HtmxHandler<Self::State>) -> Self;
63}
64
65impl<S> HtmxRouter for axum::Router<S>
66where
67    S: Send + Sync + Clone + 'static,
68{
69    type State = S;
70
71    fn htmx_route(self, handler: impl HtmxHandler<Self::State>) -> Self {
72        let (path, method_router) = handler.axum_router();
73        self.route(path, method_router)
74    }
75}